1 /*
2 * Copyright (C) 2006 The Free Software Foundation, Inc.
3 *
4 * Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net>
5 * <http://cvsacl.sourceforge.net>
6 *
7 *
8 * You may distribute under the terms of the GNU General Public License as
9 * specified in the README file that comes with the CVS source distribution.
10 *
11 *
12 *
13 * CVS ACCESS CONTROL LIST EXTENSION
14 *
15 * It provides advanced access control definitions per modules,
16 * directories, and files on branch/tag for remote cvs repository
17 * connections.Execution of all CVS subcommands can be controlled
18 * with eight different permissions.
19 *
20 * Permission Types:
21 * - no permission (n) (1)
22 * - all permissions (a) (2)
23 * - write permission (w) (3)
24 * - tag permission (t) (4)
25 * - read permission (r) (5)
26 * - add permission (c) (6)
27 * - remove permission (d) (7)
28 * - permission change (p) (8)
29 *
30 */
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: acl.c,v 1.6 2016/05/17 14:00:09 christos Exp $");
33
34 #include "cvs.h"
35 #include "getline.h"
36 #include <pwd.h>
37 #include <grp.h>
38
39 static int acl_fileproc (void *callerdat, struct file_info *finfo);
40
41 static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos,
42 const char *update_dir, List *entries);
43
44 static int acllist_fileproc (void *callerdat, struct file_info *finfo);
45 static Dtype acllist_dirproc (void *callerdat, const char *dir,
46 const char *repos, const char *update_dir,
47 List *entries);
48
49 static void acllist_print (char *line, const char *obj);
50
51 static int racl_proc (int argc, char **argv, char *xwhere,
52 char *mwhere, char *mfile, int shorten,
53 int local_specified, char *mname, char *msg);
54
55 static FILE *open_accessfile (char *xmode, const char *repos, char **fname);
56 static FILE *open_groupfile (char *xmode);
57
58 static char *get_perms (const char *xperms);
59 static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
60
61 static char *findusername (const char *string1, const char *string2);
62 static char *findgroupname (const char *string1, const char *string2);
63 static int valid_tag (const char *part_tag, const char *tag);
64 static int valid_perm (const char *part_perms, int perm);
65 static int write_perms (const char *user, const char *perms,
66 const char *founduserpart, int foundline,
67 char *otheruserparts, const char *part_type,
68 const char *part_object, const char *part_tag, int pos,
69 const char *arepos);
70
71 static char *cache_repository;
72 static int cache_retval;
73 static int founddeniedfile;
74 static int cache_perm;
75
76 static int is_racl;
77 static int debug = 0;
78
79 int use_cvs_acl = 0;
80 char *cvs_acl_default_permissions;
81 int use_cvs_groups = 0;
82 int use_system_groups = 0;
83 int use_separate_acl_file_for_each_dir = 0;
84 char *cvs_acl_file_location = NULL;
85 char *cvs_groups_file_location = NULL;
86 char *cvs_server_run_as = NULL;
87 int stop_at_first_permission_denied = 0;
88
89 char *tag = NULL;
90
91 char *muser;
92 char *mperms;
93 static int defaultperms;
94
95 static char *default_perms_object;
96 char *default_part_perms_accessfile;
97 int aclconfig_default_used;
98
99 int acldir = 0;
100 int aclfile = 0;
101 int listacl = 0;
102
103 int userfound = 0;
104 int groupfound = 0;
105
106 /* directory depth ... */
107 char *dirs[255];
108
109 static const char *const acl_usage[] =
110 {
111 "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n",
112 "\t-R\tProcess directories recursively.\n",
113 "\t-r rev\tExisting revision/tag.\n",
114 "\t-l\tList defined ACLs.\n",
115 "(Specify the --help global option for a list of other help options)\n",
116 NULL
117 };
118
119 static const char *const racl_usage[] =
120 {
121 "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...]"
122 " [files...]\n",
123 "\t-R\tProcess directories recursively.\n",
124 "\t-r rev\tExisting revision/tag.\n",
125 "\t-l\tList defined ACLs.\n",
126 "(Specify the --help global option for a list of other help options)\n",
127 NULL
128 };
129
130
131 int
access_allowed(const char * file,const char * repos,const char * tag,int perm,char ** mline,int * mpos,int usecache)132 access_allowed (const char *file, const char *repos, const char *tag,
133 int perm, char **mline, int *mpos, int usecache)
134 {
135 int retval = 0;
136 int foundline = 0;
137 FILE *accessfp;
138
139 int flag = 1;
140
141 char *iline;
142 char *tempv;
143 char *tempc;
144 size_t tempsize;
145
146 int intcount;
147 int accessfilecount;
148 int signlevel = -1;
149 int dadmin = 0;
150
151 const char *repository;
152 char *filefullname = NULL;
153 userfound = 0;
154 groupfound = 0;
155
156 if (defaultperms)
157 {
158 repository = xstrdup ("ALL");
159 }
160 else {
161 if (strlen(repository = Short_Repository (repos)) == 0)
162 {
163 repository = xstrdup (".");
164 }
165 }
166
167 /* cache */
168 if (usecache && cache_repository != NULL &&
169 strcmp (cache_repository, repository) == 0 && !founddeniedfile
170 && perm == cache_perm)
171 return (cache_retval);
172 else
173 {
174 free (cache_repository);
175 cache_repository = xstrdup (repository);
176 cache_perm = perm;
177 }
178
179 iline = xstrdup(repository);
180
181 tempv = strtok(iline, "/\t");
182 tempc = xstrdup(tempv);
183 tempsize = ( tempc != NULL ) ? strlen(tempc) : 0;
184
185 intcount = 0;
186 /* store paths from object to cvsroot */
187 dirs[intcount] = xstrdup(tempc);
188 while ((tempv = strtok(NULL, "/\t")) != NULL)
189 {
190 intcount++;
191
192 xrealloc_and_strcat(&tempc, &tempsize, "/");
193 xrealloc_and_strcat(&tempc, &tempsize, tempv);
194
195 dirs[intcount] = xstrdup(tempc);
196 }
197
198 /* free not needed variables here */
199 free (tempv);
200 free (tempc);
201 free (iline);
202
203 /* accessfilecount will used
204 * if UseSeparateACLFile keyword is set to yes*/
205 accessfilecount = intcount;
206
207 /* if file is not null add it to dirs array */
208 if (file != NULL)
209 {
210 filefullname = Xasprintf("%s/%s", repository, file);
211 intcount++;
212 dirs[intcount] = xstrdup(filefullname);
213 }
214
215 for (; accessfilecount >= 0 && flag; accessfilecount--)
216 {
217 if (!use_separate_acl_file_for_each_dir) {
218 flag = 0;
219 accessfp = open_accessfile ("r", repository, NULL);
220 }
221 else
222 {
223 flag = 1;
224 accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
225 }
226
227 if (accessfp != NULL)
228 {
229 char *line = NULL;
230 size_t line_allocated = 0;
231
232 char *xline;
233 char *part_type = NULL;
234 char *part_object = NULL;
235 char *part_tag = NULL;
236 char *part_perms = NULL;
237
238 int x;
239
240 while (getline (&line, &line_allocated, accessfp) >= 0)
241 {
242
243 if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
244 continue;
245
246 xline = xstrdup (line);
247 part_type = strtok (line, ":\t");
248 part_object = strtok (NULL, ":\t");
249 part_tag = strtok (NULL, ":\t");
250 part_perms = strtok (NULL, ":\t");
251
252 if (part_type == NULL || part_object == NULL ||
253 part_tag == NULL || part_perms == NULL)
254 {
255 free (line);
256 error(1, 0, "access file is corrupted or has invalid"
257 " format");
258 }
259
260 if (debug) fprintf (stderr, "type %s object %s tag %s perms"
261 "%s\n", part_type, part_object, part_tag,
262 part_perms);
263 for (x = intcount; x >= signlevel && x != -1; x--)
264 {
265 if (debug) fprintf (stderr, "dirs[%d] = %s, part_object="
266 "%s\n", x, dirs[x], part_object);
267 if (strcmp (dirs[x], part_object) == 0)
268 {
269 if (debug) fprintf(stderr, "tag %s \n", tag);
270 if (valid_tag (part_tag, tag))
271 {
272 foundline = 1;
273 if (debug) fprintf(stderr, "foundline\n");
274
275 if (listacl || ((acldir || aclfile) &&
276 x == intcount) &&
277 strcmp(part_tag, tag) == 0)
278 {
279 *mline = xstrdup (xline);
280 *mpos = ftell (accessfp);
281 }
282
283 if (debug) fprintf(stderr, "perm %d\n", perm);
284 if (valid_perm (part_perms, perm))
285 {
286 if (debug) fprintf(stderr, "signlevel=%d "
287 " x=%d, aclconfig_default_used=%d\n",
288 signlevel, x, aclconfig_default_used);
289 if (signlevel == x)
290 {
291 if (strcmp(part_tag, "ALL") != 0 &&
292 !aclconfig_default_used) {
293 retval = 1;
294 if (debug) fprintf(stderr,
295 "%s, %d: %d\n", __FILE__, __LINE__,
296 retval);
297 }
298 }
299 else if (!aclconfig_default_used)
300 {
301 signlevel = x;
302 retval = 1;
303 if (debug) fprintf(stderr,
304 "%s, %d: %d\n", __FILE__, __LINE__,
305 retval);
306 }
307 else {
308 /* nothing... */
309 }
310 }
311 else
312 {
313 if (signlevel == x)
314 {
315 if (strcmp(part_tag, "ALL") != 0 &&
316 !aclconfig_default_used) {
317 retval = 0;
318 if (debug) fprintf(stderr,
319 "%s, %d: %d\n", __FILE__, __LINE__,
320 retval);
321 }
322 }
323 else if (!aclconfig_default_used)
324 {
325 signlevel = x;
326 retval = 0;
327 if (debug) fprintf(stderr,
328 "%s, %d: %d\n", __FILE__, __LINE__,
329 retval);
330
331 if (strncmp (part_type, "f", 1) == 0)
332 founddeniedfile = 1;
333 }
334 else {
335 }
336 }
337 }
338 }
339 }
340
341 if (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline,
342 groupfound, userfound);
343 if (strncmp (xline, "d:ALL:", 6) == 0 &&
344 ((!groupfound && !userfound) || listacl))
345 {
346 if (debug) fprintf (stderr, "ALL tag = %s\n", tag);
347 /* a default found */
348 if (valid_tag (part_tag, tag) > 0)
349 {
350 foundline = 1;
351
352 default_part_perms_accessfile = xstrdup (part_perms);
353
354 if (debug) fprintf (stderr, "valid perm = %d\n", perm);
355 if (valid_perm (part_perms, perm))
356 {
357 retval = 1;
358 if (debug) fprintf(stderr,
359 "%s, %d: %d\n", __FILE__, __LINE__,
360 retval);
361 if (perm == 8)
362 dadmin = 1;
363 }
364 else {
365 retval = 0;
366 if (debug) fprintf(stderr,
367 "%s, %d: %d\n", __FILE__, __LINE__,
368 retval);
369 }
370 }
371 }
372
373 }
374
375 if (fclose (accessfp) == EOF)
376 error (1, errno, "cannot close 'access' file");
377 }
378 }
379
380 if (!foundline)
381 {
382 if (debug) fprintf(stderr, "not found line\n");
383 /* DEFAULT */
384 if (valid_perm (NULL, perm)) {
385 retval = 1;
386 if (debug) fprintf(stderr,
387 "%s, %d: %d\n", __FILE__, __LINE__,
388 retval);
389 } else {
390 retval = 0;
391 if (debug) fprintf(stderr,
392 "%s, %d: %d\n", __FILE__, __LINE__,
393 retval);
394 }
395 }
396
397 /* acl admin rigths 'p' */
398 if (dadmin)
399 {
400 retval = dadmin;
401 }
402
403 cache_retval = retval;
404
405 free (filefullname);
406 /* free directories array */
407 while (intcount >= 0)
408 {
409 free (dirs[intcount]);
410 intcount--;
411 }
412
413 return retval;
414 }
415
416 /* Returns 1 if tag is valid, 0 if not */
417 static int
valid_tag(const char * part_tag,const char * tag)418 valid_tag (const char *part_tag, const char *tag)
419 {
420 int retval;
421
422 if (tag == NULL)
423 tag = "HEAD";
424
425 if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0)
426 retval = 1;
427 else
428 retval = 0;
429
430 return retval;
431 }
432
433 /* Returns 1 if successful, 0 if not. */
434 static int
valid_perm(const char * part_perms,int perm)435 valid_perm (const char *part_perms, int perm)
436 {
437 char *perms;
438 int retval = 0;
439
440 perms = get_perms (part_perms);
441
442 /* Allow, if nothing found. */
443 if (perms[0] == '\0')
444 return (1);
445
446 /* no access allowed, exit */
447 if (strstr (perms, "n"))
448 retval = 0;
449
450 if (strstr (perms, "p"))
451 /* admin rights */
452 retval = 1;
453 else if (strstr (perms, "a") && perm != 8)
454 /* all access allowed, exit */
455 retval = 1;
456 else
457 switch (perm)
458 {
459 case 3:/* write permission */
460 if (strstr (perms, "w"))
461 retval = 1;
462 break;
463 case 4:/* tag permission */
464 if (strstr (perms, "t"))
465 retval = 1;
466 break;
467 case 5:/* read permission */
468 if (strstr (perms, "w") || strstr (perms, "t") ||
469 strstr (perms, "c") || strstr (perms, "d") ||
470 strstr (perms, "r"))
471 retval = 1;
472 break;
473 case 6:/* create permission */
474 if (strstr (perms, "c"))
475 retval = 1;
476 break;
477 case 7:/* delete permission */
478 if (strstr (perms, "d"))
479 retval = 1;
480 break;
481 case 8:/* permission change */
482 if (strstr (perms, "p"))
483 retval = 1;
484 break;
485 default:/* never reached */
486 retval = 0;
487 break;
488 }
489
490 free (perms);
491
492 return (retval);
493 }
494
495 /* returns permissions found */
496 char *
get_perms(const char * part_perms)497 get_perms (const char *part_perms)
498 {
499 char *username;
500 char *xperms;
501 size_t xperms_len = 1;
502
503 FILE *groupfp;
504
505 char *founduser = NULL;
506 char *foundall = NULL;
507 int default_checked = 0;
508
509 if (debug) fprintf (stderr, "get_perms %s...", part_perms);
510 aclconfig_default_used = 0;
511
512 xperms = xmalloc (xperms_len);
513 xperms[0] = '\0';
514
515 /* use CVS_Username if set */
516 if (CVS_Username == NULL)
517 username = getcaller ();
518 else
519 username = CVS_Username;
520
521 /* no defined acl, no default acl in access file,
522 * or no access file at all */
523 if (part_perms == NULL) {
524 if (cvs_acl_default_permissions)
525 {
526 aclconfig_default_used = 1;
527 if (debug) fprintf (stderr, "default %s\n",
528 cvs_acl_default_permissions);
529 return xstrdup(cvs_acl_default_permissions);
530 }
531 else {
532 if (debug) fprintf (stderr, "early %s\n", xperms);
533 return xperms;
534 }
535 }
536
537 check_default:
538 founduser = findusername (part_perms, username);
539 foundall = strstr (part_perms, "ALL!");
540
541 if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n",
542 founduser, foundall);
543 if (founduser)
544 {
545 char *usr;
546 char *per;
547
548 usr = strtok (founduser, "!\t");
549 per = strtok (NULL, ",\t");
550
551 free(xperms);
552 xperms = xstrdup (per);
553 xperms_len = strlen (xperms);
554
555 userfound = 1;
556 free (founduser);
557 }
558 else
559 {
560 if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups);
561 if (use_system_groups) {
562 struct group *griter;
563 struct passwd *pwd;
564 gid_t gid = (pwd = getpwnam(username)) != NULL ? pwd->pw_gid : -1;
565 setgrent ();
566 while (griter = getgrent ())
567 {
568 char *userchk;
569 if (gid == griter->gr_gid) {
570 userchk = username;
571 } else {
572 char **users = griter->gr_mem;
573 int index = 0;
574 userchk = users [index++];
575 while(userchk != NULL) {
576 if(strcmp (userchk, username) == 0)
577 break;
578 userchk = users[index++];
579 }
580 }
581 if (userchk != NULL) {
582 char *grp;
583 if ((grp = findusername (part_perms, griter->gr_name)))
584 {
585 char *gperm = strtok (grp, "!\t");
586 if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n",
587 userchk, grp);
588 gperm = strtok (NULL, ",\t");
589 xrealloc_and_strcat (&xperms, &xperms_len, gperm);
590
591 groupfound = 1;
592 free (grp);
593 }
594 }
595 }
596 endgrent ();
597 }
598 else if (use_cvs_groups) {
599 groupfp = open_groupfile ("r");
600 if (groupfp != NULL)
601 {
602 char *line = NULL;
603 char *grp;
604 char *gperm;
605 int read;
606
607 size_t line_allocated = 0;
608
609 while ((read = getline (&line, &line_allocated, groupfp)) >= 0)
610 {
611 char *user;
612 if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
613 continue;
614
615 if (line[read - 1] == '\n')
616 line[--read] = '\0';
617
618 if ((grp = findgroupname (line, username)) &&
619 (user = findusername (part_perms, grp)))
620
621 {
622 gperm = strtok (user, "!\t");
623 gperm = strtok (NULL, ",\t");
624 xrealloc_and_strcat (&xperms, &xperms_len, gperm);
625 groupfound = 1;
626 free (grp);
627 free (user);
628 }
629 }
630
631 free (line);
632
633 if (fclose (groupfp) == EOF)
634 error (1, errno, "cannot close 'group' file");
635 }
636 }
637 }
638
639 if (foundall)
640 {
641 char *usr;
642 char *per;
643
644 usr = strtok (strstr (part_perms, "ALL!"), "!\t");
645 per = strtok (NULL, ",\t");
646
647 if (!default_checked)
648 default_perms_object = xstrdup (per);
649
650 if (xperms[0] == '\0')
651 {
652 xperms = xstrdup (per);
653 xperms_len = strlen (xperms);
654 }
655
656 /* You don't free pointers from strtok()! */
657 //free(usr);
658 //free(per);
659 }
660
661 if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
662 {
663 part_perms = xstrdup (default_part_perms_accessfile);
664 default_checked = 1;
665
666 goto check_default;
667 }
668
669 if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
670 {
671 if (default_perms_object)
672 xperms = xstrdup (default_perms_object);
673 else if (default_part_perms_accessfile)
674 {
675 part_perms = default_part_perms_accessfile;
676 default_checked = 1;
677 goto check_default;
678 }
679 else if (cvs_acl_default_permissions)
680 {
681 aclconfig_default_used = 1;
682 xperms = xstrdup (cvs_acl_default_permissions);
683 }
684 }
685
686 if (xperms[0] == '\0' && cvs_acl_default_permissions)
687 {
688 aclconfig_default_used = 1;
689 xperms = xstrdup (cvs_acl_default_permissions);
690 }
691
692 if (debug) fprintf (stderr, "late %s\n", xperms);
693 return xperms;
694 }
695
696
697 int
cvsacl(int argc,char ** argv)698 cvsacl (int argc, char **argv)
699 {
700 char *chdirrepository;
701 int c;
702 int err = 0;
703 int usetag = 0;
704 int recursive = 0;
705
706 int which;
707 char *where;
708
709 is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
710
711 if (argc == -1)
712 usage (is_racl ? racl_usage : acl_usage);
713
714 /* parse the args */
715 optind = 0;
716
717 while ((c = getopt (argc, argv, "dRr:l")) != -1)
718 {
719 switch (c)
720 {
721 case 'd':
722 debug++;
723 break;
724 case 'R':
725 recursive = 1;
726 break;
727 case 'r': // baris
728 tag = xstrdup (optarg);
729 break;
730 case 'l':
731 listacl = 1;
732 break;
733 case '?':
734 default:
735 usage (is_racl ? racl_usage : acl_usage);
736 break;
737 }
738 }
739
740 argc -= optind;
741 argv += optind;
742
743 if (argc < (is_racl ? 1 : 1))
744 usage (is_racl ? racl_usage : acl_usage);
745 if (listacl) {
746 if (strstr (argv[0], ":"))
747 usage (is_racl ? racl_usage : acl_usage);
748 } else {
749 if (!strstr (argv[0], ":"))
750 usage (is_racl ? racl_usage : acl_usage);
751 }
752
753
754 #ifdef CLIENT_SUPPORT
755
756 if (current_parsed_root->isremote)
757 {
758 start_server ();
759 ign_setup ();
760
761 if(recursive)
762 send_arg ("-R");
763
764 if (listacl)
765 send_arg ("-l");
766
767 if(tag)
768 {
769 option_with_arg ("-r", tag);
770 }
771
772 send_arg ("--");
773
774 if (!listacl)
775 {
776 send_arg (argv[0]);
777
778 argc--;
779 argv++;
780 }
781
782 if (is_racl)
783 {
784 int i;
785 for (i = 0; i < argc; ++i)
786 send_arg (argv[i]);
787
788 send_to_server ("racl\012",0);
789 }
790 else
791 {
792 send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
793 send_file_names (argc, argv, SEND_EXPAND_WILD);
794 send_to_server ("acl\012", 0);
795 }
796
797 return get_responses_and_close ();
798 }
799 #endif
800
801 #ifdef SERVER_SUPPORT
802
803 if (!listacl)
804 {
805 muser = strtok (argv[0], ":\t");
806 mperms = strtok (NULL, ":\t");
807
808 /* if set to 'default' */
809 if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
810 mperms = xstrdup ("x");
811
812 /* Check that the given permissions are valid. */
813 if (!given_perms_valid (mperms))
814 error (1,0,"Invalid permissions: `%s'", mperms);
815
816 argc--;
817 argv++;
818 }
819
820
821 if (!tag)
822 tag = xstrdup ("HEAD");
823
824 if (!strcasecmp (argv[0], "ALL"))
825 {
826 argv[0] = xstrdup (".");
827 defaultperms = 1;
828 if (!use_separate_acl_file_for_each_dir)
829 {
830 recursive = 0;
831 }
832
833 }
834
835 if (is_racl)
836 {
837 DBM *db;
838 int i;
839 db = open_module ();
840 for (i = 0; i < argc; i++)
841 {
842 err += do_module (db, argv[i], MISC, "ACL ing: ",
843 racl_proc, NULL, 0, !recursive, 0,
844 0, NULL);
845 }
846 close_module (db);
847 }
848 else
849 {
850 err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive,
851 NULL, NULL);
852 }
853
854 return err;
855
856 #endif
857 }
858
859 static int
racl_proc(int argc,char ** argv,char * xwhere,char * mwhere,char * mfile,int shorten,int local,char * mname,char * msg)860 racl_proc (int argc, char **argv, char *xwhere, char *mwhere,
861 char *mfile, int shorten, int local, char *mname, char *msg)
862 {
863 char *myargv[2];
864 int err = 0;
865 int which;
866 char *repository;
867 char *where;
868 char *obj;
869 size_t objlen = 0;
870
871 if (!use_cvs_acl)
872 {
873 error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'"
874 " in aclconfig file");
875 }
876
877 if (is_racl)
878 {
879 char *v;
880 repository = Xasprintf ("%s/%s", current_parsed_root->directory,
881 argv[0]);
882 where = xstrdup (argv[0]);
883
884 /* if mfile isn't null, we need to set up to do only part of the
885 * module */
886 if (mfile != NULL)
887 {
888 char *cp;
889 char *path;
890
891 /* if the portion of the module is a path, put the dir part on
892 * repos */
893 if ((cp = strrchr (mfile, '/')) != NULL)
894 {
895 *cp = '\0';
896 v = Xasprintf ("%s/%s", repository, mfile);
897 free (repository);
898 repository = v;
899 v = Xasprintf ("%s/%s", where, mfile);
900 free(where);
901 where = v;
902 mfile = cp + 1;
903 }
904
905 /* take care of the rest */
906 path = Xasprintf ("%s/%s", repository, mfile);
907 if (isdir (path))
908 {
909 /* directory means repository gets the dir tacked on */
910 free(repository);
911 repository = path;
912 v = Xasprintf ("%s/%s", where, mfile);
913 free(where);
914 where = v;
915 }
916 else
917 {
918 free (path);
919 myargv[0] = argv[0];
920 myargv[1] = mfile;
921 argc = 2;
922 argv = myargv;
923 }
924 }
925
926 /* cd to the starting repository */
927 if ( CVS_CHDIR (repository) < 0)
928 {
929 error (0, errno, "cannot chdir to %s", repository);
930 free (repository);
931 free (where);
932 return 1;
933 }
934
935 /* End section which is identical to patch_proc. */
936
937 which = W_REPOS | W_ATTIC;
938
939 if (argc > 1)
940 {
941 obj = Xasprintf ("%s/%s", repository, argv[1]);
942 }
943 else
944 {
945 obj = xstrdup(repository);
946 }
947 }
948 else
949 {
950 where = NULL;
951 repository = NULL;
952 which = W_LOCAL | W_REPOS | W_ATTIC;
953
954 obj = xstrdup (argv[1]);
955 }
956
957 if (isdir (obj))
958 acldir = 1;
959 else if (isfile (obj))
960 aclfile = 1;
961 else
962 error(1, 0, "no such file or directory");
963
964 free (obj);
965
966 if (listacl)
967 err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL,
968 NULL, argc - 1, argv + 1, local, which, 0, 0,
969 where, 1, repository);
970 else
971 err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
972 argc - 1, argv + 1, local, which, 0, 0,
973 where, 1, repository);
974
975 if (repository != NULL)
976 free (repository);
977 if (where != NULL)
978 free (where);
979
980 return err;
981 }
982
983
984 static int
acl_fileproc(void * callerdat,struct file_info * finfo)985 acl_fileproc (void *callerdat, struct file_info *finfo)
986 {
987 char *filefullname;
988 char *founduserpart = NULL;
989 char *otheruserparts = NULL;
990 size_t otherslen = 0;
991
992 const char *frepository;
993 int foundline = 0;
994
995 char *line = NULL;
996 size_t line_allocated = 0;
997 int linelen;
998
999 char *wperms;
1000 char *errmsg;
1001
1002 int pos;
1003
1004 if (!aclfile)
1005 return 0;
1006
1007 frepository = Short_Repository (finfo->repository);
1008
1009 filefullname = Xasprintf("%s/%s", frepository, finfo->file);
1010
1011
1012 if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos,
1013 0))
1014 error (1, 0, "You do not have acl admin rights on '%s'", frepository);
1015
1016 if (line != NULL)
1017 {
1018 char *part_type = NULL;
1019 char *part_object = NULL;
1020 char *part_tag = NULL;
1021 char *part_perms = NULL;
1022 char *userpart;
1023
1024 part_type = strtok (line, ":\t");
1025 part_object = strtok (NULL, ":\t");
1026 part_tag = strtok (NULL, ":\t");
1027 part_perms = strtok (NULL, ":\t");
1028
1029 foundline = 1;
1030 userpart = strtok (part_perms, ",\t");
1031
1032 do
1033 {
1034 if (strncmp (userpart, muser, strlen (muser)) == 0)
1035 founduserpart = xstrdup (userpart);
1036 else
1037 {
1038 if (otheruserparts != NULL)
1039 {
1040 xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1041 xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1042 }
1043 else
1044 {
1045 otheruserparts = xstrdup (userpart);
1046 otherslen = strlen (otheruserparts);
1047 }
1048 }
1049 } while ((userpart = strtok (NULL, ",\t")) != NULL);
1050
1051 free (userpart);
1052 }
1053
1054 wperms = make_perms (mperms, founduserpart, &errmsg);
1055 if (wperms == NULL)
1056 {
1057 if (errmsg)
1058 error (0, 0, "`%s' %s", filefullname, errmsg);
1059 }
1060 else
1061 {
1062 cvs_output ("X ", 0);
1063 cvs_output (filefullname, 0);
1064 cvs_output ("\n", 0);
1065
1066 write_perms (muser, wperms, founduserpart, foundline,
1067 otheruserparts, "f", filefullname, tag, pos,
1068 Short_Repository(finfo->repository));
1069 }
1070
1071 free (line);
1072 free (founduserpart);
1073 free (otheruserparts);
1074 free (wperms);
1075 free (filefullname);
1076
1077 return 0;
1078 }
1079
1080 static Dtype
acl_dirproc(void * callerdat,const char * dir,const char * repos,const char * update_dir,List * entries)1081 acl_dirproc (void *callerdat, const char *dir, const char *repos,
1082 const char *update_dir, List *entries)
1083 {
1084 const char *drepository;
1085 char *founduserpart = NULL;
1086 char *otheruserparts = NULL;
1087 size_t otherslen = 0;
1088 int foundline = 0;
1089
1090 char *line = NULL;
1091 size_t line_allocated = 0;
1092 int linelen;
1093
1094 int pos;
1095
1096 char *wperms;
1097 char *errmsg;
1098
1099 if (!acldir)
1100 return 0;
1101
1102 if (repos[0] == '\0')
1103 repos = Name_Repository (dir, NULL);
1104
1105 if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
1106 error (1, 0, "You do not have admin rights on '%s'",
1107 Short_Repository (repos));
1108
1109 drepository = Short_Repository (repos);
1110
1111 if (line != NULL)
1112 {
1113 char *part_type = NULL;
1114 char *part_object = NULL;
1115 char *part_tag = NULL;
1116 char *part_perms = NULL;
1117 char *userpart;
1118
1119 part_type = strtok (line, ":\t");
1120 part_object = strtok (NULL, ":\t");
1121 part_tag = strtok (NULL, ":\t");
1122 part_perms = strtok (NULL, ":\t");
1123
1124 foundline = 1;
1125 userpart = strtok (part_perms, ",\t");
1126
1127 do
1128 {
1129 if (strncmp (userpart, muser, strlen (muser)) == 0)
1130 founduserpart = xstrdup (userpart);
1131 else
1132 {
1133 if (otheruserparts != NULL)
1134 {
1135 xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1136 xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1137 }
1138 else
1139 {
1140 otheruserparts = xstrdup (userpart);
1141 otherslen = strlen (otheruserparts);
1142 }
1143 }
1144 } while ((userpart = strtok (NULL, ",\t")) != NULL);
1145 }
1146
1147 wperms = make_perms (mperms, founduserpart, &errmsg);
1148 if (wperms == NULL)
1149 {
1150 if (errmsg)
1151 error (0, 0, "`%s' %s", drepository, errmsg);
1152 }
1153 else
1154 {
1155 if (defaultperms)
1156 {
1157 cvs_output ("X ", 0);
1158 cvs_output ("ALL", 0);
1159 cvs_output ("\n", 0);
1160 write_perms (muser, wperms, founduserpart, foundline,
1161 otheruserparts, "d", "ALL", tag, pos, drepository);
1162
1163 }
1164 else
1165 {
1166 cvs_output ("X ", 0);
1167 cvs_output (drepository, 0);
1168 cvs_output ("\n", 0);
1169 write_perms (muser, wperms, founduserpart, foundline,
1170 otheruserparts, "d", drepository, tag, pos,
1171 drepository);
1172 }
1173 }
1174
1175 free (line);
1176 free (founduserpart);
1177 free (otheruserparts);
1178 free (wperms);
1179
1180 return 0;
1181 }
1182
1183 /* Open CVSROOT/access or defined CVSACLFileLocation file
1184 * Open access file In each directory if UseSeparateACLFileForEachDir=yes
1185 * returns file pointer to access file or NULL if access file not found */
1186 FILE *
open_accessfile(char * fmode,const char * adir,char ** fname)1187 open_accessfile (char *fmode, const char *adir, char **fname)
1188 {
1189 char *accessfile = NULL;
1190 FILE *accessfp;
1191
1192 if (!use_separate_acl_file_for_each_dir)
1193 {
1194 if (cvs_acl_file_location == NULL)
1195 {
1196 accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
1197 CVSROOTADM, CVSROOTADM_ACCESS);
1198 }
1199 else
1200 {
1201 accessfile = xstrdup(cvs_acl_file_location);
1202 }
1203 }
1204 else
1205 {
1206 size_t accessfilelen = 0;
1207 xrealloc_and_strcat (&accessfile, &accessfilelen,
1208 current_parsed_root->directory);
1209 xrealloc_and_strcat (&accessfile, &accessfilelen, "/");
1210 xrealloc_and_strcat (&accessfile, &accessfilelen, adir);
1211 xrealloc_and_strcat (&accessfile, &accessfilelen, "/access");
1212 }
1213
1214 accessfp = CVS_FOPEN (accessfile, fmode);
1215
1216 if (fname != NULL)
1217 *fname = xstrdup (accessfile);
1218
1219 free (accessfile);
1220
1221 return accessfp;
1222 }
1223
1224 /* Open /etc/group file if UseSystemGroups=yes in config file
1225 * Open CVSROOT/group file if UseCVSGroups=yes in config file
1226 * Open group file if specified in CVSGroupsFileLocation
1227 * returns group file pointer if UseSystemGroups=yes
1228 * returns NULL if UseSystemGroups=no or group file not found */
1229 FILE *
open_groupfile(char * fmode)1230 open_groupfile (char *fmode)
1231 {
1232 char *groupfile;
1233 FILE *groupfp;
1234
1235 if (use_cvs_groups)
1236 {
1237 if (cvs_groups_file_location != NULL)
1238 {
1239 groupfile = xstrdup (cvs_groups_file_location);
1240 }
1241 else
1242 {
1243 groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
1244 CVSROOTADM, CVSROOTADM_GROUP);
1245 }
1246 }
1247 else
1248 {
1249 return NULL;
1250 }
1251
1252 groupfp = CVS_FOPEN (groupfile, "r");
1253
1254 if (groupfp == NULL)
1255 error (0, 0, "cannot open file: %s", groupfile);
1256
1257 free (groupfile);
1258
1259 return groupfp;
1260 }
1261
1262
1263 /* Check whether given permissions are valid or not
1264 * Returns 1 if permissions are valid
1265 * Returns 0 if permissions are NOT valid */
1266 int
given_perms_valid(const char * cperms)1267 given_perms_valid (const char *cperms)
1268 {
1269 int cperms_len;
1270 int retval;
1271 int index, i;
1272
1273 if (cperms[0] == '+' || cperms[0] == '-')
1274 index = 1;
1275 else
1276 index = 0;
1277
1278 cperms_len = strlen (cperms);
1279
1280 switch (cperms[index])
1281 {
1282 case 'x':
1283 if ((cperms_len - index) == 1 && cperms_len == 1)
1284 retval = 1;
1285 else
1286 retval = 0;
1287 break;
1288 case 'n':
1289 if ((cperms_len - index) == 1 && cperms_len == 1)
1290 retval = 1;
1291 else
1292 retval = 0;
1293 break;
1294 case 'p':
1295 if ((cperms_len - index) == 1)
1296 retval = 1;
1297 else
1298 retval = 0;
1299 break;
1300 case 'a':
1301 if ((cperms_len - index) == 1)
1302 retval = 1;
1303 else
1304 retval = 0;
1305 break;
1306 case 'r':
1307 if ((cperms_len - index) == 1)
1308 retval = 1;
1309 else
1310 retval = 0;
1311 break;
1312 case 'w':
1313 if ((cperms_len - index) == 1)
1314 retval = 1;
1315 else
1316 for (i = index + 1; i < cperms_len; i++)
1317 if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1318 retval = 1;
1319 else
1320 retval = 0;
1321 break;
1322 case 't':
1323 if ((cperms_len - index) == 1)
1324 retval = 1;
1325 else
1326 for (i = index + 1; i < cperms_len; i++)
1327 if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
1328 retval = 1;
1329 else
1330 retval = 0;
1331 break;
1332 case 'c':
1333 if ((cperms_len - index) == 1)
1334 retval = 1;
1335 else
1336 for (i = index + 1; i < cperms_len; i++)
1337 if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
1338 retval = 1;
1339 else
1340 retval = 0;
1341 break;
1342 case 'd':
1343 if ((cperms_len - index) == 1)
1344 retval = 1;
1345 else
1346 for (i = index + 1; i < cperms_len; i++)
1347 if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
1348 retval = 1;
1349 else
1350 retval = 0;
1351 break;
1352 default:
1353 retval = 0;
1354 break;
1355 }
1356
1357 return retval;
1358 }
1359
1360 /* prepare permsissions string to be written to access file
1361 * returns permissions or NULL if */
1362 char *
make_perms(char * perms,char * founduserpart,char ** xerrmsg)1363 make_perms (char *perms, char *founduserpart, char **xerrmsg)
1364 {
1365 char *fperms = NULL;
1366 size_t perms_len;
1367 size_t fperms_len;
1368
1369 int i, j;
1370 int err = 0;
1371 char *errmsg = NULL;
1372
1373 char *retperms;
1374 size_t retperms_len;
1375
1376 perms_len = strlen (perms);
1377 if (perms[0] == '+' || perms[0] == '-')
1378 {
1379 retperms = xmalloc (retperms_len);
1380 retperms[0] = '\0';
1381 retperms_len = 1;
1382
1383 if (founduserpart)
1384 {
1385 char *tempfperms;
1386 size_t tempfperms_len;
1387
1388 char *temp;
1389 int per = 0;
1390 temp = strtok (founduserpart, "!\t");
1391 fperms = strtok (NULL, "!\t");
1392 fperms_len = strlen (fperms);
1393
1394 if (strncmp (fperms, "x", 1) == 0)
1395 {
1396 err = 1;
1397 if (perms[0] == '+')
1398 *xerrmsg = xstrdup ("cannot add default permission 'x'");
1399 else
1400 *xerrmsg = xstrdup ("cannot remove default permission 'x'");
1401 }
1402
1403 /* go through perms */
1404 for (i = 1; i < perms_len && !err; i++)
1405 {
1406 switch (perms[i])
1407 {
1408 case 'n':
1409 err = 1;
1410 break;
1411 case 'p':
1412 if (perms[0] == '+')
1413 fperms = xstrdup ("p");
1414 else if (perms[0] == '-')
1415 {
1416 fperms_len = 1;
1417 fperms = xmalloc (fperms_len);
1418 fperms[0] = '\0';
1419 }
1420 break;
1421 case 'a':
1422 for (j = 0; j < fperms_len; j++)
1423 {
1424 if (fperms[j] == 'p')
1425 {
1426 err = 1;
1427 *xerrmsg = xstrdup ("user have admin rights,"
1428 " cannot use +/- permissions");
1429 }
1430 else if (fperms[j] == 'a' && perms[0] == '+')
1431 {
1432 err = 1;
1433 *xerrmsg = xstrdup ("user already has all ('a')"
1434 " permission");
1435 }
1436 else if (fperms[j] != 'a' && perms[0] == '-')
1437 {
1438 err = 1;
1439 *xerrmsg = xstrdup ("user does not have all "
1440 "('a') permission");
1441 }
1442 }
1443 if (perms[0] == '+')
1444 {
1445 fperms = xstrdup ("a");
1446 fperms_len = strlen (fperms);
1447 }
1448 else if (perms[0] == '-')
1449 {
1450 fperms_len = 1;
1451 fperms = xmalloc (fperms_len);
1452 fperms[0] = '\0';
1453 }
1454 break;
1455 case 'r':
1456 for (i = 0; i < fperms_len; i++)
1457 {
1458 if (fperms[i] == 'n' && perms[0] == '+')
1459 {
1460 fperms = xstrdup ("r");
1461 fperms_len = strlen (fperms);
1462 }
1463 else if (fperms[i] == 'r' && perms[0] == '-')
1464 {
1465 fperms_len = 1;
1466 fperms = xmalloc (fperms_len);
1467 fperms[0] = '\0';
1468 }
1469 else if (perms[0] == '-')
1470 {
1471 err = 1;
1472 *xerrmsg = xstrdup ("user has other permissions,"
1473 " cannot remove read ('r')"
1474 " permission");
1475 }
1476 else
1477 {
1478 err = 1;
1479 *xerrmsg = xstrdup ("user has other permissions,"
1480 " cannot remove read ('r')"
1481 " permission");
1482 }
1483 }
1484 break;
1485 case 'w':
1486 {
1487 tempfperms_len = 1;
1488
1489 tempfperms = xmalloc (tempfperms_len);
1490 tempfperms[0] = '\0';
1491
1492 for (j = 0; j < fperms_len; j++)
1493 {
1494 if (fperms[j] == 't' || fperms[j] == 'c' ||
1495 fperms[j] == 'd')
1496 {
1497 char *temp;
1498 temp = xmalloc (2);
1499 temp[0] = fperms[j];
1500 temp[1] = '\0';
1501
1502 xrealloc_and_strcat (&tempfperms,
1503 &tempfperms_len, temp);
1504 free (temp);
1505 }
1506 else if (fperms[j] == 'a' || fperms[j] == 'p')
1507 {
1508 err = 1;
1509 *xerrmsg = xstrdup ("user has higher"
1510 " permissions, cannot use"
1511 " +/- write permissions");
1512 }
1513 else if (fperms[j] == 'n' || fperms[j] == 'r')
1514 {
1515 if (perms[0] == '-')
1516 {
1517 err = 1;
1518 *xerrmsg = xstrdup ("user does not have"
1519 " write ('w')"
1520 " permission");
1521 }
1522 }
1523 else if (fperms[j] == 'w')
1524 {
1525 per = 1;
1526 if (perms[0] == '+') {
1527 err = 1;
1528 *xerrmsg = xstrdup ("user already have"
1529 " write ('w')"
1530 "permission");
1531 }
1532 }
1533 }
1534
1535 fperms = tempfperms;
1536 fperms_len = strlen (fperms);
1537
1538 if (!per && !err && (perms[0] == '-')) {
1539 err = 1;
1540 *xerrmsg = xstrdup ("user does not have write"
1541 " ('w') permission");
1542 }
1543
1544 if (perms[0] == '+')
1545 {
1546 xrealloc_and_strcat (&fperms, &fperms_len, "w");
1547 }
1548 }
1549 break;
1550 case 't':
1551 {
1552 tempfperms_len = 1;
1553
1554 tempfperms = xmalloc (tempfperms_len);
1555 tempfperms[0] = '\0';
1556
1557 for (j = 0; j < fperms_len; j++)
1558 {
1559 if (fperms[j] == 'w' || fperms[j] == 'c' ||
1560 fperms[j] == 'd')
1561 {
1562 char *temp;
1563 temp = xmalloc (2);
1564 temp[0] = fperms[j];
1565 temp[1] = '\0';
1566
1567 xrealloc_and_strcat (&tempfperms,
1568 &tempfperms_len, temp);
1569 free (temp);
1570 }
1571 else if (fperms[j] == 'a' || fperms[j] == 'p')
1572 {
1573 err = 1;
1574 *xerrmsg = xstrdup ("user has higher"
1575 " permissions, cannot use"
1576 " +/- tag permissions");
1577 }
1578 else if (fperms[j] == 'n' || fperms[i] == 'r')
1579 {
1580 if (perms[0] == '-')
1581 *xerrmsg = xstrdup ("user does not have tag"
1582 " ('t') permission");
1583 }
1584 else if (fperms[j] == 't')
1585 {
1586 per = 1;
1587 if (perms[0] == '+')
1588 {
1589 err = 1;
1590 *xerrmsg = xstrdup ("user already have tag"
1591 " ('t') permission");
1592 }
1593 }
1594 }
1595
1596 fperms = tempfperms;
1597 fperms_len = strlen (fperms);
1598
1599 if (!per && !err && (perms[0] == '-'))
1600 {
1601 err = 1;
1602 *xerrmsg = xstrdup ("user does not have tag ('t')"
1603 " permission");
1604 }
1605
1606 if (perms[0] == '+')
1607 {
1608 xrealloc_and_strcat (&fperms, &fperms_len, "t");
1609 }
1610 }
1611 break;
1612 case 'c':
1613 {
1614 tempfperms_len = 1;
1615
1616 tempfperms = xmalloc (tempfperms_len);
1617 tempfperms[0] = '\0';
1618
1619 for (j = 0; j < fperms_len; j++)
1620 {
1621 if (fperms[j] == 'w' || fperms[j] == 't' ||
1622 fperms[j] == 'd')
1623 {
1624 char *temp;
1625 temp = xmalloc (2);
1626 temp[0] = fperms[j];
1627 temp[1] = '\0';
1628
1629 xrealloc_and_strcat (&tempfperms,
1630 &tempfperms_len, temp);
1631 free (temp);
1632 }
1633 else if (fperms[j] == 'a' || fperms[j] == 'p')
1634 {
1635 err = 1;
1636 *xerrmsg = xstrdup ("user has higher"
1637 " permissions, cannot use"
1638 " +/- create permissions");
1639 }
1640 else if (fperms[j] == 'n' || fperms[i] == 'r')
1641 {
1642 if (perms[0] == '-')
1643 err = 1;
1644 *xerrmsg = xstrdup ("user does not have create"
1645 " ('c') permission");
1646 }
1647 else if (fperms[j] == 'c')
1648 {
1649 per = 1;
1650 if (perms[0] == '+') {
1651 err = 1;
1652 *xerrmsg = xstrdup ("user already have"
1653 " create ('c')"
1654 " permission");
1655 }
1656 }
1657 }
1658
1659 fperms = tempfperms;
1660 fperms_len = strlen (fperms);
1661
1662 if (!per && !err && (perms[0] == '-')) {
1663 err = 1;
1664 *xerrmsg = xstrdup ("user does not have create"
1665 " ('c') permission");
1666 }
1667
1668 if (perms[0] == '+')
1669 {
1670 xrealloc_and_strcat (&fperms, &fperms_len, "c");
1671 }
1672 }
1673 break;
1674 case 'd':
1675 {
1676 tempfperms_len = 1;
1677
1678 tempfperms = xmalloc (tempfperms_len);
1679 tempfperms[0] = '\0';
1680
1681 for (j = 0; j < fperms_len; j++)
1682 {
1683 if (fperms[j] == 'w' || fperms[j] == 'c' ||
1684 fperms[j] == 't')
1685 {
1686 char *temp;
1687 temp = xmalloc (2);
1688 temp[0] = fperms[j];
1689 temp[1] = '\0';
1690
1691 xrealloc_and_strcat (&tempfperms,
1692 &tempfperms_len, temp);
1693 free (temp);
1694 }
1695 else if (fperms[j] == 'a' || fperms[j] == 'p')
1696 {
1697 err = 1;
1698 *xerrmsg = xstrdup ("user has higher"
1699 " permissions, cannot use"
1700 " +/- delete permissions");
1701 }
1702 else if (fperms[j] == 'n' || fperms[i] == 'r')
1703 {
1704 if (perms[0] == '-')
1705 err = 1;
1706 *xerrmsg = xstrdup ("user does not have delete"
1707 " ('d') permission");
1708 }
1709 else if (fperms[j] == 'd')
1710 {
1711 per = 1;
1712 if (perms[0] == '+') {
1713 err = 1;
1714 *xerrmsg = xstrdup ("user already have"
1715 " delete ('d')"
1716 " permission");
1717 }
1718 }
1719 }
1720
1721 fperms = tempfperms;
1722 fperms_len = strlen (fperms);
1723
1724 if (!per && !err && (perms[0] == '-')) {
1725 err = 1;
1726 *xerrmsg = xstrdup ("user does not have delete"
1727 " ('d') permission");
1728 }
1729
1730 if (perms[0] == '+')
1731 {
1732 xrealloc_and_strcat (&fperms, &fperms_len, "d");
1733 }
1734 }
1735 break;
1736 default:
1737 err = 1;
1738 *xerrmsg = xstrdup ("error in 'access' file format");
1739 break;
1740 }
1741
1742 if (fperms[0] == '\0')
1743 retperms = xstrdup ("none");
1744 else
1745 retperms = xstrdup (fperms);
1746 }
1747 }
1748 else
1749 {
1750 err = 1;
1751 *xerrmsg = xstrdup("user is not given any permissions to remove/add");
1752 }
1753 }
1754 else
1755 {
1756 retperms = xstrdup (perms);
1757 }
1758 if (fperms)
1759 free (fperms);
1760 if (err && retperms)
1761 free (retperms);
1762
1763 return (err ? NULL : retperms);
1764 }
1765
1766 /* prepare and write resulting permissions to access file */
1767 static int
write_perms(const char * user,const char * perms,const char * founduserpart,int foundline,char * otheruserparts,const char * part_type,const char * part_object,const char * part_tag,int pos,const char * arepos)1768 write_perms (const char *user, const char *perms, const char *founduserpart,
1769 int foundline, char *otheruserparts,
1770 const char *part_type, const char *part_object,
1771 const char *part_tag, int pos, const char *arepos)
1772 {
1773 char *accessfile;
1774 char *tmpaccessout;
1775 FILE *accessfpin;
1776 FILE *accessfpout;
1777
1778 char *newline = NULL;
1779 size_t newlinelen = 1;
1780 char *object;
1781
1782 char *line = NULL;
1783 size_t line_allocated = 0;
1784
1785 newline = xmalloc (newlinelen);
1786 newline[0] = '\0';
1787
1788 if (!strcasecmp (part_tag, "ALL"))
1789 part_tag = "ALL";
1790
1791 /* strip any trailing slash if found */
1792 object = xstrdup (part_object);
1793 if (object[strlen (object) - 1] == '/')
1794 object[strlen (object) - 1] = '\0';
1795
1796 /* first parts, part type, object, and tag */
1797 xrealloc_and_strcat (&newline, &newlinelen, part_type);
1798 xrealloc_and_strcat (&newline, &newlinelen, ":");
1799 xrealloc_and_strcat (&newline, &newlinelen, object);
1800 xrealloc_and_strcat (&newline, &newlinelen, ":");
1801 xrealloc_and_strcat (&newline, &newlinelen, part_tag);
1802 xrealloc_and_strcat (&newline, &newlinelen, ":");
1803
1804 if (strncmp (perms, "none", 4) != 0)
1805 {
1806 xrealloc_and_strcat (&newline, &newlinelen, user);
1807 xrealloc_and_strcat (&newline, &newlinelen, "!");
1808 xrealloc_and_strcat (&newline, &newlinelen, perms);
1809 if (otheruserparts != NULL)
1810 xrealloc_and_strcat (&newline, &newlinelen, ",");
1811 }
1812
1813 if (otheruserparts != NULL)
1814 {
1815 if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
1816 otheruserparts[strlen (otheruserparts) - 1] = '\0';
1817
1818 xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
1819 }
1820
1821 xrealloc_and_strcat (&newline, &newlinelen, ":");
1822
1823 if (foundline)
1824 {
1825 accessfpout = cvs_temp_file (&tmpaccessout);
1826 if (accessfpout == NULL)
1827 error (1, errno, "cannot open temporary file: %s", tmpaccessout);
1828
1829 accessfpin = open_accessfile ("r", arepos, &accessfile);
1830 if (accessfpout == NULL)
1831 error (1, errno, "cannot open access file: %s", accessfile);
1832
1833 while (getline (&line, &line_allocated, accessfpin) >= 0)
1834 {
1835 if (pos != ftell (accessfpin))
1836 {
1837 if (fprintf (accessfpout, "%s", line) < 0)
1838 error (1, errno, "writing temporary file: %s", tmpaccessout);
1839 }
1840 else
1841 {
1842 if (fprintf (accessfpout, "%s\n", newline) < 0)
1843 error (1, errno, "writing temporary file: %s", tmpaccessout);
1844 }
1845
1846 }
1847 if (fclose (accessfpin) == EOF)
1848 error (1, errno, "cannot close access file: %s", accessfile);
1849
1850 if (fclose (accessfpout) == EOF)
1851 error (1, errno, "cannot close temporary file: %s", tmpaccessout);
1852
1853 if (CVS_UNLINK (accessfile) < 0)
1854 error (0, errno, "cannot remove %s", accessfile);
1855
1856 copy_file (tmpaccessout, accessfile);
1857
1858 if (CVS_UNLINK (tmpaccessout) < 0)
1859 error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
1860 }
1861 else
1862 {
1863 accessfpout = open_accessfile ("r+", arepos, &accessfile);
1864
1865 if (accessfpout == NULL)
1866 {
1867 if (existence_error (errno))
1868 {
1869 accessfpout = open_accessfile ("w+", arepos, &accessfile);
1870 }
1871 if (accessfpout == NULL)
1872 error (1, errno, "cannot open access file: %s", accessfile);
1873 }
1874 else {
1875 if (fseek (accessfpout, 0, 2) != 0)
1876 error (1, errno, "cannot fseek access file: %s", accessfile);
1877 }
1878
1879 if (fprintf (accessfpout, "%s\n", newline) < 0)
1880 error (1, errno, "writing access file: %s", accessfile);
1881
1882 if (fclose (accessfpout) == EOF)
1883 error (1, errno, "cannot close access file: %s", accessfile);
1884 }
1885
1886 free (line);
1887 free (newline);
1888
1889 chmod (accessfile, 0644);
1890
1891 return 0;
1892 }
1893
1894 static int
acllist_fileproc(void * callerdat,struct file_info * finfo)1895 acllist_fileproc (void *callerdat, struct file_info *finfo)
1896 {
1897 char *filefullname;
1898 const char *frepository;
1899 char *line = NULL;
1900 int pos;
1901
1902 if (!aclfile)
1903 return 0;
1904
1905 frepository = Short_Repository (finfo->repository);
1906
1907 filefullname = Xasprintf("%s/%s", frepository, finfo->file);
1908
1909 /* check that user, which run acl/racl command, has admin permisson,
1910 * and also return the line with permissions from access file. */
1911 if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos,
1912 0))
1913 error (1, 0, "You do not have admin rights on '%s'", frepository);
1914
1915 acllist_print (line, filefullname);
1916
1917 free (filefullname);
1918
1919 return 0;
1920 }
1921
1922 static Dtype
acllist_dirproc(void * callerdat,const char * dir,const char * repos,const char * update_dir,List * entries)1923 acllist_dirproc (void *callerdat, const char *dir, const char *repos,
1924 const char *update_dir, List *entries)
1925 {
1926 char *line = NULL;
1927 const char *drepository;
1928 int pos;
1929
1930 if (repos[0] == '\0')
1931 repos = Name_Repository (dir, NULL);
1932
1933 if (!acldir)
1934 return 0;
1935
1936 drepository = Short_Repository (repos);
1937
1938 /* check that user, which run acl/racl command, has admin permisson,
1939 * and also return the line with permissions from access file. */
1940 if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
1941 error (1, 0, "You do not have admin rights on '%s'", drepository);
1942
1943 acllist_print (line, drepository);
1944
1945 return 0;
1946 }
1947
1948 /* Prints permissions to screen with -l option */
1949 void
acllist_print(char * line,const char * obj)1950 acllist_print (char *line, const char *obj)
1951 {
1952 char *temp;
1953 int c = 0;
1954 int def = 0;
1955
1956 char *printedusers[255];
1957 printedusers[0] = NULL;
1958
1959 if (line != NULL)
1960 {
1961 temp = strtok (line, ":\t");
1962
1963 if (acldir)
1964 cvs_output ("d ", 0);
1965 else if (aclfile)
1966 cvs_output ("f ", 0);
1967
1968 temp = strtok (NULL, ":\t");
1969
1970 cvs_output(obj, 0);
1971 cvs_output (" | ", 0);
1972
1973 temp = strtok (NULL, ":\t");
1974 cvs_output (temp, 0);
1975 cvs_output (" | ", 0);
1976
1977 while ((temp = strtok (NULL, "!\t")) != NULL)
1978 {
1979 if (strncmp (temp, ":", 1) == 0)
1980 break;
1981
1982 if (strcmp (temp, "ALL") == 0)
1983 {
1984 temp = strtok (NULL, ",\t");
1985 continue;
1986 }
1987
1988 cvs_output (temp, 0);
1989 cvs_output (":", 0);
1990
1991 while (printedusers[c] != NULL)
1992 c++;
1993
1994 printedusers[c] = xstrdup (temp);
1995 c++;
1996 printedusers[c] = NULL;
1997
1998 temp = strtok (NULL, ",\t");
1999
2000 if (temp != NULL && temp[strlen (temp) - 2] == ':')
2001 temp[strlen (temp) - 2] = '\0';
2002
2003 cvs_output (temp, 0);
2004 cvs_output (" ", 0);
2005 }
2006
2007 if (default_perms_object)
2008 {
2009 cvs_output ("| defaults ", 0);
2010 cvs_output ("ALL:", 0);
2011 cvs_output (default_perms_object, 0);
2012 def = 1;
2013 }
2014 if (default_part_perms_accessfile)
2015 {
2016 size_t i;
2017 i = strlen (default_part_perms_accessfile);
2018 xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
2019
2020 free (line);
2021 line = xstrdup (default_part_perms_accessfile);
2022
2023 if (!def)
2024 cvs_output ("| defaults ", 0);
2025 else
2026 cvs_output (" ", 0);
2027
2028 temp = strtok (line, "!\t");
2029 cvs_output (temp, 0);
2030 cvs_output (":", 0);
2031
2032 temp = strtok (NULL, ",\t");
2033
2034 cvs_output (temp, 0);
2035 cvs_output (" ", 0);
2036
2037 while ((temp = strtok (NULL, "!\t")) != NULL)
2038 {
2039 int printed = 0;
2040 int c2 = 0;
2041 while (printedusers[c2] != NULL && printed == 0)
2042 {
2043 if (strcmp (printedusers[c2], temp) == 0)
2044 {
2045 printed = 1;
2046 break;
2047 }
2048 c2++;
2049 }
2050
2051 if (printed == 0)
2052 {
2053 cvs_output (temp, 0);
2054 cvs_output (":", 0);
2055 }
2056
2057 temp = strtok (NULL, ",\t");
2058
2059 if (temp[strlen (temp) - 2] == ':')
2060 temp[strlen (temp) - 2] = '\0';
2061
2062 if (printed == 0)
2063 {
2064 cvs_output (temp, 0);
2065 cvs_output (" ", 0);
2066 }
2067 }
2068 def = 1;
2069 }
2070 else if (cvs_acl_default_permissions)
2071 {
2072 cvs_output ("| defaults ", 0);
2073 cvs_output ("ALL: ", 0);
2074 cvs_output (cvs_acl_default_permissions, 0);
2075 }
2076 }
2077 else
2078 {
2079 if (acldir)
2080 cvs_output ("d ", 0);
2081 else if (aclfile)
2082 cvs_output ("f ", 0);
2083 cvs_output (obj, 0);
2084 cvs_output (" | ", 0);
2085 cvs_output (tag, 0);
2086 cvs_output (" | ", 0);
2087
2088 if (default_perms_object)
2089 {
2090 cvs_output ("| defaults ", 0);
2091 cvs_output ("ALL:", 0);
2092 cvs_output (default_perms_object, 0);
2093 def = 1;
2094 }
2095 if (default_part_perms_accessfile)
2096 {
2097 free (line);
2098 line = xstrdup (default_part_perms_accessfile);
2099
2100 if (!def)
2101 cvs_output ("| defaults ", 0);
2102 else
2103 cvs_output (" ", 0);
2104
2105 temp = strtok (line, "!\t");
2106 cvs_output (temp, 0);
2107 cvs_output (":", 0);
2108
2109 temp = strtok (NULL, ",\t");
2110
2111 if (temp[strlen (temp) - 2] == ':')
2112 temp[strlen (temp) - 2] = '\0';
2113
2114 cvs_output (temp, 0);
2115 cvs_output (" ", 0);
2116
2117 while ((temp = strtok (NULL, "!\t")) != NULL)
2118 {
2119 cvs_output (temp, 0);
2120 cvs_output (":", 0);
2121
2122 if ((temp = strtok (NULL, ",\t")) != NULL)
2123 {
2124 if (temp[strlen (temp) - 2] == ':')
2125 temp[strlen (temp) - 2] = '\0';
2126
2127 cvs_output (temp, 0);
2128 cvs_output (" ", 0);
2129 }
2130 }
2131 cvs_output ("\n", 0);
2132 }
2133 else if (cvs_acl_default_permissions)
2134 {
2135 cvs_output ("| defaults ", 0);
2136 cvs_output ("ALL: ", 0);
2137 cvs_output (cvs_acl_default_permissions, 0);
2138 }
2139 else
2140 cvs_output ("default:p (no perms)", 0);
2141 }
2142 cvs_output ("\n", 0);
2143
2144 while (c >= 0) {
2145 free (printedusers[c]);
2146 c--;
2147 }
2148
2149 free (line);
2150 }
2151
2152 /* find username
2153 * returns username with its permissions if user found
2154 * returns NULL if user not found */
findusername(const char * string1,const char * string2)2155 char *findusername (const char *string1, const char *string2)
2156 {
2157 char *tmp1, *tmp2;
2158
2159 if (string1 != NULL && string2 != NULL)
2160 {
2161 tmp1 = xstrdup (string1);
2162 tmp2 = strtok (tmp1, ",\t");
2163
2164 do
2165 {
2166 if (strncmp (tmp2, string2, strlen (string2)) == 0 &&
2167 tmp2[strlen (string2)] == '!')
2168 {
2169 tmp2 = xstrdup (tmp2);
2170 free (tmp1);
2171 return tmp2;
2172 }
2173 tmp2 = strtok (NULL, ",\t");
2174 }
2175 while (tmp2 != NULL);
2176
2177 free (tmp1);
2178
2179 return NULL;
2180 }
2181 else
2182 return NULL;
2183 }
2184
2185 /* find user name in group file
2186 * returns group name if user found
2187 * returns NULL if user not found */
findgroupname(const char * string1,const char * string2)2188 char *findgroupname (const char *string1, const char *string2)
2189 {
2190 char *tmp1, *tmp2;
2191 char *grpname;
2192
2193 if (string1 != NULL && string2 != NULL)
2194 {
2195 tmp1 = xstrdup (string1);
2196 grpname = strtok (tmp1, ":\t");
2197
2198 while (tmp2 = strtok(NULL, ",\t"))
2199 {
2200 if (strcmp (tmp2, string2) == 0)
2201 {
2202 grpname = xstrdup (grpname);
2203 free (tmp1);
2204 return grpname;
2205 }
2206 }
2207
2208 free (tmp1);
2209
2210 return NULL;
2211 }
2212 else
2213 return NULL;
2214 }
2215