1 diff -urN cvs-1.11.17.orig/aclconfig.default cvs-1.11.17/aclconfig.default
2 --- cvs-1.11.17.orig/aclconfig.default 1970-01-01 01:00:00.000000000 +0100
3 +++ cvs-1.11.17/aclconfig.default 2004-06-17 14:33:44.000000000 +0200
5 +# Set `UseCVSACL' to yes to use CVS ACL feature.
8 +# Default CVS ACL Permission are to use.
9 +#CVSACLDefaultPermissions=a
11 +# Default file location for CVS ACL file (access) is CVSROOT/access.
12 +# If you want to use a different location, define it below.
13 +#CVSACLFileLocation=/path/to/cvs/access
15 +# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).
18 +# Set `UseCVSGroups' to yes to use another group file.
21 +# Default file location for CVS groups file is CVSROOT/group.
22 +# If you want to use a different location, define it below.
23 +#CVSGroupsFileLocation=/path/to/cvs/group
25 +# Set UseSeparateACLFileForEachDir to yes in order to use a
26 +# separate 'access' file for each directory.
27 +# This increased the performance if you have really big repository.
28 +#UseSeparateACLFileForEachDir=no
30 +# If StopAtFirstPermissionDenied is set to yes
31 +# operation will stop at first permission denied message.
33 +#StopAtFirstPermissionDenied=no
35 +# Set CVSServerRunAsUser to a system user, in order CVS server
37 +#CVSServerRunAsUser=runascvsuser
38 diff -urN cvs-1.11.17.orig/INSTALL.cvsacl cvs-1.11.17/INSTALL.cvsacl
39 --- cvs-1.11.17.orig/INSTALL.cvsacl 1970-01-01 01:00:00.000000000 +0100
40 +++ cvs-1.11.17/INSTALL.cvsacl 2004-06-25 07:39:24.000000000 +0200
45 +- copy the file acl.c under src directory of CVS source distribution.
46 + "cp acl.c /path/to/cvs-1.11.17/src/"
47 +- copy the patch file cvsacl-patch-1.2.1 under CVS source distribution
49 + "cp cvsacl-patch-1.2.1 /path/to/cvs-1.11.17/"
50 +- cd to CVS source directory.
51 + "cd /path/to/cvs-1.11.17/"
53 + "patch -p0 < cvsacl-patch-1.2.1"
54 +- if you are initializing the repository after applying patch, related
55 + config files will be created with init command.
56 + "cvs -d /path/to/repository init"
57 +- if you already have a repository, you have to add the aclconfig file
58 + to your $CVSROOT/CVSROOT/. aclconfig.default is the default configuration
59 + file, you can rename it to aclconfig, and use it .
60 +- modify aclconfig file, if you need to change some options.
61 +- as the last step, you have to define yourself as acl administrator.
62 + "cvs -d /path/to/repository racl yourname:p -r ALL -d ALL"
63 + this command gives p (acl admin) rights to user (yourname),
64 + on all repository and tags/branches.
65 diff -urN cvs-1.11.17.orig/README.cvsacl cvs-1.11.17/README.cvsacl
66 --- cvs-1.11.17.orig/README.cvsacl 1970-01-01 01:00:00.000000000 +0100
67 +++ cvs-1.11.17/README.cvsacl 2004-06-25 07:39:30.000000000 +0200
70 +CVS Access Control List Extension Patch
72 +http://cvsacl.sourceforge.net/
73 +sbaris@users.sourceforge.net
75 +CVSACL is a patch for CVS. It adds two new subcommands
76 +(acl & racl) to cvs for access control list management. It
77 +provides advanced ACL definitions per modules, directories,
78 +and files on branch/tag for remote cvs repository connections.
79 +Execution of all CVS subcommands can be controlled with eight
80 +different permissions.
81 +ACL definitions works for only remote connections, local users
82 +can access and modify repository, if unix file system permissions
83 +allow. If you want all users to make remote connections to
84 +repository, and not allow local users to access repository, you
85 +have to set CVSServerRunAsUser keyword in aclconfig file
87 +Still local users can use acl and racl subcommands to set
88 +permissions on directories or files if they have acl admin rights (p)
89 +on related directories or files.
90 +So, in order to control all access to repository with this ACL
91 +extension, you should use CVSServerRunAsUser keyword and force all
92 +users to make remote connections. CVS repository administrator or
93 +project managers have to use acl and racl subcommands to manage
94 +permissions. But there is no gui client supporting these subcommands,
95 +so you have to use cvs client itself either locally or remotely.
103 + Command line character: n
104 + If a user given n permission, it is not allowed for any action on repository.
106 + Command line character: r
107 + r permission gives only read access on repository.
108 + With r permission you are allowed to run cvs subcommands: annotate,
109 + checkout, diff, export, log, rannotate, rdiff, rlog, status.
111 + Command line character: w
112 + w permission allows only cvs commit/checkin action.
113 + With w permission, you are not allowed to add/remove any file to/from
114 + repository, other permissions should be defines for that.
116 + Command line character: t
117 + t permission allows cvs tag and rtag subcommands to run, so you may
118 + control tagging and untagging operations. t permission includes r
119 + permission, since without reading you can not tag/untag a file.
120 + However t permission does not include write permission, you can not
121 + commit a file with only t permission.
123 + Command line character: c
124 + c permission allows cvs add and import subcommands to run. To add or
125 + import a file/directory to repository, you have to given a c
126 + permission. Again, c permission does not include write permission,
127 + thus you may only add or import files, but you can not modify any
128 + existing file. After issuing add subcommand, you have to commit the file
129 + to complete adding. This commit subcommand is allowed because you are
130 + adding file and not modifying existing one.
132 + Command line character: d
133 + d permission allows cvs remove command to run. To remove a file/directory
134 + from repository, d permission have to set. It does not include write
135 + permission, so you can not modify contents of an existing file on repository.
136 +- full access except admin rights
137 + Command line character: a
138 + a permission gives all access (above permissions) to repository, but it
139 + can not modify permissions. Only acl admins may modify the acl definitions.
141 + Command line character: p
142 + p permission means that user is an acl admin, so it is allowed to make anything on repository.
146 +The administrative file aclconfig contains miscellaneous settings which
147 +affect the behaviour of ACL extension. Currently defined keywords are:
150 +Use ACL definitions if set to yes. If you do not want to use ACLs for
151 +some repositories in a patched CVS server, set this keyword to no. The default is no.
153 +UseCVSACLDefaultPermissions=value
154 +Value can be any combination of valid permission types (w,r,t,c,d,t,a,p).
155 +if there is no defined ACL and default permission in access file, or no
156 +access file at all, this permissions are used. The default is p (admin rights),
157 +if aclconfig file is created with cvs init.
160 +CVS does not have a CVSROOT/passwd file. However it can be created manually
161 +(format should be same as /etc/group). If value set to yes, CVS checks for
162 +groups in file $CVSROOT/CVSROOT/group The default value is no.
164 +UseSystemGroups=value
165 +Group memberships for users are checked in file /etc/group, if value is set
166 +to yes. The default value is no.
168 +CVSACLFileLocation=value
169 +Originally access file is put under CVSROOT/CVSROOT, if you want a different
170 +location, set value to a valid path. The default value is $CVSROOT/CVSROOT/access.
172 +CVSGroupsFileLocation=value
173 +IF UseCVSGroups is set to yes, CVS looks for a group file under $CVSROOT/CVSROOT.
174 +To use a different location for group file set value to a valid path to group.
175 +The default value is $CVSROOT/CVSROOT/group.
177 +UseSeparateACLFileForEachDir=value
178 +If value is set to yes, a separate ACL file (access) is created for each
179 +directory in repository. If you have a really big repository
180 +(directories>10,000 and files>100,000), performance may drop due to a big
181 +acl file, access. Setting the value to yes, may increase performance. Normally,
182 +you will not need this. The default value is no.
184 +StopAtFirstPermissionDenied=value
185 +If StopAtFirstPermissionDenied is set to yes
186 +operation will stop at first permission denied message.
187 +e.g. when you send commit command for a directory, if you dont
188 +have write permission for just one file under the directory,
189 +by default you will have a warning and commit will continue
190 +on the other files. If you set this keyword to 'no', then
191 +commit operation will be stopped when inaccassable file found.
194 +CVSServerRunAsUser=value
195 +Set CVSServerRunAsUser keyword to a valid system user.
196 +When a user make a remote connection to CVS, after successfull authentication
197 +cvs process switch to run as that user, or defined system user in
198 +$CVSROOT/CVSROOT/passwd. So, you also have to set unix file permissions accordingly.
200 +Add a user and group such as both cvsadm.
201 +Set CVSServerRunAsUser keyword to cvsadm.
202 +Change unix file system permissions for your repository,
203 +make cvsadm user and group owner, and read,write,execute permissions and setgid.
204 +(chown cvsadm -R /path/to/your/repository)
205 +(chgrp cvsadm -R /path/to/your/repository)
206 +(chmod 2770 -R /path/to/your/repository)
207 +Add yourself to cvsadm group (since you are ACL administrator).
208 +Therefore, only users making remote connections will have access to repository
209 +if you give rights. Local users can not access to repository via a cvs client or directly.
212 +Command Line Usage Information
213 +acl command is used on checked out files or directories. racl command is
214 +used on repository without a working copy. Usage information can be obtained
215 +with standard cvs --help command.
216 +Output of cvs --help acl and cvs --help racl:
218 +Usage: cvs racl [user||group:permissions] [-Rl] [-r tag]
219 + -d [directory] -f [file]
220 + -R Process directories recursively.
221 + -r rev Existing revision/tag.
222 + -l List defined ACLs.
223 + -d dir Process on given directory.
224 + -f file Process on given file.
226 +Usage: cvs acl [user||group:permissions] [-Rl] [-r tag]
227 + -d [directory] -f [file]
228 + -R Process directories recursively.
229 + -r rev Existing revision/tag.
230 + -l List defined ACLs.
231 + -d dir Process on given directory.
232 + -f file Process on given file.
234 +You may directly set permissions for a user or group or add/remove
235 +permissions with + and - signs to/from existing permissions.
236 +If you do not give the branch/tag information, default value of HEAD
237 +(main branch) will be used. You have to give branch/tag name with -r option.
238 +You may type ALL for branch/tag field.
240 +While checking for permissions, it goes thorough the list below. So the highest
241 +significant permission is the first item in list.
243 +- permissions assigned to username for specific directory or file.
244 +- permissions assigned to group name for specific directory or file.
245 +- permissions as defaults for specific directory or file.
246 +- permissions assigned to parent folders (inherits from the first parent
247 + which permissions are assigned).
248 +- permissions as repository defaults.
249 +- permissions in aclconfig file.
279 +We have above directory structure for a cvs repository, and no defined permissions.
281 +Setting main default permissions:
283 +$ cvs -d /cvs/projectA racl cvsadmin:p -r ALL -d ALL
284 +$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
285 +User cvsadmin will be an acl admin, and all other users will have only read
286 +rights on all branches/tags in projectA repository. This is the default acl
287 +definition and it overwrites default permissions in $CVSROOT/CVSROOT/aclconfig file.
289 +$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
290 +$ cvs -d /cvs/projectA racl ALL:n -r ALL -d gui
291 +After executing these two commands, all users will have read access on all
292 +directories and files except gui directory. Everyone will be denied to access to gui
293 +directory becase no access, n, permissions is set.
295 +Setting permissions directly on a file or directory:
297 +$ cvs -d /cvs/projectA racl userX:wcd -d lib
298 +$ cvs -d /cvs/projectA racl group1:w -d lib
299 +First command will set write, create, and delete permissions for userX on directory
300 +lib with branch HEAD (since no branch/tag information given, branch defaults to HEAD).
301 +Second command will set only write permission for group1 on directory lib with branch HEAD.
302 +Members of group1 will have only commit rights on lib directory, branch HEAD, they can
303 +not add or remove any file, just modify existing files.
304 +If userX is also a member of group1, userX will have write, create, and delete permissions
305 +because it is specifically given these permissions.
307 +$ cvs -d /cvs/projectA racl userY:wcd -r develStream -d lib
308 +$ cvs -d /cvs/projectA racl userY:r -r integStream -d lib
309 +These commands will give wcd permissions to userY on lib directory with tag develstream,
310 +and r permissions on lib directory with tag integStream.
312 +$ cvs -d /cvs/projectA racl userZ:wcd -d src
313 +$ cvs -d /cvs/projectA racl userZ:r -f src/main.c
314 +First command will give wcd permissions to userZ on src directory, but only read
315 +permission on file main.c in src directory.
317 +Using + and - signs to set permissions on a file or directory:
319 +$ cvs -d /cvs/projectA racl userZ:+t -d src
320 +$ cvs -d /cvs/projectA racl userZ:-cd -d src
321 +$ cvs -d /cvs/projectA racl userZ:-wt -d src
322 +Before the first command, userZ has wcd permissions on src directory, after issuing
323 +command it will have wcdt permissions. Tag permission will be added. UserZ has wcdt
324 +permissions, and we execute the second command to remove create and delete permissions.
325 +So userZ has wt permissions. In the last command we also remove wt permissions, finally
326 +userZ has no defined permissions left, and it will use the default permissions if set.
328 +Listing permissions on a file or directory:
330 +$ cvs -d /cvs/projectA racl -l -d src
331 +$ cvs -d /cvs/projectA racl -l -f src
332 +$ cvs -d /cvs/projectA racl -l -f src/main.c
334 +First command will list the permissions for src directory.
336 +d src HEAD | userX:wcd group1:r | defaults:r
337 +userX and group1 has assigned permissions, all other users will have default
338 +permissions, which is only read.
340 +Second command will list the permissions for files in src directory.
342 +f src/main.c HEAD | userX:wcd group1:r | defaults:r
343 +f src/server.c HEAD | userX:wcd group1:r | defaults:r
344 +f src/client.c HEAD | userX:wcd group1:r | defaults:r
346 +Third command will list the permissions for main.c file in src directory.
348 +f src/main.c HEAD | userX:wcd group1:r | defaults:r
351 diff -urN cvs-1.11.17.orig/src/acl.c cvs-1.11.17/src/acl.c
352 --- cvs-1.11.17.orig/src/acl.c 1970-01-01 01:00:00.000000000 +0100
353 +++ cvs-1.11.17/src/acl.c 2004-06-24 10:52:51.000000000 +0200
357 + * CVS ACCESS CONTROL LIST EXTENSION
359 + * sbaris@users.sourceforge.net
361 + * http://cvsacl.sourceforge.net/
363 + * CVSACL is a patch for CVS versions
366 + * It adds two new subcommands (acl & racl) to cvs for access control
368 + * It provides advanced ACL definitions per modules, directories,
369 + * and files on branch/tag for remote cvs repository connections.
370 + * Execution of all CVS subcommands can be controlled with eight
371 + * different permissions.
372 + * ACL definitions works for only remote connections, local users can
373 + * access and modify repository, if unix file system permissions allow.
374 + * If you want all users to make remote connections to repository,
375 + * and not allow local users to access repository, you have to set
376 + * CVSServerRunAsUser keyword in aclconfig file (explained below).
377 + * Still local users can use acl and racl subcommands to set permissions
378 + * on directories or files if they have acl admin rights (p) on related
379 + * directories or files.
380 + * So, in order to control all access to repository with this ACL extension,
381 + * you should use CVSServerRunAsUser keyword and force all users to make
382 + * remote connections.
383 + * CVS repository administrator or project managers have to use acl and racl
384 + * subcommands to manage permissions. But there is no gui client supporting
385 + * these subcommands, so you have to use cvs client itself either
386 + * locally or remotely.
389 + * Permission Types:
390 + * - no permission (n) (1)
391 + * - all permissions (a) (2)
392 + * - write permission (w) (3)
393 + * - tag permission (t) (4)
394 + * - read permission (r) (5)
395 + * - add permission (c) (6)
396 + * - remove permission (d) (7)
397 + * - permission change (p) (8)
402 + * ********************************************************************
403 + * This program is free software; you can redistribute it and/or modify
404 + * it under the terms of the GNU General Public License as published by
405 + * the Free Software Foundation; either version 1, or (at your option)
406 + * any later version.
408 + * This program is distributed in the hope that it will be useful,
409 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
410 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
411 + * GNU General Public License for more details.
412 + * *******************************************************************
417 +#include "getline.h"
420 +static int acl_fileproc PROTO ((void *callerdat, struct file_info *finfo));
421 +static Dtype acl_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
422 + const char *update_dir, List *entries));
424 +static int acllist_fileproc PROTO ((void *callerdat, struct file_info *finfo));
425 +static Dtype acllist_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
426 + const char *update_dir, List *entries));
428 +static void acllist_print PROTO ((char *line, const char *obj));
430 +static int racl_proc PROTO((int argc, char **argv, char *xwhere,
431 + char *mwhere, char *mfile, int shorten,
432 + int local_specified, char *mname, char *msg));
434 +FILE *open_accessfile (char *xmode, const char *repos, char **fname);
435 +FILE *open_groupfile (char *xmode);
437 +char *get_perms (char *xperms);
438 +char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
440 +static char *cache_repository;
441 +static int cache_retval;
442 +static int founddeniedfile;
443 +static int cache_perm;
447 +int use_cvs_acl = 0;
448 +char *cvs_acl_default_permissions;
449 +int use_cvs_groups = 0;
450 +int use_system_groups = 0;
451 +int use_separate_acl_file_for_each_dir = 0;
452 +char *cvs_acl_file_location = NULL;
453 +char *cvs_groups_file_location = NULL;
454 +char *cvs_server_run_as = NULL;
455 +int stop_at_first_permission_denied = 0;
461 +static int defaultperms;
463 +static char *default_perms_object;
464 +char *default_part_perms_accessfile;
475 +int aclconfig_default_used;
477 +static const char *const acl_usage[] =
479 + "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
480 + "\t-R\tProcess directories recursively.\n",
481 + "\t-r rev\tExisting revision/tag.\n",
482 + "\t-l\tList defined ACLs.\n",
483 + "\t-d dir\tProcess on given directory.\n",
484 + "\t-f file\tProcess on given file.\n",
485 + "(Specify the --help global option for a list of other help options)\n",
489 +static const char *const racl_usage[] =
491 + "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
492 + "\t-R\tProcess directories recursively.\n",
493 + "\t-r rev\tExisting revision/tag.\n",
494 + "\t-l\tList defined ACLs.\n",
495 + "\t-d dir\tProcess on given directory.\n",
496 + "\t-f file\tProcess on given file.\n",
497 + "(Specify the --help global option for a list of other help options)\n",
503 +access_allowed (file, repos, tag, perm, mline, mpos, usecache)
517 + size_t line_allocated = 0;
519 + char *part_type = NULL;
520 + char *part_object = NULL;
521 + char *part_tag = NULL;
522 + char *part_perms = NULL;
533 + int oneaccessfile = 0;
534 + int accessfilecount;
536 + int signlevel = -1;
540 + const char *repository;
541 + char *filefullname = NULL;
550 + repository = xstrdup ("ALL");
553 + repository = Short_Repository (repos);
557 + && cache_repository != NULL
558 + && strcmp (cache_repository, repository) == 0
559 + && !founddeniedfile
560 + && perm == cache_perm)
561 + return (cache_retval);
564 + free(cache_repository);
565 + cache_repository = xstrdup(repository);
571 + filefullname = xmalloc (strlen (repository)
575 + strcpy (filefullname, repository);
576 + strcat (filefullname, "/");
577 + strcat (filefullname, file);
581 + iline = xstrdup(repository);
583 + tempv = strtok(iline, "/\t");
584 + tempc = xstrdup(tempv);
585 + tempsize = strlen(tempc);
589 + dirs[intcount] = xstrdup(tempc);
591 + while ((tempv = strtok(NULL, "/\t")) != NULL)
595 + xrealloc_and_strcat(&tempc, &tempsize, "/");
596 + xrealloc_and_strcat(&tempc, &tempsize, tempv);
598 + dirs[intcount] = xstrdup(tempc);
603 + accessfilecount = intcount;
605 + dirs[intcount] = xstrdup(filefullname);
608 + for (accessfilecount; accessfilecount >= 0 && !oneaccessfile; accessfilecount--)
610 + if (!use_separate_acl_file_for_each_dir)
612 + else if (use_separate_acl_file_for_each_dir)
615 + if (acldir || aclfile)
619 + accessfp = open_accessfile ("r", repository, NULL);
621 + accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
623 + if (accessfp != NULL)
625 + while (getline (&line, &line_allocated, accessfp) >= 0)
628 + if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
631 + xline = xstrdup (line);
632 + part_type = strtok (line, ":\t");
633 + part_object = strtok (NULL, ":\t");
634 + part_tag = strtok (NULL, ":\t");
635 + part_perms = strtok (NULL, ":\t");
637 + for (x = intcount; x >= signlevel && x != -1; x--)
639 + if (strcmp (dirs[x], part_object) == 0)
641 + if (valid_tag (part_tag, tag))
645 + if (listacl || acldir || aclfile)
647 + *mline = xstrdup (xline);
648 + *mpos = ftell (accessfp);
651 + if (valid_perm (part_perms, perm))
653 + if (signlevel == x)
655 + if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
658 + else if (!aclconfig_default_used)
668 + if (signlevel == x)
670 + if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
673 + else if (!aclconfig_default_used)
678 + if (strncmp (part_type, "f", 1) == 0)
679 + founddeniedfile = 1;
687 + if (strncmp (xline, "d:ALL", 5) == 0 && (!groupfound && !userfound || listacl))
689 + /* a default found */
690 + if (valid_tag (part_tag, tag))
694 + default_part_perms_accessfile = xstrdup (part_perms);
696 + if (valid_perm (part_perms, perm))
709 + if (fclose (accessfp) == EOF)
710 + error (1, errno, "cannot close 'access' file");
718 + if (valid_perm (NULL, perm))
729 + cache_retval = retval;
731 + free (filefullname);
736 +/* Returns 1 if successful, 0 if not. */
738 +valid_tag (part_tag, tag)
743 + tag = xstrdup ("HEAD");
745 + if (strcmp (part_tag, "ALL") == 0)
748 + if (strcmp (tag, part_tag) == 0)
754 +/* Returns 1 if successful, 0 if not. */
756 +valid_perm (part_perms, perm)
763 + perms = get_perms (part_perms);
765 + /* Allow, if nothing found. */
766 + if (perms[0] == '\0')
770 + if (strstr (perms, "n"))
771 + retval = 0; /* no access allowed, exit */
772 + if (strstr (perms, "p"))
773 + retval = 1; /* admin rights */
774 + else if (strstr (perms, "a") && perm != 8)
775 + retval = 1; /* all access allowed, exit */
779 + case 3: /* write permission */
780 + if (strstr (perms, "w"))
783 + case 4: /* tag permission */
784 + if (strstr (perms, "t"))
787 + case 5: /* read permission */
788 + if (strstr (perms, "w") || strstr (perms, "t") || strstr (perms, "c") ||
789 + strstr (perms, "d") || strstr (perms, "r"))
792 + case 6: /* create permission */
793 + if (strstr (perms, "c"))
796 + case 7: /* delete permission */
797 + if (strstr (perms, "d"))
800 + case 8: /* permission change */
801 + if (strstr (perms, "p"))
805 + retval = 0; /* never reached */
813 +get_perms (part_perms)
819 + size_t xperms_len = 1;
825 + char *founduser = NULL;
826 + char *foundall = NULL;
827 + int default_checked = 0;
829 + aclconfig_default_used = 0;
831 + xperms = xmalloc (xperms_len);
834 + username = getcaller ();
836 + /* no defined acl, no default acl in access file,
837 + or no access file at all */
838 + if (part_perms == NULL)
839 + if (cvs_acl_default_permissions)
841 + aclconfig_default_used = 1;
842 + return (cvs_acl_default_permissions);
848 + founduser = strstr (part_perms, username);
849 + foundall = strstr (part_perms, "ALL!");
853 + usr = strtok (founduser, "!\t");
854 + per = strtok (NULL, ",\t");
856 + if (strcmp (usr, username) == 0)
858 + xperms = xstrdup (per);
859 + xperms_len = strlen (xperms);
866 + if (use_system_groups) {
867 + struct group *griter;
869 + while (griter = getgrent ()) {
870 + char **users=griter->gr_mem;
872 + char *userchk = users [index++];
873 + while(userchk != NULL) {
874 + if(strcmp (userchk, username) == 0)
876 + userchk = users[index++];
878 + if (userchk != NULL) {
880 + if ((grp = strstr (part_perms, griter->gr_name)) && grp[strlen (griter->gr_name)] == '!') {
881 + char *gperm = strtok (grp, "!\t");
882 + gperm = strtok (NULL, ",\t");
883 + xrealloc_and_strcat (&xperms, &xperms_len, gperm);
891 + else if (use_cvs_groups) {
892 + groupfp = open_groupfile ("r");
893 + if (groupfp != NULL)
896 + size_t line_allocated = 0;
898 + while (getline (&line, &line_allocated, groupfp) >= 0)
900 + if (strstr (line, username))
903 + temp = strstr (line, username);
905 + if (temp[strlen (username)] == ','
906 + || temp[strlen (username)] == ' '
907 + || temp[strlen (username)] == '\n')
910 + tmp = strtok (line, ":\t");
911 + if (strcmp (tmp, username) != 0)
914 + if ((grp = strstr (part_perms, tmp)))
915 + if (grp[strlen (tmp)] == '!')
918 + gperm = strtok (grp, "!\t");
919 + gperm = strtok (NULL, ",\t");
921 + xrealloc_and_strcat (&xperms, &xperms_len, gperm);
929 + if (fclose (groupfp) == EOF)
930 + error (1, errno, "cannot close 'group' file");
935 + if (foundall && (!groupfound && !userfound))
937 + usr = strtok (strstr (part_perms, "ALL!"), "!\t");
938 + per = strtok (NULL, ",\t");
940 + if (!default_checked)
941 + default_perms_object = xstrdup (per);
943 + if (xperms[0] == '\0')
945 + xperms = xstrdup (per);
946 + xperms_len = strlen (xperms);
949 + else if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
951 + part_perms = xstrdup (default_part_perms_accessfile);
952 + default_checked = 1;
954 + goto check_default;
957 + if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
959 + if (default_perms_object)
960 + xperms = xstrdup (default_perms_object);
961 + else if (default_part_perms_accessfile)
963 + part_perms = default_part_perms_accessfile;
964 + default_checked = 1;
965 + goto check_default;
967 + else if (cvs_acl_default_permissions)
969 + aclconfig_default_used = 1;
970 + xperms = xstrdup (cvs_acl_default_permissions);
974 + if (xperms[0] == '\0' && cvs_acl_default_permissions)
976 + aclconfig_default_used = 1;
977 + xperms = xstrdup (cvs_acl_default_permissions);
989 + char *chdirrepository;
1000 + is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
1003 + usage (is_racl ? racl_usage : acl_usage);
1005 + /* parse the args */
1008 + while ((c = getopt (argc, argv, "Rr:dfl")) != -1)
1016 + tag = xstrdup (optarg);
1029 + usage (is_racl ? racl_usage : acl_usage);
1037 + if (!acldir && !aclfile)
1038 + usage (is_racl ? racl_usage : acl_usage);
1039 + if (acldir && aclfile)
1040 + usage (is_racl ? racl_usage : acl_usage);
1043 + if (strstr (argv[0], ":"))
1044 + usage (is_racl ? racl_usage : acl_usage);
1046 + if (!strstr (argv[0], ":"))
1047 + usage (is_racl ? racl_usage : acl_usage);
1049 + if (argc < (is_racl ? 1 : 1))
1050 + usage (is_racl ? racl_usage : acl_usage);
1052 +#ifdef CLIENT_SUPPORT
1054 + if (current_parsed_root->isremote)
1081 + send_arg (argv[0]);
1090 + for (i = 0; i < argc; ++i)
1091 + send_arg (argv[i]);
1093 + send_to_server ("racl\012",0);
1097 + send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
1098 + send_file_names (argc, argv, SEND_EXPAND_WILD);
1099 + send_to_server ("acl\012", 0);
1102 + return get_responses_and_close ();
1106 +#ifdef SERVER_SUPPORT
1110 + muser = strtok (argv[0], ":\t");
1111 + mperms = strtok (NULL, ":\t");
1113 + /* if set to 'default' */
1114 + if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
1115 + mperms = xstrdup ("x");
1117 + /* Check that the given permissions are valid. */
1118 + if (!given_perms_valid (mperms))
1119 + error (1,0,"Invalid permissions: '%s'", mperms);
1127 + tag = xstrdup ("HEAD");
1129 + if (!cvs_casecmp (argv[0], "ALL"))
1131 + argv[0] = xstrdup (".");
1133 + if (!use_separate_acl_file_for_each_dir)
1144 + db = open_module ();
1145 + for (i = 0; i < argc; i++)
1147 + err += do_module (db, argv[i], MISC, "ACL ing: ",
1148 + racl_proc, (char *) NULL, 0, !recursive, 0,
1151 + close_module (db);
1155 + err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive, NULL,
1159 + error (1, 0, "an error accured");
1167 +racl_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg)
1186 + repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
1187 + + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
1189 + (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
1190 + where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
1192 + (void) strcpy (where, argv[0]);
1194 + /* if mfile isn't null, we need to set up to do only part of the module */
1195 + if (mfile != NULL)
1200 + /* if the portion of the module is a path, put the dir part on repos */
1201 + if ((cp = strrchr (mfile, '/')) != NULL)
1204 + (void) strcat (repository, "/");
1205 + (void) strcat (repository, mfile);
1206 + (void) strcat (where, "/");
1207 + (void) strcat (where, mfile);
1211 + /* take care of the rest */
1212 + path = xmalloc (strlen (repository) + strlen (mfile) + 5);
1213 + (void) sprintf (path, "%s/%s", repository, mfile);
1216 + /* directory means repository gets the dir tacked on */
1217 + (void) strcpy (repository, path);
1218 + (void) strcat (where, "/");
1219 + (void) strcat (where, mfile);
1223 + myargv[0] = argv[0];
1224 + myargv[1] = mfile;
1231 + /* cd to the starting repository */
1232 + if ( CVS_CHDIR (repository) < 0)
1234 + error (0, errno, "cannot chdir to %s", repository);
1235 + free (repository);
1239 + /* End section which is identical to patch_proc. */
1241 + which = W_REPOS | W_ATTIC;
1246 + which = W_LOCAL | W_REPOS | W_ATTIC;
1249 + err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL, NULL,
1250 + argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1253 + err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
1254 + argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1262 +acl_fileproc (callerdat, finfo)
1264 +struct file_info *finfo;
1270 + char *filefullname;
1272 + char *founduserpart = NULL;
1273 + char *newuserpart = NULL;
1274 + char *otheruserparts = NULL;
1275 + size_t otherslen = 0;
1277 + const char *frepository;
1278 + int foundline = 0;
1280 + char *line = NULL;
1281 + size_t line_allocated = 0;
1284 + char *part_type = NULL;
1285 + char *part_object = NULL;
1286 + char *part_tag = NULL;
1287 + char *part_perms = NULL;
1298 + frepository = Short_Repository (finfo->repository);
1300 + filefullname = xmalloc (strlen (frepository)
1301 + + strlen (finfo->file)
1303 + strcpy (filefullname, frepository);
1304 + strcat (filefullname, "/");
1305 + strcat (filefullname, finfo->file);
1307 + if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos, 0))
1308 + error (1,0,"You do not have acl admin rights on '%s'", frepository);
1312 + part_type = strtok (line, ":\t");
1313 + part_object = strtok (NULL, ":\t");
1314 + part_tag = strtok (NULL, ":\t");
1315 + part_perms = strtok (NULL, ":\t");
1318 + userpart = strtok (part_perms, ",\t");
1320 + if (strstr (userpart, muser))
1321 + founduserpart = xstrdup (userpart);
1324 + otheruserparts = xstrdup (userpart);
1325 + otherslen = strlen (otheruserparts);
1328 + while ((userpart = strtok (NULL, ",\t")) != NULL)
1330 + if (strncmp (userpart, muser, strlen (muser)) == 0)
1331 + founduserpart = xstrdup (userpart);
1334 + if (otheruserparts != NULL)
1336 + xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1337 + xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1341 + otheruserparts = xstrdup (userpart);
1342 + otherslen = strlen (otheruserparts);
1348 + wperms = make_perms (mperms, founduserpart, &errmsg);
1349 + if (wperms == NULL)
1352 + error (0, 0, "%s %s", filefullname, errmsg);
1358 + cvs_output ("X ", 0);
1359 + cvs_output (filefullname, 0);
1360 + cvs_output ("\n", 0);
1362 + write_perms (muser, wperms, founduserpart, foundline,
1363 + otheruserparts, "f", filefullname, tag, pos, finfo->repository);
1370 +acl_dirproc (callerdat, dir, repos, update_dir, entries)
1374 +const char *update_dir;
1377 + const char *drepository;
1378 + char *founduserpart = NULL;
1379 + char *newuserpart = NULL;
1380 + char *otheruserparts = NULL;
1381 + size_t otherslen = 0;
1382 + int foundline = 0;
1384 + char *line = NULL;
1385 + size_t line_allocated = 0;
1389 + char *part_type = NULL;
1390 + char *part_object = NULL;
1391 + char *part_tag = NULL;
1392 + char *part_perms = NULL;
1400 + if (repos[0] == '\0')
1401 + repos = Name_Repository (dir, NULL);
1406 + if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
1407 + error (1,0,"You do not have admin rights on '%s'", Short_Repository (repos));
1409 + drepository = Short_Repository (repos);
1413 + part_type = strtok (line, ":\t");
1414 + part_object = strtok (NULL, ":\t");
1415 + part_tag = strtok (NULL, ":\t");
1416 + part_perms = strtok (NULL, ":\t");
1419 + userpart = strtok (part_perms, ",\t");
1421 + if (strstr (userpart, muser))
1422 + founduserpart = xstrdup (userpart);
1425 + otheruserparts = xstrdup (userpart);
1426 + otherslen = strlen (otheruserparts);
1429 + while ((userpart = strtok (NULL, ",\t")) != NULL)
1431 + if (strncmp (userpart, muser, strlen (muser)) == 0)
1432 + founduserpart = xstrdup (userpart);
1435 + if (otheruserparts != NULL)
1437 + xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1438 + xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1442 + otheruserparts = xstrdup (userpart);
1443 + otherslen = strlen (otheruserparts);
1449 + wperms = make_perms (mperms, founduserpart, &errmsg);
1450 + if (wperms == NULL)
1453 + error (0, 0, "%s %s", drepository, errmsg);
1461 + cvs_output ("X ", 0);
1462 + cvs_output ("ALL", 0);
1463 + cvs_output ("\n", 0);
1464 + write_perms (muser, wperms, founduserpart, foundline,
1465 + otheruserparts, "d", "ALL", tag, pos, drepository);//baris
1470 + cvs_output ("X ", 0);
1471 + cvs_output (drepository, 0);
1472 + cvs_output ("\n", 0);
1473 + write_perms (muser, wperms, founduserpart, foundline,
1474 + otheruserparts, "d", drepository, tag, pos, drepository);//baris `repos`
1481 +/* Open CVSROOT/access or defined CVSACLFileLocation file. */
1483 +open_accessfile (fmode, adir, fname)
1491 + if (!use_separate_acl_file_for_each_dir)
1493 + if (cvs_acl_file_location == NULL)
1495 + accessfile = xmalloc (strlen (current_parsed_root->directory)
1496 + + sizeof (CVSROOTADM)
1497 + + sizeof (CVSROOTADM_ACCESS)
1500 + strcpy (accessfile, current_parsed_root->directory);
1501 + strcat (accessfile, "/");
1502 + strcat (accessfile, CVSROOTADM);
1503 + strcat (accessfile, "/");
1504 + strcat (accessfile, CVSROOTADM_ACCESS);
1508 + accessfile = xmalloc (strlen (cvs_acl_file_location));
1509 + strcpy (accessfile, cvs_acl_file_location);
1514 + accessfile = xmalloc (strlen (current_parsed_root->directory)
1516 + + strlen ("access")
1519 + strcpy (accessfile, current_parsed_root->directory);
1520 + strcat (accessfile, "/");
1521 + strcat (accessfile, adir);
1522 + strcat (accessfile, "/");
1523 + strcat (accessfile, "access");
1526 + accessfp = CVS_FOPEN (accessfile, fmode);
1528 + if (accessfp == NULL)
1529 + error (0, 0, "cannot open file: %s", accessfile);
1531 + if (fname != NULL)
1532 + *fname = xstrdup (accessfile);
1534 + free (accessfile);
1536 + return (accessfp);
1539 +/* Open /etc/group file if UseSystemGroups=yes in config file. */
1540 +/* Open CVSROOT/group file if UseCVSGroups=yes in config file. */
1542 +open_groupfile (fmode)
1548 + if (use_cvs_groups)
1550 + if (cvs_groups_file_location != NULL)
1552 + groupfile = xmalloc (strlen (cvs_groups_file_location));
1553 + strcpy (groupfile, cvs_groups_file_location);
1557 + groupfile = xmalloc (strlen (current_parsed_root->directory)
1558 + + sizeof (CVSROOTADM)
1559 + + sizeof (CVSROOTADM_GROUP)
1562 + strcpy (groupfile, current_parsed_root->directory);
1563 + strcat (groupfile, "/");
1564 + strcat (groupfile, CVSROOTADM);
1565 + strcat (groupfile, "/");
1566 + strcat (groupfile, CVSROOTADM_GROUP);
1575 + groupfp = CVS_FOPEN (groupfile, "r");
1577 + if (groupfp == NULL)
1578 + error (0, 0, "cannot open file: %s", groupfile);
1586 +/* Check whether given permissions are valid or not. */
1587 +/* Returns 1 if permissions are valid. */
1588 +/* Returns 0 if permissions are NOT valid. */
1590 +given_perms_valid (cperms)
1597 + if (cperms[0] == '+' || cperms[0] == '-')
1602 + cperms_len = strlen (cperms);
1604 + switch (cperms[index])
1607 + if ((cperms_len - index) == 1 && cperms_len == 1)
1613 + if ((cperms_len - index) == 1 && cperms_len == 1)
1619 + if ((cperms_len - index) == 1)
1625 + if ((cperms_len - index) == 1)
1628 + for (i = index + 1; i < cperms_len; i++)
1629 + if (cperms[i] == 'p')
1635 + if ((cperms_len - index) == 1)
1638 + for (i = index + 1; i < cperms_len; i++)
1639 + if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1645 + if ((cperms_len - index) == 1)
1648 + for (i = index + 1; i < cperms_len; i++)
1649 + if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1655 + if ((cperms_len - index) == 1)
1658 + for (i = index + 1; i < cperms_len; i++)
1659 + if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
1665 + if ((cperms_len - index) == 1)
1668 + for (i = index + 1; i < cperms_len; i++)
1669 + if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
1675 + if ((cperms_len - index) == 1)
1678 + for (i = index + 1; i < cperms_len; i++)
1679 + if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
1692 +make_perms (perms, founduserpart, xerrmsg)
1694 +char *founduserpart;
1699 + size_t fperms_len;
1700 + char *retperms = NULL;
1704 + char *errmsg = NULL;
1705 + size_t retperms_len = 1;
1707 + retperms = xmalloc (retperms_len);
1708 + retperms[0] = '\0';
1710 + perms_len = strlen (perms);
1712 + if (perms[0] == '+' || perms[0] == '-')
1714 + if (founduserpart)
1717 + temp = strtok (founduserpart, "!\t");
1718 + fperms = strtok (NULL, "!\t");
1719 + fperms_len = strlen (fperms);
1721 + if (strncmp (fperms, "x", 1) == 0)
1724 + if (perms[0] == '+')
1725 + *xerrmsg = xstrdup ("cannot add default permission 'x'");
1727 + *xerrmsg = xstrdup ("cannot remove default permission 'x'");
1730 + for (i = 1; i < perms_len && !err; i++)
1738 + if (perms[0] == '+')
1739 + fperms = xstrdup ("p");
1740 + else if (perms[0] == '-')
1743 + fperms = xmalloc (fperms_len);
1748 + for (j = 0; j < fperms_len; j++)
1750 + if (fperms[j] == 'p')
1753 + *xerrmsg = xstrdup ("user has admin rights, cannot use +/- permissions");
1755 + else if (fperms[j] == 'a' && perms[0] == '+')
1758 + *xerrmsg = xstrdup ("user already has all ('a') permission");
1760 + else if (fperms[j] != 'a' && perms[0] == '-')
1763 + *xerrmsg = xstrdup ("user does not have all ('a') permission");
1766 + if (perms[0] == '+')
1768 + fperms = xstrdup ("a");
1769 + fperms_len = strlen (fperms);
1771 + else if (perms[0] == '-')
1774 + fperms = xmalloc (fperms_len);
1780 + for (i = 0; i < fperms_len; i++)
1782 + if (fperms[i] == 'n' && perms[0] == '+')
1784 + fperms = xstrdup ("r");
1785 + fperms_len = strlen (fperms);
1787 + else if (fperms[i] == 'r' && perms[0] == '-')
1790 + fperms = xmalloc (fperms_len);
1793 + else if (perms[0] == '-')
1796 + *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1801 + *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1808 + size_t tempfperms_len = 1;
1810 + tempfperms = xmalloc (tempfperms_len);
1811 + tempfperms[0] = '\0';
1813 + for (j = 0; j < fperms_len; j++)
1815 + if (fperms[j] == 't' || fperms[j] == 'c' || fperms[j] == 'd')
1818 + temp = xmalloc (2);
1819 + temp[0] = fperms[j];
1822 + xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1825 + else if (fperms[j] == 'a' || fperms[j] == 'p')
1828 + *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- write permissions");
1830 + else if (fperms[j] == 'n' || fperms[j] == 'r')
1832 + if (perms[0] == '-')
1835 + *xerrmsg = xstrdup ("user does not have write ('w') permission");
1840 + fperms = xstrdup (tempfperms);
1841 + fperms_len = strlen (fperms);
1842 + free (tempfperms);
1844 + if (perms[0] == '+')
1846 + xrealloc_and_strcat (&fperms, &fperms_len, "w");
1853 + size_t tempfperms_len = 1;
1855 + tempfperms = xmalloc (tempfperms_len);
1856 + tempfperms[0] = '\0';
1858 + for (j = 0; j < fperms_len; j++)
1860 + if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 'd')
1863 + temp = xmalloc (2);
1864 + temp[0] = fperms[j];
1867 + xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1870 + else if (fperms[j] == 'a' || fperms[j] == 'p')
1873 + *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- tag permissions");
1875 + else if (fperms[i] == 'n' || fperms[i] == 'r')
1877 + if (perms[0] == '-')
1878 + *xerrmsg = xstrdup ("user does not have tag ('t') permission");
1882 + fperms = xstrdup (tempfperms);
1883 + fperms_len = strlen (fperms);
1884 + free (tempfperms);
1886 + if (perms[0] == '+')
1888 + xrealloc_and_strcat (&fperms, &fperms_len, "t");
1895 + size_t tempfperms_len = 1;
1897 + tempfperms = xmalloc (tempfperms_len);
1898 + tempfperms[0] = '\0';
1900 + for (j = 0; j < fperms_len; j++)
1902 + if (fperms[j] == 'w' || fperms[j] == 't' || fperms[j] == 'd')
1905 + temp = xmalloc (2);
1906 + temp[0] = fperms[j];
1909 + xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1912 + else if (fperms[j] == 'a' || fperms[j] == 'p')
1915 + *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- create permissions");
1917 + else if (fperms[i] == 'n' || fperms[i] == 'r')
1919 + if (perms[0] == '-')
1921 + *xerrmsg = xstrdup ("user does not have create ('c') permission");
1926 + fperms = xstrdup (tempfperms);
1927 + fperms_len = strlen (fperms);
1928 + free (tempfperms);
1930 + if (perms[0] == '+')
1932 + xrealloc_and_strcat (&fperms, &fperms_len, "c");
1939 + size_t tempfperms_len = 1;
1941 + tempfperms = xmalloc (tempfperms_len);
1942 + tempfperms[0] = '\0';
1944 + for (j = 0; j < fperms_len; j++)
1946 + if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 't')
1949 + temp = xmalloc (2);
1950 + temp[0] = fperms[j];
1953 + xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1956 + else if (fperms[j] == 'a' || fperms[j] == 'p')
1959 + *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- delete permissions");
1961 + else if (fperms[i] == 'n' || fperms[i] == 'r')
1963 + if (perms[0] == '-')
1965 + *xerrmsg = xstrdup ("user does not have delete ('d') permission");
1969 + fperms = xstrdup (tempfperms);
1970 + fperms_len = strlen (fperms);
1971 + free (tempfperms);
1973 + if (perms[0] == '+')
1975 + xrealloc_and_strcat (&fperms, &fperms_len, "d");
1981 + *xerrmsg = xstrdup ("error in 'access' file format");
1984 + if (fperms[0] == '\0')
1985 + retperms = xstrdup ("none");
1987 + retperms = xstrdup (fperms);
1993 + *xerrmsg = xstrdup("user is not given any permissions to remove/add");
1999 + retperms = xstrdup (perms);
2005 + return (retperms);
2009 +write_perms (user, perms, founduserpart, foundline, otheruserparts,
2010 + part_type, part_object, part_tag, pos, arepos)
2013 +char *founduserpart;
2015 +char *otheruserparts;
2023 + char *tmpaccessout;
2025 + FILE *accessfpout;
2027 + char *newline = NULL;
2028 + size_t newlinelen = 1;
2030 + char *line = NULL;
2031 + size_t line_allocated = 0;
2033 + newline = xmalloc (newlinelen);
2034 + newline[0] = '\0';
2036 + if (!cvs_casecmp (part_tag, "ALL"))
2037 + part_tag = xstrdup ("ALL");
2039 + xrealloc_and_strcat (&newline, &newlinelen, part_type);
2040 + xrealloc_and_strcat (&newline, &newlinelen, ":");
2041 + xrealloc_and_strcat (&newline, &newlinelen, part_object);
2042 + xrealloc_and_strcat (&newline, &newlinelen, ":");
2043 + xrealloc_and_strcat (&newline, &newlinelen, part_tag);
2044 + xrealloc_and_strcat (&newline, &newlinelen, ":");
2046 + if (strncmp (perms, "none", 4) != 0)
2048 + xrealloc_and_strcat (&newline, &newlinelen, user);
2049 + xrealloc_and_strcat (&newline, &newlinelen, "!");
2050 + xrealloc_and_strcat (&newline, &newlinelen, perms);
2051 + if (otheruserparts != NULL)
2052 + xrealloc_and_strcat (&newline, &newlinelen, ",");
2055 + if (otheruserparts != NULL)
2057 + if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
2058 + otheruserparts[strlen (otheruserparts) - 1] = '\0';
2060 + xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
2063 + xrealloc_and_strcat (&newline, &newlinelen, ":");
2067 + accessfpout = cvs_temp_file (&tmpaccessout);
2068 + accessfpin = open_accessfile ("r", arepos, &accessfile);
2070 + while (getline (&line, &line_allocated, accessfpin) >= 0)
2072 + if (pos != ftell (accessfpin))
2074 + if (fprintf (accessfpout, line) < 0)
2075 + error (1, errno, "writing temporary file: %s", tmpaccessout);
2079 + if (fprintf (accessfpout, "%s\n", newline) < 0)
2080 + error (1, errno, "writing temporary file: %s", tmpaccessout);
2084 + if (fclose (accessfpin) == EOF)
2085 + error (1, errno, "cannot close access file: %s", accessfile);
2087 + if (fclose (accessfpout) == EOF)
2088 + error (1, errno, "cannot close temporary file: %s", tmpaccessout);
2090 + if (CVS_UNLINK (accessfile) < 0)
2091 + error (0, errno, "cannot remove %s", accessfile);
2093 + copy_file (tmpaccessout, accessfile);
2095 + if (CVS_UNLINK (tmpaccessout) < 0)
2096 + error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
2100 + accessfpout = open_accessfile ("r+", arepos, &accessfile);
2102 + if (accessfpout == NULL)
2104 + if (existence_error (errno))
2106 + accessfpout = open_accessfile ("w+", arepos, &accessfile);
2110 + if (fseek (accessfpout, 0, 2) != 0)
2111 + error (1, errno, "cannot fseek access file: %s", accessfile);
2114 + if (fprintf (accessfpout, "%s\n", newline) < 0)
2115 + error (1, errno, "writing access file: %s", accessfile);
2117 + if (fclose (accessfpout) == EOF)
2118 + error (1, errno, "cannot close access file: %s", accessfile);
2123 + chmod(accessfile, 0644);
2130 +acllist_fileproc (callerdat, finfo)
2132 +struct file_info *finfo;
2135 + char *filefullname;
2136 + const char *frepository;
2137 + char *line = NULL;
2143 + frepository = Short_Repository (finfo->repository);
2145 + filefullname = xmalloc (strlen (frepository)
2146 + + strlen (finfo->file)
2148 + strcpy (filefullname, frepository);
2149 + strcat (filefullname, "/");
2150 + strcat (filefullname, finfo->file);
2152 + if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos, 0))
2153 + error (1,0,"You do not have admin rights on '%s'", frepository);
2155 + acllist_print (line, filefullname);
2161 +acllist_dirproc (callerdat, dir, repos, update_dir, entries)
2165 +const char *update_dir;
2169 + char *line = NULL;
2170 + const char *drepository;
2173 + if (repos[0] == '\0')
2174 + repos = Name_Repository (dir, NULL);
2179 + drepository = Short_Repository (repos);
2181 + if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
2182 + error (1, 0, "You do not have admin rights on '%s'", drepository);
2184 + acllist_print (line, drepository);
2191 +acllist_print (line, obj)
2200 + char *printedusers[255];
2201 + printedusers[0] = NULL;
2205 + temp = strtok (line, ":\t");
2208 + cvs_output ("d ", 0);
2210 + cvs_output ("f ", 0);
2212 + temp = strtok (NULL, ":\t");
2214 + cvs_output(obj, 0);
2215 + cvs_output (" | ", 0);
2217 + temp = strtok (NULL, ":\t");
2218 + cvs_output (temp, 0);
2219 + cvs_output (" | ", 0);
2221 + while ((temp = strtok (NULL, "!\t")) != NULL)
2223 + if (strncmp (temp, ":", 1) == 0)
2226 + if (strcmp (temp, "ALL") == 0)
2228 + temp = strtok (NULL, ",\t");
2232 + cvs_output (temp, 0);
2233 + cvs_output (":", 0);
2235 + while (printedusers[c] != NULL)
2238 + printedusers[c] = xstrdup (temp);
2240 + printedusers[c] = NULL;
2242 + temp = strtok (NULL, ",\t");
2244 + if (temp != NULL && temp[strlen (temp) - 2] == ':')
2245 + temp[strlen (temp) - 2] = '\0';
2247 + cvs_output (temp, 0);
2248 + cvs_output (" ", 0);
2251 + if (default_perms_object)
2253 + cvs_output ("| defaults ", 0);
2254 + cvs_output ("ALL:", 0);
2255 + cvs_output (default_perms_object, 0);
2257 + else if (default_part_perms_accessfile)
2260 + i = strlen (default_part_perms_accessfile);
2261 + xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
2264 + line = xstrdup(default_part_perms_accessfile);
2266 + cvs_output ("| defaults ", 0);
2268 + temp = strtok (line, "!\t");
2269 + cvs_output (temp, 0);
2270 + cvs_output (":", 0);
2272 + temp = strtok (NULL, ",\t");
2274 + cvs_output (temp, 0);
2275 + cvs_output (" ", 0);
2277 + while ((temp = strtok (NULL, "!\t")) != NULL)
2281 + while (printedusers[c2] != NULL && printed == 0)
2283 + if (strcmp (printedusers[c2], temp) == 0)
2293 + cvs_output (temp, 0);
2294 + cvs_output (":", 0);
2297 + temp = strtok (NULL, ",\t");
2299 + if (temp[strlen (temp) - 2] == ':')
2300 + temp[strlen (temp) - 2] = '\0';
2304 + cvs_output (temp, 0);
2305 + cvs_output (" ", 0);
2309 + else if (cvs_acl_default_permissions)
2311 + cvs_output ("| defaults ", 0);
2312 + cvs_output ("ALL: ", 0);
2313 + cvs_output (cvs_acl_default_permissions, 0);
2316 + cvs_output ("\n", 0);
2322 + cvs_output ("d ", 0);
2324 + cvs_output ("f ", 0);
2325 + cvs_output (obj, 0);
2326 + cvs_output (" | ", 0);
2327 + cvs_output (tag, 0);
2328 + cvs_output (" | ", 0);
2330 + if (default_perms_object)
2332 + cvs_output ("| defaults ", 0);
2333 + cvs_output ("ALL:", 0);
2334 + cvs_output (default_perms_object, 0);
2335 + cvs_output ("\n", 0);
2337 + else if (default_part_perms_accessfile)
2340 + line = xstrdup(default_part_perms_accessfile);
2342 + cvs_output ("| defaults ", 0);
2344 + temp = strtok (line, "!\t");
2345 + cvs_output (temp, 0);
2346 + cvs_output (":", 0);
2348 + temp = strtok (NULL, ",\t");
2350 + if (temp[strlen (temp) - 2] == ':')
2351 + temp[strlen (temp) - 2] = '\0';
2353 + cvs_output (temp, 0);
2354 + cvs_output (" ", 0);
2356 + while ((temp = strtok (NULL, "!\t")) != NULL)
2358 + cvs_output (temp, 0);
2359 + cvs_output (":", 0);
2361 + temp = strtok (NULL, ",\t");
2363 + if (temp[strlen (temp) - 2] == ':')
2364 + temp[strlen (temp) - 2] = '\0';
2366 + cvs_output (temp, 0);
2367 + cvs_output (" ", 0);
2369 + cvs_output ("\n", 0);
2371 + else if (cvs_acl_default_permissions)
2373 + cvs_output ("| defaults ", 0);
2374 + cvs_output ("ALL: ", 0);
2375 + cvs_output (cvs_acl_default_permissions, 0);
2376 + cvs_output ("\n", 0);
2379 + cvs_output ("default:p (no perms)\n", 0);
2383 diff -urN cvs-1.11.17.orig/src/add.c cvs-1.11.17/src/add.c
2384 --- cvs-1.11.17.orig/src/add.c 2004-05-10 16:35:54.000000000 +0200
2385 +++ cvs-1.11.17/src/add.c 2004-08-04 10:40:18.602728608 +0200
2386 @@ -400,6 +400,24 @@
2391 +#ifdef SERVER_SUPPORT
2392 + if (use_cvs_acl && server_active)
2394 + if (!access_allowed (finfo.file, repository, vers->tag, 6,
2397 + if (stop_at_first_permission_denied)
2398 + error (1, 0, "permission denied for %s",
2399 + Short_Repository (finfo.repository));
2401 + error (0, 0, "permission denied for %s/%s",
2402 + Short_Repository (finfo.repository), finfo.file);
2408 /* There is a user file, so build the entry for it */
2409 if (build_entry (repository, finfo.file, vers->options,
2410 message, entries, vers->tag) != 0)
2411 @@ -656,6 +674,26 @@
2412 && isdir (finfo.file)
2413 && !wrap_name_has (finfo.file, WRAP_TOCVS))
2417 +#ifdef SERVER_SUPPORT
2418 + if (use_cvs_acl && server_active)
2420 + if (!access_allowed (NULL, repository, NULL, 6,
2423 + if (stop_at_first_permission_denied)
2424 + error (1, 0, "permission denied for %s",
2425 + Short_Repository (finfo.repository));
2427 + error (0, 0, "permission denied for %s/%s",
2428 + Short_Repository (finfo.repository), finfo.file);
2435 err += add_directory (&finfo);
2438 diff -urN cvs-1.11.17.orig/src/annotate.c cvs-1.11.17/src/annotate.c
2439 --- cvs-1.11.17.orig/src/annotate.c 2004-03-22 16:44:27.000000000 +0100
2440 +++ cvs-1.11.17/src/annotate.c 2004-08-04 10:40:18.603728456 +0200
2441 @@ -276,6 +276,25 @@
2442 if (version == NULL)
2446 +#ifdef SERVER_SUPPORT
2447 + if (use_cvs_acl && server_active)
2449 + if (!access_allowed (finfo->file, finfo->repository, version, 5,
2452 + if (stop_at_first_permission_denied)
2453 + error (1, 0, "permission denied for %s",
2454 + Short_Repository (finfo->repository));
2456 + error (0, 0, "permission denied for %s/%s",
2457 + Short_Repository (finfo->repository), finfo->file);
2464 /* Distinguish output for various files if we are processing
2466 cvs_outerr ("\nAnnotations for ", 0);
2467 diff -urN cvs-1.11.17.orig/src/commit.c cvs-1.11.17/src/commit.c
2468 --- cvs-1.11.17.orig/src/commit.c 2004-06-09 16:34:54.000000000 +0200
2469 +++ cvs-1.11.17/src/commit.c 2004-08-04 10:40:18.606728000 +0200
2470 @@ -1299,6 +1299,34 @@
2476 +#ifdef SERVER_SUPPORT
2477 + if (use_cvs_acl && server_active)
2480 + if (ci->status == T_MODIFIED)
2482 + else if (ci->status == T_ADDED)
2484 + else if (ci->status == T_REMOVED)
2487 + if (!access_allowed (finfo->file, finfo->repository, ci->tag, whichperm,
2490 + if (stop_at_first_permission_denied)
2491 + error (1, 0, "permission denied for %s",
2492 + Short_Repository (finfo->repository));
2494 + error (0, 0, "permission denied for %s/%s",
2495 + Short_Repository (finfo->repository), finfo->file);
2502 if (ci->status == T_MODIFIED)
2504 if (finfo->rcs == NULL)
2505 diff -urN cvs-1.11.17.orig/src/cvs.h cvs-1.11.17/src/cvs.h
2506 --- cvs-1.11.17.orig/src/cvs.h 2004-08-04 10:31:54.000000000 +0200
2507 +++ cvs-1.11.17/src/cvs.h 2004-08-04 10:40:18.609727544 +0200
2508 @@ -195,6 +195,11 @@
2509 #define CVSROOTADM_PASSWD "passwd"
2510 #define CVSROOTADM_CONFIG "config"
2513 +#define CVSROOTADM_ACLCONFIG "aclconfig"
2514 +#define CVSROOTADM_ACCESS "access"
2515 +#define CVSROOTADM_GROUP "group"
2517 #define CVSNULLREPOS "Emptydir" /* an empty directory */
2519 /* Other CVS file names */
2520 @@ -572,6 +577,18 @@
2521 /* LockDir setting from CVSROOT/config. */
2522 extern char *lock_dir;
2525 +/* ACL Patch settings from CVSROOT/config */
2526 +extern int use_cvs_acl;
2527 +extern char *cvs_acl_default_permissions;
2528 +extern int use_cvs_groups;
2529 +extern int use_system_groups;
2530 +extern int use_separate_acl_file_for_each_dir;
2531 +extern char *cvs_acl_file_location;
2532 +extern char *cvs_groups_file_location;
2533 +extern char *cvs_server_run_as;
2534 +extern int stop_at_first_permission_denied;
2536 void Scratch_Entry PROTO((List * list, const char *fname));
2537 void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
2538 void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
2539 @@ -867,6 +884,10 @@
2540 int editors PROTO ((int argc, char **argv));
2541 int watchers PROTO ((int argc, char **argv));
2542 extern int annotate PROTO ((int argc, char **argv));
2545 +extern int cvsacl PROTO ((int argc, char **argv));
2547 extern int add PROTO ((int argc, char **argv));
2548 extern int admin PROTO ((int argc, char **argv));
2549 extern int checkout PROTO ((int argc, char **argv));
2550 diff -urN cvs-1.11.17.orig/src/diff.c cvs-1.11.17/src/diff.c
2551 --- cvs-1.11.17.orig/src/diff.c 2004-03-20 03:06:45.000000000 +0100
2552 +++ cvs-1.11.17/src/diff.c 2004-08-04 10:40:18.611727240 +0200
2553 @@ -474,6 +474,43 @@
2555 /* Skip all the following checks regarding the user file; we're
2559 +#ifdef SERVER_SUPPORT
2560 + if (use_cvs_acl && server_active)
2564 + if (!access_allowed (NULL, finfo->repository, diff_rev1, 5,
2567 + if (stop_at_first_permission_denied)
2568 + error (1, 0, "permission denied for %s",
2569 + Short_Repository (finfo->repository));
2571 + error (0, 0, "permission denied for %s/%s",
2572 + Short_Repository (finfo->repository), finfo->file);
2579 + if (!access_allowed (NULL, finfo->repository, diff_rev2, 5))
2581 + if (stop_at_first_permission_denied)
2582 + error (1, 0, "permission denied for %s",
2583 + Short_Repository (finfo->repository));
2585 + error (0, 0, "permission denied for %s/%s",
2586 + Short_Repository (finfo->repository), finfo->file);
2595 else if (vers->vn_user == NULL)
2597 @@ -827,6 +864,42 @@
2599 return (R_SKIP_ALL);
2602 +#ifdef SERVER_SUPPORT
2603 + if (use_cvs_acl && server_active)
2607 + if (!access_allowed (NULL, update_dir, diff_rev1, 5,
2610 + if (stop_at_first_permission_denied)
2611 + error (1, 0, "permission denied for %s",
2612 + Short_Repository (update_dir));
2614 + error (0, 0, "permission denied for %s/%s",
2615 + Short_Repository (update_dir), update_dir);
2622 + if (!access_allowed (NULL, update_dir, diff_rev2, 5))
2624 + if (stop_at_first_permission_denied)
2625 + error (1, 0, "permission denied for %s",
2626 + Short_Repository (update_dir));
2628 + error (0, 0, "permission denied for %s/%s",
2629 + Short_Repository (update_dir), update_dir);
2638 error (0, 0, "Diffing %s", update_dir);
2640 diff -urN cvs-1.11.17.orig/src/import.c cvs-1.11.17/src/import.c
2641 --- cvs-1.11.17.orig/src/import.c 2004-04-02 20:55:49.000000000 +0200
2642 +++ cvs-1.11.17/src/import.c 2004-08-04 10:40:18.634723744 +0200
2643 @@ -304,6 +304,20 @@
2644 error (1, 0, "attempt to import the repository");
2648 +#ifdef SERVER_SUPPORT
2649 + if (use_cvs_acl && server_active)
2651 + if (!access_allowed (NULL, repository, argv[1], 6, NULL, NULL, 1))
2653 + error (stop_at_first_permission_denied, 0, "permission denied for %s",
2654 + Short_Repository (repository));
2662 * Make all newly created directories writable. Should really use a more
2663 * sophisticated security mechanism here.
2664 diff -urN cvs-1.11.17.orig/src/log.c cvs-1.11.17/src/log.c
2665 --- cvs-1.11.17.orig/src/log.c 2004-05-10 15:37:16.000000000 +0200
2666 +++ cvs-1.11.17/src/log.c 2004-08-04 10:40:18.636723440 +0200
2667 @@ -837,6 +837,25 @@
2672 +#ifdef SERVER_SUPPORT
2673 + if (use_cvs_acl && server_active)
2675 + if (!access_allowed (finfo->file, finfo->repository, NULL, 5,
2678 + if (stop_at_first_permission_denied)
2679 + error (1, 0, "permission denied for %s",
2680 + Short_Repository (finfo->repository));
2682 + error (0, 0, "permission denied for %s/%s",
2683 + Short_Repository (finfo->repository), finfo->file);
2690 if (log_data->sup_header || !log_data->nameonly)
2693 diff -urN cvs-1.11.17.orig/src/main.c cvs-1.11.17/src/main.c
2694 --- cvs-1.11.17.orig/src/main.c 2004-08-04 10:31:54.000000000 +0200
2695 +++ cvs-1.11.17/src/main.c 2004-08-04 10:40:18.639722984 +0200
2696 @@ -106,6 +106,10 @@
2700 + /* cvsacl patch */
2701 + { "acl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2702 + { "racl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2704 { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2705 { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2706 { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR },
2708 if we didn't, then there would be no way to check in a new
2709 CVSROOT/config file to fix the broken one! */
2710 parse_config (current_parsed_root->directory);
2712 + /* cvsacl patch */
2713 + parse_aclconfig (current_parsed_root->directory);
2716 #ifdef CLIENT_SUPPORT
2717 diff -urN cvs-1.11.17.orig/src/Makefile.am cvs-1.11.17/src/Makefile.am
2718 --- cvs-1.11.17.orig/src/Makefile.am 2004-08-04 10:32:06.000000000 +0200
2719 +++ cvs-1.11.17/src/Makefile.am 2004-08-04 10:40:18.594729824 +0200
2722 # The cvs executable
2728 diff -urN cvs-1.11.17.orig/src/Makefile.in cvs-1.11.17/src/Makefile.in
2729 --- cvs-1.11.17.orig/src/Makefile.in 2004-06-09 16:46:19.000000000 +0200
2730 +++ cvs-1.11.17/src/Makefile.in 2004-08-04 10:40:18.600728912 +0200
2733 # The cvs executable
2739 @@ -253,11 +254,11 @@
2740 bin_PROGRAMS = cvs$(EXEEXT)
2741 PROGRAMS = $(bin_PROGRAMS)
2743 -am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \
2744 - buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \
2745 - classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \
2746 - create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \
2747 - edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
2748 +am_cvs_OBJECTS = acl.$(OBJEXT) add.$(OBJEXT) admin.$(OBJEXT) \
2749 + annotate.$(OBJEXT) buffer.$(OBJEXT) checkin.$(OBJEXT) \
2750 + checkout.$(OBJEXT) classify.$(OBJEXT) client.$(OBJEXT) \
2751 + commit.$(OBJEXT) create_adm.$(OBJEXT) cvsrc.$(OBJEXT) \
2752 + diff.$(OBJEXT) edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
2753 expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \
2754 find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \
2755 history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \
2756 @@ -280,34 +281,34 @@
2757 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
2758 depcomp = $(SHELL) $(top_srcdir)/depcomp
2759 am__depfiles_maybe = depfiles
2760 -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/add.Po ./$(DEPDIR)/admin.Po \
2761 -@AMDEP_TRUE@ ./$(DEPDIR)/annotate.Po ./$(DEPDIR)/buffer.Po \
2762 -@AMDEP_TRUE@ ./$(DEPDIR)/checkin.Po ./$(DEPDIR)/checkout.Po \
2763 -@AMDEP_TRUE@ ./$(DEPDIR)/classify.Po ./$(DEPDIR)/client.Po \
2764 -@AMDEP_TRUE@ ./$(DEPDIR)/commit.Po ./$(DEPDIR)/create_adm.Po \
2765 -@AMDEP_TRUE@ ./$(DEPDIR)/cvsrc.Po ./$(DEPDIR)/diff.Po \
2766 -@AMDEP_TRUE@ ./$(DEPDIR)/edit.Po ./$(DEPDIR)/entries.Po \
2767 -@AMDEP_TRUE@ ./$(DEPDIR)/error.Po ./$(DEPDIR)/expand_path.Po \
2768 -@AMDEP_TRUE@ ./$(DEPDIR)/fileattr.Po ./$(DEPDIR)/filesubr.Po \
2769 -@AMDEP_TRUE@ ./$(DEPDIR)/find_names.Po ./$(DEPDIR)/hardlink.Po \
2770 -@AMDEP_TRUE@ ./$(DEPDIR)/hash.Po ./$(DEPDIR)/history.Po \
2771 -@AMDEP_TRUE@ ./$(DEPDIR)/ignore.Po ./$(DEPDIR)/import.Po \
2772 -@AMDEP_TRUE@ ./$(DEPDIR)/lock.Po ./$(DEPDIR)/log.Po \
2773 -@AMDEP_TRUE@ ./$(DEPDIR)/login.Po ./$(DEPDIR)/logmsg.Po \
2774 -@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/mkmodules.Po \
2775 -@AMDEP_TRUE@ ./$(DEPDIR)/modules.Po ./$(DEPDIR)/myndbm.Po \
2776 -@AMDEP_TRUE@ ./$(DEPDIR)/no_diff.Po ./$(DEPDIR)/parseinfo.Po \
2777 -@AMDEP_TRUE@ ./$(DEPDIR)/patch.Po ./$(DEPDIR)/rcs.Po \
2778 -@AMDEP_TRUE@ ./$(DEPDIR)/rcscmds.Po ./$(DEPDIR)/recurse.Po \
2779 -@AMDEP_TRUE@ ./$(DEPDIR)/release.Po ./$(DEPDIR)/remove.Po \
2780 -@AMDEP_TRUE@ ./$(DEPDIR)/repos.Po ./$(DEPDIR)/root.Po \
2781 -@AMDEP_TRUE@ ./$(DEPDIR)/run.Po ./$(DEPDIR)/scramble.Po \
2782 -@AMDEP_TRUE@ ./$(DEPDIR)/server.Po ./$(DEPDIR)/stack.Po \
2783 -@AMDEP_TRUE@ ./$(DEPDIR)/status.Po ./$(DEPDIR)/subr.Po \
2784 -@AMDEP_TRUE@ ./$(DEPDIR)/tag.Po ./$(DEPDIR)/update.Po \
2785 -@AMDEP_TRUE@ ./$(DEPDIR)/vers_ts.Po ./$(DEPDIR)/version.Po \
2786 -@AMDEP_TRUE@ ./$(DEPDIR)/watch.Po ./$(DEPDIR)/wrapper.Po \
2787 -@AMDEP_TRUE@ ./$(DEPDIR)/zlib.Po
2788 +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/acl.Po ./$(DEPDIR)/add.Po \
2789 +@AMDEP_TRUE@ ./$(DEPDIR)/admin.Po ./$(DEPDIR)/annotate.Po \
2790 +@AMDEP_TRUE@ ./$(DEPDIR)/buffer.Po ./$(DEPDIR)/checkin.Po \
2791 +@AMDEP_TRUE@ ./$(DEPDIR)/checkout.Po ./$(DEPDIR)/classify.Po \
2792 +@AMDEP_TRUE@ ./$(DEPDIR)/client.Po ./$(DEPDIR)/commit.Po \
2793 +@AMDEP_TRUE@ ./$(DEPDIR)/create_adm.Po ./$(DEPDIR)/cvsrc.Po \
2794 +@AMDEP_TRUE@ ./$(DEPDIR)/diff.Po ./$(DEPDIR)/edit.Po \
2795 +@AMDEP_TRUE@ ./$(DEPDIR)/entries.Po ./$(DEPDIR)/error.Po \
2796 +@AMDEP_TRUE@ ./$(DEPDIR)/expand_path.Po ./$(DEPDIR)/fileattr.Po \
2797 +@AMDEP_TRUE@ ./$(DEPDIR)/filesubr.Po ./$(DEPDIR)/find_names.Po \
2798 +@AMDEP_TRUE@ ./$(DEPDIR)/hardlink.Po ./$(DEPDIR)/hash.Po \
2799 +@AMDEP_TRUE@ ./$(DEPDIR)/history.Po ./$(DEPDIR)/ignore.Po \
2800 +@AMDEP_TRUE@ ./$(DEPDIR)/import.Po ./$(DEPDIR)/lock.Po \
2801 +@AMDEP_TRUE@ ./$(DEPDIR)/log.Po ./$(DEPDIR)/login.Po \
2802 +@AMDEP_TRUE@ ./$(DEPDIR)/logmsg.Po ./$(DEPDIR)/main.Po \
2803 +@AMDEP_TRUE@ ./$(DEPDIR)/mkmodules.Po ./$(DEPDIR)/modules.Po \
2804 +@AMDEP_TRUE@ ./$(DEPDIR)/myndbm.Po ./$(DEPDIR)/no_diff.Po \
2805 +@AMDEP_TRUE@ ./$(DEPDIR)/parseinfo.Po ./$(DEPDIR)/patch.Po \
2806 +@AMDEP_TRUE@ ./$(DEPDIR)/rcs.Po ./$(DEPDIR)/rcscmds.Po \
2807 +@AMDEP_TRUE@ ./$(DEPDIR)/recurse.Po ./$(DEPDIR)/release.Po \
2808 +@AMDEP_TRUE@ ./$(DEPDIR)/remove.Po ./$(DEPDIR)/repos.Po \
2809 +@AMDEP_TRUE@ ./$(DEPDIR)/root.Po ./$(DEPDIR)/run.Po \
2810 +@AMDEP_TRUE@ ./$(DEPDIR)/scramble.Po ./$(DEPDIR)/server.Po \
2811 +@AMDEP_TRUE@ ./$(DEPDIR)/stack.Po ./$(DEPDIR)/status.Po \
2812 +@AMDEP_TRUE@ ./$(DEPDIR)/subr.Po ./$(DEPDIR)/tag.Po \
2813 +@AMDEP_TRUE@ ./$(DEPDIR)/update.Po ./$(DEPDIR)/vers_ts.Po \
2814 +@AMDEP_TRUE@ ./$(DEPDIR)/version.Po ./$(DEPDIR)/watch.Po \
2815 +@AMDEP_TRUE@ ./$(DEPDIR)/wrapper.Po ./$(DEPDIR)/zlib.Po
2816 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
2817 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
2823 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Po@am__quote@
2824 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Po@am__quote@
2825 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@
2826 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate.Po@am__quote@
2827 diff -urN cvs-1.11.17.orig/src/mkmodules.c cvs-1.11.17/src/mkmodules.c
2828 --- cvs-1.11.17.orig/src/mkmodules.c 2004-02-03 15:39:40.000000000 +0100
2829 +++ cvs-1.11.17/src/mkmodules.c 2004-08-04 10:40:18.641722680 +0200
2830 @@ -311,6 +311,44 @@
2835 +static const char *const aclconfig_contents[] = {
2836 + "# Set `UseCVSACL' to yes to use CVSACL feature.\n",
2837 + "UseCVSACL=yes\n",
2839 + "# Default CVSACL Permission to use.\n",
2840 + "#CVSACLDefaultPermissions=p\n",
2842 + "# Default file location for CVS ACL file (access) is CVSROOT/access.\n",
2843 + "# If you want to use a different location, define it below.\n",
2844 + "#CVSACLFileLocation=/path/to/cvs/access\n",
2846 + "# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).\n",
2847 + "UseSystemGroups=yes\n",
2849 + "# Set `UseCVSGroups' to yes to use another group file.\n",
2850 + "#UseCVSGroups=yes\n",
2852 + "# Default file location for CVS groups file is CVSROOT/group.\n",
2853 + "# If you want to use a different location, define it below.\n",
2854 + "#CVSGroupsFileLocation=/path/to/cvs/group\n",
2856 + "# Set UseSeparateACLFileForEachDir to yes in order to use a\n",
2857 + "# separate 'access' file for each directory.\n",
2858 + "# This increased the performance if you have really big repository.\n",
2859 + "#UseSeparateACLFileForEachDir=no\n",
2861 + "# If StopAtFirstPermissionDenied is set to yes\n",
2862 + "# operation will stop at first permission denied message.\n",
2863 + "# Default is no.\n",
2864 + "#StopAtFirstPermissionDenied=no\n",
2866 + "# Set CVSServerRunAsUser to a system user, in order CVS server\n",
2868 + "#CVSServerRunAsUser=runascvsuser",
2872 static const struct admin_file filelist[] = {
2873 {CVSROOTADM_LOGINFO,
2874 "no logging of 'cvs commit' messages is done without a %s file",
2875 @@ -373,7 +411,12 @@
2877 "a %s file configures various behaviors",
2879 - {NULL, NULL, NULL}
2881 + /* cvsacl patch */
2882 + {CVSROOTADM_ACLCONFIG,
2883 + "a %s file configures Access Control List behaviors",
2884 + aclconfig_contents},
2885 + {NULL, NULL, NULL}
2888 /* Rebuild the checked out administrative files in directory DIR. */
2889 @@ -957,6 +1000,26 @@
2890 because xchmod() is too shy. */
2894 + /* cvsacl patch */
2895 + /* Make an empty 'CVSROOT/access' file */
2896 + strcpy (info, adm);
2897 + strcat (info, "/");
2898 + strcat (info, CVSROOTADM_ACCESS);
2899 + if (!isfile (info))
2903 + fp = open_file (info, "w");
2904 + if (fputs ("# CVS ACL definitions file. DO NOT EDIT MANUALLY\n",
2906 + error (1, errno, "cannot write %s", info);
2908 + if (fclose (fp) < 0)
2909 + error (1, errno, "cannot close %s", info);
2911 + chmod (info, 0644);
2914 /* Make an empty val-tags file to prevent problems creating it later. */
2916 diff -urN cvs-1.11.17.orig/src/parseinfo.c cvs-1.11.17/src/parseinfo.c
2917 --- cvs-1.11.17.orig/src/parseinfo.c 2004-03-19 21:36:39.000000000 +0100
2918 +++ cvs-1.11.17/src/parseinfo.c 2004-08-04 10:40:18.643722376 +0200
2919 @@ -448,3 +448,192 @@
2925 +parse_aclconfig (cvsroot)
2930 + char *line = NULL;
2931 + size_t line_allocated = 0;
2934 + /* FIXME-reentrancy: If we do a multi-threaded server, this would need
2935 + to go to the per-connection data structures. */
2936 + static int parsed = 0;
2938 + /* Authentication code and serve_root might both want to call us.
2939 + Let this happen smoothly. */
2944 + infopath = xmalloc (strlen (cvsroot)
2945 + + sizeof (CVSROOTADM_ACLCONFIG)
2946 + + sizeof (CVSROOTADM)
2948 + if (infopath == NULL)
2950 + error (0, 0, "out of memory; cannot allocate infopath");
2951 + goto error_return;
2954 + strcpy (infopath, cvsroot);
2955 + strcat (infopath, "/");
2956 + strcat (infopath, CVSROOTADM);
2957 + strcat (infopath, "/");
2958 + strcat (infopath, CVSROOTADM_ACLCONFIG);
2960 + fp_info = CVS_FOPEN (infopath, "r");
2961 + if (fp_info == NULL)
2963 + /* If no file, don't do anything special. */
2964 + if (!existence_error (errno))
2966 + /* Just a warning message; doesn't affect return
2967 + value, currently at least. */
2968 + error (0, errno, "cannot open %s", infopath);
2974 + while (getline (&line, &line_allocated, fp_info) >= 0)
2976 + /* Skip comments. */
2977 + if (line[0] == '#')
2980 + len = strlen (line) - 1;
2981 + if (line[len] == '\n')
2984 + /* Skip blank lines. */
2985 + if (line[0] == '\0')
2988 + /* The first '=' separates keyword from value. */
2989 + p = strchr (line, '=');
2992 + /* Probably should be printing line number. */
2993 + error (0, 0, "syntax error in %s: line '%s' is missing '='",
2995 + goto error_return;
3000 + if (strcmp (line, "UseCVSACL") == 0)
3002 + if (strcmp (p, "no") == 0)
3004 + else if (strcmp (p, "yes") == 0)
3008 + error (0, 0, "unrecognized value '%s' for UseCVSACL", p);
3009 + goto error_return;
3012 + else if (strcmp (line, "UseSeparateACLFileForEachDir") == 0)
3014 + if (strcmp (p, "no") == 0)
3015 + use_separate_acl_file_for_each_dir = 0;
3016 + else if (strcmp (p, "yes") == 0)
3017 + use_separate_acl_file_for_each_dir = 1;
3020 + error (0, 0, "unrecognized value '%s' for UseSeparateACLFileForEachDir", p);
3021 + goto error_return;
3024 + else if (strcmp (line, "StopAtFirstPermissionDenied") == 0)
3026 + if (strcmp (p, "no") == 0)
3027 + stop_at_first_permission_denied = 0;
3028 + else if (strcmp (p, "yes") == 0)
3029 + stop_at_first_permission_denied = 1;
3032 + error (0, 0, "unrecognized value '%s' for StopAtFirstPermissionDenied", p);
3033 + goto error_return;
3036 + else if (strcmp (line, "CVSACLDefaultPermissions") == 0)
3038 + if (cvs_acl_default_permissions != NULL)
3039 + free (cvs_acl_default_permissions);
3040 + if (!given_perms_valid (p))
3041 + error (1,0,"Invalid CVS ACL Default Permissions: '%s' in CVSROOT/aclconfig", p);
3042 + cvs_acl_default_permissions = xstrdup (p);
3044 + else if (strcmp (line, "UseCVSGroups") == 0)
3046 + if (strcmp (p, "no") == 0)
3047 + use_cvs_groups = 0;
3048 + else if (strcmp (p, "yes") == 0)
3049 + use_cvs_groups = 1;
3052 + error (0, 0, "unrecognized value '%s' for UseCVSGroups", p);
3053 + goto error_return;
3056 + else if (strcmp (line, "UseSystemGroups") == 0)
3058 + if (strcmp (p, "no") == 0)
3059 + use_system_groups = 0;
3060 + else if (strcmp (p, "yes") == 0)
3061 + use_system_groups = 1;
3064 + error (0, 0, "unrecognized value '%s' for UseSystemGroups", p);
3065 + goto error_return;
3068 + else if (strcmp (line, "CVSACLFileLocation") == 0)
3070 + if (cvs_acl_file_location != NULL)
3071 + free (cvs_acl_file_location);
3072 + cvs_acl_file_location = xstrdup (p);
3074 + else if (strcmp (line, "CVSGroupsFileLocation") == 0)
3076 + if (cvs_groups_file_location != NULL)
3077 + free (cvs_groups_file_location);
3078 + cvs_groups_file_location = xstrdup (p);
3080 + else if (strcmp (line, "CVSServerRunAsUser") == 0)
3082 + if (cvs_server_run_as != NULL)
3083 + free (cvs_server_run_as);
3084 + cvs_server_run_as = xstrdup (p);
3089 + if (ferror (fp_info))
3091 + error (0, errno, "cannot read %s", infopath);
3092 + goto error_return;
3094 + if (fclose (fp_info) < 0)
3096 + error (0, errno, "cannot close %s", infopath);
3097 + goto error_return;
3105 + if (infopath != NULL)
3112 diff -urN cvs-1.11.17.orig/src/patch.c cvs-1.11.17/src/patch.c
3113 --- cvs-1.11.17.orig/src/patch.c 2004-04-02 21:25:32.000000000 +0200
3114 +++ cvs-1.11.17/src/patch.c 2004-08-04 10:40:18.645722072 +0200
3115 @@ -498,6 +498,43 @@
3120 +#ifdef SERVER_SUPPORT
3121 + if (use_cvs_acl && server_active)
3125 + if (!access_allowed (finfo->file, finfo->repository, rev1, 5,
3128 + if (stop_at_first_permission_denied)
3129 + error (1, 0, "permission denied for %s",
3130 + Short_Repository (finfo->repository));
3132 + error (0, 0, "permission denied for %s/%s",
3133 + Short_Repository (finfo->repository), finfo->file);
3140 + if (!access_allowed (finfo->file, finfo->repository, rev2, 5,
3143 + if (stop_at_first_permission_denied)
3144 + error (1, 0, "permission denied for %s",
3145 + Short_Repository (finfo->repository));
3147 + error (0, 0, "permission denied for %s/%s",
3148 + Short_Repository (finfo->repository), finfo->file);
3156 /* Create 3 empty files. I'm not really sure there is any advantage
3157 * to doing so now rather than just waiting until later.
3159 diff -urN cvs-1.11.17.orig/src/remove.c cvs-1.11.17/src/remove.c
3160 --- cvs-1.11.17.orig/src/remove.c 2004-03-20 03:34:32.000000000 +0100
3161 +++ cvs-1.11.17/src/remove.c 2004-08-04 10:40:18.648721616 +0200
3162 @@ -250,6 +250,25 @@
3167 +#ifdef SERVER_SUPPORT
3168 + if (use_cvs_acl && server_active)
3170 + if (!access_allowed (finfo->file, finfo->repository, vers->tag, 7,
3173 + if (stop_at_first_permission_denied)
3174 + error (1, 0, "permission denied for %s",
3175 + Short_Repository (finfo->repository));
3177 + error (0, 0, "permission denied for %s/%s",
3178 + Short_Repository (finfo->repository), finfo->file);
3185 /* Re-register it with a negative version number. */
3186 fname = xmalloc (strlen (vers->vn_user) + 5);
3187 (void) strcpy (fname, "-");
3188 diff -urN cvs-1.11.17.orig/src/server.c cvs-1.11.17/src/server.c
3189 --- cvs-1.11.17.orig/src/server.c 2004-08-04 10:31:54.000000000 +0200
3190 +++ cvs-1.11.17/src/server.c 2004-08-04 10:40:18.656720400 +0200
3191 @@ -773,6 +773,10 @@
3192 nothing. But for rsh, we need to do it now. */
3193 parse_config (current_parsed_root->directory);
3195 + /* cvsacl patch */
3196 + parse_aclconfig (current_parsed_root->directory);
3199 path = xmalloc (strlen (current_parsed_root->directory)
3200 + sizeof (CVSROOTADM)
3202 @@ -3761,6 +3765,23 @@
3203 do_cvs_command ("rlog", cvslog);
3211 + do_cvs_command ("acl", cvsacl);
3219 + cvs_cmd_name = "racl";
3220 + do_cvs_command ("racl", cvsacl);
3226 @@ -4820,6 +4841,11 @@
3227 REQ_LINE("diff", serve_diff, 0),
3228 REQ_LINE("log", serve_log, 0),
3229 REQ_LINE("rlog", serve_rlog, 0),
3231 + /* cvsacl patch */
3232 + REQ_LINE("acl", serve_acl, 0),
3233 + REQ_LINE("racl", serve_racl, 0),
3235 REQ_LINE("add", serve_add, 0),
3236 REQ_LINE("remove", serve_remove, 0),
3237 REQ_LINE("update-patches", serve_ignore, 0),
3238 @@ -5293,6 +5319,10 @@
3242 + /* cvsacl patch */
3243 + if (use_cvs_acl && cvs_server_run_as)
3244 + username = cvs_server_run_as;
3246 pw = getpwnam (username);
3249 @@ -5875,6 +5905,9 @@
3250 in a new CVSROOT/config file to fix the broken one! */
3251 parse_config (repository);
3253 + /* cvsacl patch */
3254 + parse_aclconfig (repository);
3256 /* We need the real cleartext before we hash it. */
3257 descrambled_password = descramble (password);
3258 host_user = check_password (username, descrambled_password, repository);
3259 diff -urN cvs-1.11.17.orig/src/status.c cvs-1.11.17/src/status.c
3260 --- cvs-1.11.17.orig/src/status.c 2004-03-20 02:40:12.000000000 +0100
3261 +++ cvs-1.11.17/src/status.c 2004-08-04 10:40:18.658720096 +0200
3262 @@ -128,7 +128,27 @@
3264 status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
3266 - sstat = "Classify Error";
3269 +#ifdef SERVER_SUPPORT
3270 + if (use_cvs_acl && server_active)
3272 + if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3275 + if (stop_at_first_permission_denied)
3276 + error (1, 0, "permission denied for %s",
3277 + Short_Repository (finfo->repository));
3279 + error (0, 0, "permission denied for %s/%s",
3280 + Short_Repository (finfo->repository), finfo->file);
3287 + sstat = "Classify Error";
3291 diff -urN cvs-1.11.17.orig/src/tag.c cvs-1.11.17/src/tag.c
3292 --- cvs-1.11.17.orig/src/tag.c 2004-04-06 20:37:10.000000000 +0200
3293 +++ cvs-1.11.17/src/tag.c 2004-08-04 10:40:18.661719640 +0200
3294 @@ -660,6 +660,25 @@
3295 * correctly without breaking your link!
3299 +#ifdef SERVER_SUPPORT
3300 + if (use_cvs_acl && server_active)
3302 + if (!access_allowed (finfo->file, finfo->repository, numtag, 4,
3305 + if (stop_at_first_permission_denied)
3306 + error (1, 0, "permission denied for %s",
3307 + Short_Repository (finfo->repository));
3309 + error (0, 0, "permission denied for %s/%s",
3310 + Short_Repository (finfo->repository), finfo->file);
3318 return (rtag_delete (rcsfile));
3320 @@ -880,6 +899,21 @@
3321 if (nversion == NULL)
3322 goto free_vars_and_return;
3326 +#ifdef SERVER_SUPPORT
3327 + if (use_cvs_acl && server_active)
3329 + if (!access_allowed (finfo->file, finfo->repository, vers->tag, 4,
3332 + error (0, 0, "permission denied for %s/%s",
3333 + Short_Repository (finfo->repository), finfo->file);
3342 diff -urN cvs-1.11.17.orig/src/update.c cvs-1.11.17/src/update.c
3343 --- cvs-1.11.17.orig/src/update.c 2004-05-04 19:25:54.000000000 +0200
3344 +++ cvs-1.11.17/src/update.c 2004-08-04 10:40:18.664719184 +0200
3345 @@ -596,6 +596,26 @@
3346 status = Classify_File (finfo, tag, date, options, force_tag_match,
3347 aflag, &vers, pipeout);
3351 +#ifdef SERVER_SUPPORT
3352 + if (use_cvs_acl && server_active)
3354 + if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3357 + if (stop_at_first_permission_denied)
3358 + error (1, 0, "permission denied for %s",
3359 + Short_Repository (finfo->repository));
3361 + error (0, 0, "permission denied for %s/%s",
3362 + Short_Repository (finfo->repository), finfo->file);
3369 /* Keep track of whether TAG is a branch tag.
3370 Note that if it is a branch tag in some files and a nonbranch tag
3371 in others, treat it as a nonbranch tag. It is possible that case
3372 diff -urN cvs-1.11.17.orig/src/version.c cvs-1.11.17/src/version.c
3373 --- cvs-1.11.17.orig/src/version.c 2004-02-03 15:37:56.000000000 +0100
3374 +++ cvs-1.11.17/src/version.c 2004-08-04 10:40:18.669718424 +0200
3381 +char *aclpatch_string = "with CVSACL Patch 1.2.1 (cvsacl.sourceforge.net)\n";
3383 static const char *const version_usage[] =
3387 (void) fputs (PACKAGE_STRING, stdout);
3388 (void) fputs (config_string, stdout);
3389 + /* cvsacl patch */
3390 + (void) fputs (aclpatch_string, stdout);
3392 #ifdef CLIENT_SUPPORT
3393 if (current_parsed_root && current_parsed_root->isremote)