]> git.pld-linux.org Git - packages/cvs.git/blame - cvs-acl.patch
- updated for 1.11.18
[packages/cvs.git] / cvs-acl.patch
CommitLineData
4905fec9 1diff -urN cvs-1.11.18.orig/INSTALL.cvsacl cvs-1.11.18/INSTALL.cvsacl
2--- cvs-1.11.18.orig/INSTALL.cvsacl 1970-01-01 01:00:00.000000000 +0100
3+++ cvs-1.11.18/INSTALL.cvsacl 2004-11-14 14:00:39.000000000 +0100
09f63587 4@@ -0,0 +1,23 @@
5+
6+Installation
7+
8+- copy the file acl.c under src directory of CVS source distribution.
c52fdbcd 9+ "cp acl.c /path/to/cvs-1.11.17/src/"
67ba4c3a 10+- copy the patch file cvsacl-patch-1.2.1 under CVS source distribution
09f63587 11+ directory.
67ba4c3a 12+ "cp cvsacl-patch-1.2.1 /path/to/cvs-1.11.17/"
09f63587 13+- cd to CVS source directory.
c52fdbcd 14+ "cd /path/to/cvs-1.11.17/"
09f63587 15+- apply the patch.
67ba4c3a 16+ "patch -p0 < cvsacl-patch-1.2.1"
09f63587 17+- if you are initializing the repository after applying patch, related
18+ config files will be created with init command.
19+ "cvs -d /path/to/repository init"
20+- if you already have a repository, you have to add the aclconfig file
21+ to your $CVSROOT/CVSROOT/. aclconfig.default is the default configuration
22+ file, you can rename it to aclconfig, and use it .
23+- modify aclconfig file, if you need to change some options.
24+- as the last step, you have to define yourself as acl administrator.
25+ "cvs -d /path/to/repository racl yourname:p -r ALL -d ALL"
26+ this command gives p (acl admin) rights to user (yourname),
27+ on all repository and tags/branches.
4905fec9 28diff -urN cvs-1.11.18.orig/README.cvsacl cvs-1.11.18/README.cvsacl
29--- cvs-1.11.18.orig/README.cvsacl 1970-01-01 01:00:00.000000000 +0100
30+++ cvs-1.11.18/README.cvsacl 2004-11-14 14:00:39.000000000 +0100
09f63587 31@@ -0,0 +1,282 @@
32+
33+CVS Access Control List Extension Patch
34+
35+http://cvsacl.sourceforge.net/
36+sbaris@users.sourceforge.net
37+
38+CVSACL is a patch for CVS. It adds two new subcommands
39+(acl & racl) to cvs for access control list management. It
40+provides advanced ACL definitions per modules, directories,
41+and files on branch/tag for remote cvs repository connections.
42+Execution of all CVS subcommands can be controlled with eight
43+different permissions.
44+ACL definitions works for only remote connections, local users
45+can access and modify repository, if unix file system permissions
46+allow. If you want all users to make remote connections to
47+repository, and not allow local users to access repository, you
48+have to set CVSServerRunAsUser keyword in aclconfig file
49+(explained below).
50+Still local users can use acl and racl subcommands to set
51+permissions on directories or files if they have acl admin rights (p)
52+on related directories or files.
53+So, in order to control all access to repository with this ACL
54+extension, you should use CVSServerRunAsUser keyword and force all
55+users to make remote connections. CVS repository administrator or
56+project managers have to use acl and racl subcommands to manage
57+permissions. But there is no gui client supporting these subcommands,
58+so you have to use cvs client itself either locally or remotely.
59+
60+
61+
62+
63+Permission Types
64+
65+- no access
66+ Command line character: n
67+ If a user given n permission, it is not allowed for any action on repository.
68+- read
69+ Command line character: r
70+ r permission gives only read access on repository.
71+ With r permission you are allowed to run cvs subcommands: annotate,
72+ checkout, diff, export, log, rannotate, rdiff, rlog, status.
73+- write
74+ Command line character: w
75+ w permission allows only cvs commit/checkin action.
76+ With w permission, you are not allowed to add/remove any file to/from
77+ repository, other permissions should be defines for that.
78+- tag
79+ Command line character: t
80+ t permission allows cvs tag and rtag subcommands to run, so you may
81+ control tagging and untagging operations. t permission includes r
82+ permission, since without reading you can not tag/untag a file.
83+ However t permission does not include write permission, you can not
84+ commit a file with only t permission.
85+- create
86+ Command line character: c
87+ c permission allows cvs add and import subcommands to run. To add or
88+ import a file/directory to repository, you have to given a c
89+ permission. Again, c permission does not include write permission,
90+ thus you may only add or import files, but you can not modify any
91+ existing file. After issuing add subcommand, you have to commit the file
92+ to complete adding. This commit subcommand is allowed because you are
93+ adding file and not modifying existing one.
94+- delete
95+ Command line character: d
96+ d permission allows cvs remove command to run. To remove a file/directory
97+ from repository, d permission have to set. It does not include write
98+ permission, so you can not modify contents of an existing file on repository.
99+- full access except admin rights
100+ Command line character: a
101+ a permission gives all access (above permissions) to repository, but it
102+ can not modify permissions. Only acl admins may modify the acl definitions.
103+- acl admin
104+ Command line character: p
105+ p permission means that user is an acl admin, so it is allowed to make anything on repository.
106+
107+
108+ACL Config Keywords
109+The administrative file aclconfig contains miscellaneous settings which
110+affect the behaviour of ACL extension. Currently defined keywords are:
111+
112+UseCVSACL=value
113+Use ACL definitions if set to yes. If you do not want to use ACLs for
114+some repositories in a patched CVS server, set this keyword to no. The default is no.
115+
116+UseCVSACLDefaultPermissions=value
117+Value can be any combination of valid permission types (w,r,t,c,d,t,a,p).
118+if there is no defined ACL and default permission in access file, or no
119+access file at all, this permissions are used. The default is p (admin rights),
120+if aclconfig file is created with cvs init.
121+
122+UseCVSGroups=value
123+CVS does not have a CVSROOT/passwd file. However it can be created manually
124+(format should be same as /etc/group). If value set to yes, CVS checks for
125+groups in file $CVSROOT/CVSROOT/group The default value is no.
126+
127+UseSystemGroups=value
128+Group memberships for users are checked in file /etc/group, if value is set
129+to yes. The default value is no.
130+
131+CVSACLFileLocation=value
132+Originally access file is put under CVSROOT/CVSROOT, if you want a different
133+location, set value to a valid path. The default value is $CVSROOT/CVSROOT/access.
134+
135+CVSGroupsFileLocation=value
136+IF UseCVSGroups is set to yes, CVS looks for a group file under $CVSROOT/CVSROOT.
137+To use a different location for group file set value to a valid path to group.
138+The default value is $CVSROOT/CVSROOT/group.
139+
c52fdbcd 140+UseSeparateACLFileForEachDir=value
141+If value is set to yes, a separate ACL file (access) is created for each
09f63587 142+directory in repository. If you have a really big repository
143+(directories>10,000 and files>100,000), performance may drop due to a big
144+acl file, access. Setting the value to yes, may increase performance. Normally,
145+you will not need this. The default value is no.
146+
147+StopAtFirstPermissionDenied=value
148+If StopAtFirstPermissionDenied is set to yes
149+operation will stop at first permission denied message.
150+e.g. when you send commit command for a directory, if you dont
151+have write permission for just one file under the directory,
152+by default you will have a warning and commit will continue
153+on the other files. If you set this keyword to 'no', then
154+commit operation will be stopped when inaccassable file found.
155+Default is no.
156+
157+CVSServerRunAsUser=value
158+Set CVSServerRunAsUser keyword to a valid system user.
159+When a user make a remote connection to CVS, after successfull authentication
160+cvs process switch to run as that user, or defined system user in
161+$CVSROOT/CVSROOT/passwd. So, you also have to set unix file permissions accordingly.
162+A better solution:
163+Add a user and group such as both cvsadm.
164+Set CVSServerRunAsUser keyword to cvsadm.
165+Change unix file system permissions for your repository,
166+make cvsadm user and group owner, and read,write,execute permissions and setgid.
167+(chown cvsadm -R /path/to/your/repository)
168+(chgrp cvsadm -R /path/to/your/repository)
169+(chmod 2770 -R /path/to/your/repository)
170+Add yourself to cvsadm group (since you are ACL administrator).
171+Therefore, only users making remote connections will have access to repository
172+if you give rights. Local users can not access to repository via a cvs client or directly.
173+
174+
175+Command Line Usage Information
176+acl command is used on checked out files or directories. racl command is
177+used on repository without a working copy. Usage information can be obtained
178+with standard cvs --help command.
179+Output of cvs --help acl and cvs --help racl:
180+
181+Usage: cvs racl [user||group:permissions] [-Rl] [-r tag]
182+ -d [directory] -f [file]
183+ -R Process directories recursively.
184+ -r rev Existing revision/tag.
185+ -l List defined ACLs.
186+ -d dir Process on given directory.
187+ -f file Process on given file.
188+
189+Usage: cvs acl [user||group:permissions] [-Rl] [-r tag]
190+ -d [directory] -f [file]
191+ -R Process directories recursively.
192+ -r rev Existing revision/tag.
193+ -l List defined ACLs.
194+ -d dir Process on given directory.
195+ -f file Process on given file.
196+
197+You may directly set permissions for a user or group or add/remove
198+permissions with + and - signs to/from existing permissions.
199+If you do not give the branch/tag information, default value of HEAD
200+(main branch) will be used. You have to give branch/tag name with -r option.
201+You may type ALL for branch/tag field.
202+
203+While checking for permissions, it goes thorough the list below. So the highest
204+significant permission is the first item in list.
205+
206+- permissions assigned to username for specific directory or file.
207+- permissions assigned to group name for specific directory or file.
208+- permissions as defaults for specific directory or file.
209+- permissions assigned to parent folders (inherits from the first parent
210+ which permissions are assigned).
211+- permissions as repository defaults.
212+- permissions in aclconfig file.
213+
214+
215+
216+
217+Examples
218+ /cvs/
219+ |
220+ |
221+ +--projectA/
222+ | |
223+ | +---CVSROOT/
224+ | |
225+ | +---lib/
226+ | | |
227+ | | +---gnulib/
228+ | | |
229+ | | +---zlib/
230+ | |
231+ | +---src/
232+ | | |
233+ | | +---main.c
234+ | | |
235+ | | +---server.c
236+ | | |
237+ | | +---client.c
238+ | |
239+ | +---gui/
240+ |
241+ +--projectB/
242+We have above directory structure for a cvs repository, and no defined permissions.
243+
244+Setting main default permissions:
245+
246+$ cvs -d /cvs/projectA racl cvsadmin:p -r ALL -d ALL
247+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
248+User cvsadmin will be an acl admin, and all other users will have only read
249+rights on all branches/tags in projectA repository. This is the default acl
250+definition and it overwrites default permissions in $CVSROOT/CVSROOT/aclconfig file.
251+
252+$ cvs -d /cvs/projectA racl ALL:r -r ALL -d ALL
253+$ cvs -d /cvs/projectA racl ALL:n -r ALL -d gui
254+After executing these two commands, all users will have read access on all
255+directories and files except gui directory. Everyone will be denied to access to gui
256+directory becase no access, n, permissions is set.
257+
258+Setting permissions directly on a file or directory:
259+
260+$ cvs -d /cvs/projectA racl userX:wcd -d lib
261+$ cvs -d /cvs/projectA racl group1:w -d lib
262+First command will set write, create, and delete permissions for userX on directory
263+lib with branch HEAD (since no branch/tag information given, branch defaults to HEAD).
264+Second command will set only write permission for group1 on directory lib with branch HEAD.
265+Members of group1 will have only commit rights on lib directory, branch HEAD, they can
266+not add or remove any file, just modify existing files.
267+If userX is also a member of group1, userX will have write, create, and delete permissions
268+because it is specifically given these permissions.
269+
270+$ cvs -d /cvs/projectA racl userY:wcd -r develStream -d lib
271+$ cvs -d /cvs/projectA racl userY:r -r integStream -d lib
272+These commands will give wcd permissions to userY on lib directory with tag develstream,
273+and r permissions on lib directory with tag integStream.
274+
275+$ cvs -d /cvs/projectA racl userZ:wcd -d src
276+$ cvs -d /cvs/projectA racl userZ:r -f src/main.c
277+First command will give wcd permissions to userZ on src directory, but only read
278+permission on file main.c in src directory.
279+
280+Using + and - signs to set permissions on a file or directory:
281+
282+$ cvs -d /cvs/projectA racl userZ:+t -d src
283+$ cvs -d /cvs/projectA racl userZ:-cd -d src
284+$ cvs -d /cvs/projectA racl userZ:-wt -d src
285+Before the first command, userZ has wcd permissions on src directory, after issuing
286+command it will have wcdt permissions. Tag permission will be added. UserZ has wcdt
287+permissions, and we execute the second command to remove create and delete permissions.
288+So userZ has wt permissions. In the last command we also remove wt permissions, finally
289+userZ has no defined permissions left, and it will use the default permissions if set.
290+
291+Listing permissions on a file or directory:
292+
293+$ cvs -d /cvs/projectA racl -l -d src
294+$ cvs -d /cvs/projectA racl -l -f src
295+$ cvs -d /cvs/projectA racl -l -f src/main.c
296+
297+First command will list the permissions for src directory.
298+Example output:
299+d src HEAD | userX:wcd group1:r | defaults:r
300+userX and group1 has assigned permissions, all other users will have default
301+permissions, which is only read.
302+
303+Second command will list the permissions for files in src directory.
304+Example output:
305+f src/main.c HEAD | userX:wcd group1:r | defaults:r
306+f src/server.c HEAD | userX:wcd group1:r | defaults:r
307+f src/client.c HEAD | userX:wcd group1:r | defaults:r
308+
309+Third command will list the permissions for main.c file in src directory.
310+Example output:
311+f src/main.c HEAD | userX:wcd group1:r | defaults:r
312+
313+
4905fec9 314diff -urN cvs-1.11.18.orig/aclconfig.default cvs-1.11.18/aclconfig.default
315--- cvs-1.11.18.orig/aclconfig.default 1970-01-01 01:00:00.000000000 +0100
316+++ cvs-1.11.18/aclconfig.default 2004-11-14 14:00:39.000000000 +0100
317@@ -0,0 +1,33 @@
318+# Set `UseCVSACL' to yes to use CVS ACL feature.
319+UseCVSACL=yes
320+
321+# Default CVS ACL Permission are to use.
322+#CVSACLDefaultPermissions=a
323+
324+# Default file location for CVS ACL file (access) is CVSROOT/access.
325+# If you want to use a different location, define it below.
326+#CVSACLFileLocation=/path/to/cvs/access
327+
328+# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).
329+UseSystemGroups=yes
330+
331+# Set `UseCVSGroups' to yes to use another group file.
332+#UseCVSGroups=yes
333+
334+# Default file location for CVS groups file is CVSROOT/group.
335+# If you want to use a different location, define it below.
336+#CVSGroupsFileLocation=/path/to/cvs/group
337+
338+# Set UseSeparateACLFileForEachDir to yes in order to use a
339+# separate 'access' file for each directory.
340+# This increased the performance if you have really big repository.
341+#UseSeparateACLFileForEachDir=no
342+
343+# If StopAtFirstPermissionDenied is set to yes
344+# operation will stop at first permission denied message.
345+# Default is no.
346+#StopAtFirstPermissionDenied=no
347+
348+# Set CVSServerRunAsUser to a system user, in order CVS server
349+# to run as.
350+#CVSServerRunAsUser=runascvsuser
351diff -urN cvs-1.11.18.orig/src/Makefile.am cvs-1.11.18/src/Makefile.am
352--- cvs-1.11.18.orig/src/Makefile.am 2004-11-14 13:58:12.000000000 +0100
353+++ cvs-1.11.18/src/Makefile.am 2004-11-14 14:00:39.000000000 +0100
354@@ -29,6 +29,7 @@
355
356 # The cvs executable
357 cvs_SOURCES = \
358+ acl.c \
359 add.c \
360 admin.c \
361 annotate.c \
362diff -urN cvs-1.11.18.orig/src/Makefile.in cvs-1.11.18/src/Makefile.in
363--- cvs-1.11.18.orig/src/Makefile.in 2004-11-11 19:17:20.000000000 +0100
364+++ cvs-1.11.18/src/Makefile.in 2004-11-14 14:52:25.000000000 +0100
365@@ -67,11 +67,11 @@
366 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
367 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
368 PROGRAMS = $(bin_PROGRAMS)
369-am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \
370- buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \
371- classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \
372- create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \
373- edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
374+am_cvs_OBJECTS = acl.$(OBJEXT) add.$(OBJEXT) admin.$(OBJEXT) \
375+ annotate.$(OBJEXT) buffer.$(OBJEXT) checkin.$(OBJEXT) \
376+ checkout.$(OBJEXT) classify.$(OBJEXT) client.$(OBJEXT) \
377+ commit.$(OBJEXT) create_adm.$(OBJEXT) cvsrc.$(OBJEXT) \
378+ diff.$(OBJEXT) edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
379 expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \
380 find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \
381 history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \
382@@ -204,6 +204,7 @@
383
384 # The cvs executable
385 cvs_SOURCES = \
386+ acl.c \
387 add.c \
388 admin.c \
389 annotate.c \
390@@ -382,6 +383,7 @@
391 distclean-compile:
392 -rm -f *.tab.c
393
394+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Po@am__quote@
395 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Po@am__quote@
396 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@
397 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate.Po@am__quote@
398diff -urN cvs-1.11.18.orig/src/acl.c cvs-1.11.18/src/acl.c
399--- cvs-1.11.18.orig/src/acl.c 1970-01-01 01:00:00.000000000 +0100
400+++ cvs-1.11.18/src/acl.c 2004-11-14 14:00:39.000000000 +0100
67ba4c3a 401@@ -0,0 +1,2028 @@
09f63587 402+/*
403+ *
404+ * CVS ACCESS CONTROL LIST EXTENSION
405+ *
406+ * sbaris@users.sourceforge.net
407+ *
408+ * http://cvsacl.sourceforge.net/
409+ *
c52fdbcd 410+ * CVSACL is a patch for CVS versions
411+ * - cvs-1.11.17
412+ *
09f63587 413+ * It adds two new subcommands (acl & racl) to cvs for access control
414+ * list management.
415+ * It provides advanced ACL definitions per modules, directories,
416+ * and files on branch/tag for remote cvs repository connections.
417+ * Execution of all CVS subcommands can be controlled with eight
418+ * different permissions.
419+ * ACL definitions works for only remote connections, local users can
420+ * access and modify repository, if unix file system permissions allow.
421+ * If you want all users to make remote connections to repository,
422+ * and not allow local users to access repository, you have to set
423+ * CVSServerRunAsUser keyword in aclconfig file (explained below).
424+ * Still local users can use acl and racl subcommands to set permissions
425+ * on directories or files if they have acl admin rights (p) on related
426+ * directories or files.
427+ * So, in order to control all access to repository with this ACL extension,
428+ * you should use CVSServerRunAsUser keyword and force all users to make
429+ * remote connections.
430+ * CVS repository administrator or project managers have to use acl and racl
431+ * subcommands to manage permissions. But there is no gui client supporting
432+ * these subcommands, so you have to use cvs client itself either
433+ * locally or remotely.
434+ *
435+ *
436+ * Permission Types:
437+ * - no permission (n) (1)
438+ * - all permissions (a) (2)
439+ * - write permission (w) (3)
440+ * - tag permission (t) (4)
441+ * - read permission (r) (5)
442+ * - add permission (c) (6)
443+ * - remove permission (d) (7)
444+ * - permission change (p) (8)
445+ *
446+ *
447+ *
448+ *
449+ * ********************************************************************
450+ * This program is free software; you can redistribute it and/or modify
451+ * it under the terms of the GNU General Public License as published by
452+ * the Free Software Foundation; either version 1, or (at your option)
453+ * any later version.
454+ *
455+ * This program is distributed in the hope that it will be useful,
456+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
457+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
458+ * GNU General Public License for more details.
459+ * *******************************************************************
460+ *
461+ */
462+
463+#include "cvs.h"
464+#include "getline.h"
465+#include <grp.h>
466+
467+static int acl_fileproc PROTO ((void *callerdat, struct file_info *finfo));
468+static Dtype acl_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
469+ const char *update_dir, List *entries));
470+
471+static int acllist_fileproc PROTO ((void *callerdat, struct file_info *finfo));
472+static Dtype acllist_dirproc PROTO ((void *callerdat, const char *dir, const char *repos,
473+ const char *update_dir, List *entries));
474+
475+static void acllist_print PROTO ((char *line, const char *obj));
476+
477+static int racl_proc PROTO((int argc, char **argv, char *xwhere,
478+ char *mwhere, char *mfile, int shorten,
479+ int local_specified, char *mname, char *msg));
480+
67ba4c3a 481+FILE *open_accessfile (char *xmode, const char *repos, char **fname);
09f63587 482+FILE *open_groupfile (char *xmode);
483+
484+char *get_perms (char *xperms);
485+char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
486+
487+static char *cache_repository;
488+static int cache_retval;
489+static int founddeniedfile;
490+static int cache_perm;
491+
492+static int is_racl;
493+
494+int use_cvs_acl = 0;
495+char *cvs_acl_default_permissions;
496+int use_cvs_groups = 0;
497+int use_system_groups = 0;
c52fdbcd 498+int use_separate_acl_file_for_each_dir = 0;
09f63587 499+char *cvs_acl_file_location = NULL;
500+char *cvs_groups_file_location = NULL;
501+char *cvs_server_run_as = NULL;
502+int stop_at_first_permission_denied = 0;
503+
504+char *tag = NULL;
505+
506+char *muser;
507+char *mperms;
508+static int defaultperms;
509+
510+static char *default_perms_object;
511+char *default_part_perms_accessfile;
512+
513+int acldir = 0;
514+int aclfile = 0;
515+int listacl = 0;
516+
517+int userfound;
518+int groupfound;
519+
520+char *dirs[25];
521+
522+int aclconfig_default_used;
523+
524+static const char *const acl_usage[] =
525+ {
526+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
527+ "\t-R\tProcess directories recursively.\n",
528+ "\t-r rev\tExisting revision/tag.\n",
529+ "\t-l\tList defined ACLs.\n",
530+ "\t-d dir\tProcess on given directory.\n",
531+ "\t-f file\tProcess on given file.\n",
532+ "(Specify the --help global option for a list of other help options)\n",
533+ NULL
534+ };
535+
536+static const char *const racl_usage[] =
537+ {
538+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag]\n -d [directory] -f [file]\n",
539+ "\t-R\tProcess directories recursively.\n",
540+ "\t-r rev\tExisting revision/tag.\n",
541+ "\t-l\tList defined ACLs.\n",
542+ "\t-d dir\tProcess on given directory.\n",
543+ "\t-f file\tProcess on given file.\n",
544+ "(Specify the --help global option for a list of other help options)\n",
545+ NULL
546+ };
547+
548+
549+int
550+access_allowed (file, repos, tag, perm, mline, mpos, usecache)
551+char *file;
552+char *repos;
553+char *tag;
554+int perm;
555+char **mline;
556+int *mpos;
557+int usecache;
558+{
559+ int retval = 0;
560+ int foundline = 0;
561+ FILE *accessfp;
562+
563+ char *line = NULL;
564+ size_t line_allocated = 0;
565+
566+ char *part_type = NULL;
567+ char *part_object = NULL;
568+ char *part_tag = NULL;
569+ char *part_perms = NULL;
570+ char *xline;
67ba4c3a 571+ int x;
09f63587 572+
573+ char *iline;
574+
575+ char *tempv;
576+ char *tempc;
577+ size_t tempsize;
578+ int intcount;
579+
580+ int oneaccessfile = 0;
581+ int accessfilecount;
582+
67ba4c3a 583+ int signlevel = -1;
09f63587 584+
585+ int dadmin = 0;
586+
587+ const char *repository;
588+ char *filefullname = NULL;
589+
590+
591+ userfound = 0;
592+ groupfound = 0;
593+
594+
595+ if (defaultperms)
596+ {
597+ repository = xstrdup ("ALL");
598+ }
599+ else
600+ repository = Short_Repository (repos);
601+
602+ /* cache */
603+ if (usecache
604+ && cache_repository != NULL
605+ && strcmp (cache_repository, repository) == 0
606+ && !founddeniedfile
607+ && perm == cache_perm)
608+ return (cache_retval);
609+ else
610+ {
611+ free(cache_repository);
612+ cache_repository = xstrdup(repository);
613+ cache_perm = perm;
614+ }
615+
616+ if (file != NULL)
617+ {
618+ filefullname = xmalloc (strlen (repository)
619+ + strlen (file)
620+ + 2);
621+
622+ strcpy (filefullname, repository);
623+ strcat (filefullname, "/");
624+ strcat (filefullname, file);
625+ }
626+
627+
628+ iline = xstrdup(repository);
629+
630+ tempv = strtok(iline, "/\t");
631+ tempc = xstrdup(tempv);
632+ tempsize = strlen(tempc);
633+
634+ intcount = 0;
635+
636+ dirs[intcount] = xstrdup(tempc);
637+
638+ while ((tempv = strtok(NULL, "/\t")) != NULL)
639+ {
640+ intcount++;
641+
642+ xrealloc_and_strcat(&tempc, &tempsize, "/");
643+ xrealloc_and_strcat(&tempc, &tempsize, tempv);
644+
645+ dirs[intcount] = xstrdup(tempc);
646+ }
647+
648+ if (file != NULL)
649+ {
67ba4c3a 650+ accessfilecount = intcount;
09f63587 651+ intcount++;
652+ dirs[intcount] = xstrdup(filefullname);
653+ }
654+
67ba4c3a 655+ for (accessfilecount; accessfilecount >= 0 && !oneaccessfile; accessfilecount--)
09f63587 656+ {
c52fdbcd 657+ if (!use_separate_acl_file_for_each_dir)
09f63587 658+ oneaccessfile = 1;
c52fdbcd 659+ else if (use_separate_acl_file_for_each_dir)
09f63587 660+ oneaccessfile = 0;
661+
67ba4c3a 662+ if (acldir || aclfile)
663+ oneaccessfile = 1;
664+
09f63587 665+ if (oneaccessfile)
67ba4c3a 666+ accessfp = open_accessfile ("r", repository, NULL);
09f63587 667+ else
668+ accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
669+
670+ if (accessfp != NULL)
671+ {
672+ while (getline (&line, &line_allocated, accessfp) >= 0)
673+ {
67ba4c3a 674+
09f63587 675+ if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
676+ continue;
677+
678+ xline = xstrdup (line);
679+ part_type = strtok (line, ":\t");
680+ part_object = strtok (NULL, ":\t");
681+ part_tag = strtok (NULL, ":\t");
682+ part_perms = strtok (NULL, ":\t");
683+
67ba4c3a 684+ for (x = intcount; x >= signlevel && x != -1; x--)
09f63587 685+ {
686+ if (strcmp (dirs[x], part_object) == 0)
687+ {
688+ if (valid_tag (part_tag, tag))
689+ {
690+ foundline = 1;
691+
c52fdbcd 692+ if (listacl || acldir || aclfile)
09f63587 693+ {
694+ *mline = xstrdup (xline);
695+ *mpos = ftell (accessfp);
696+ }
697+
698+ if (valid_perm (part_perms, perm))
699+ {
700+ if (signlevel == x)
701+ {
702+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
703+ retval = 1;
704+ }
705+ else if (!aclconfig_default_used)
706+ {
707+ signlevel = x;
708+ retval = 1;
709+ }
67ba4c3a 710+ else {
711+ }
09f63587 712+ }
713+ else
714+ {
715+ if (signlevel == x)
716+ {
717+ if (strncmp(part_tag, "ALL", 3) != 0 && !aclconfig_default_used)
718+ retval = 0;
719+ }
720+ else if (!aclconfig_default_used)
721+ {
722+ signlevel = x;
723+ retval = 0;
724+
725+ if (strncmp (part_type, "f", 1) == 0)
726+ founddeniedfile = 1;
67ba4c3a 727+ }
728+ else {
09f63587 729+ }
730+ }
731+ }
732+ }
733+ }
734+ if (strncmp (xline, "d:ALL", 5) == 0 && (!groupfound && !userfound || listacl))
735+ {
736+ /* a default found */
737+ if (valid_tag (part_tag, tag))
738+ {
739+ foundline = 1;
740+
741+ default_part_perms_accessfile = xstrdup (part_perms);
742+
743+ if (valid_perm (part_perms, perm))
744+ {
745+ retval = 1;
746+
747+ if (perm == 8)
748+ dadmin = 1;
749+ }
750+ else
751+ retval = 0;
752+ }
753+ }
754+
755+ }
756+ if (fclose (accessfp) == EOF)
757+ error (1, errno, "cannot close 'access' file");
758+
759+ }
760+ }
761+
762+ if (!foundline)
763+ {
764+ /* DEFAULT */
765+ if (valid_perm (NULL, perm))
766+ retval = 1;
767+ else
768+ retval = 0;
769+ }
770+
771+ if (dadmin)
772+ {
773+ retval = dadmin;
774+ }
775+
776+ cache_retval = retval;
777+
778+ free (filefullname);
779+
780+ return (retval);
781+}
782+
783+/* Returns 1 if successful, 0 if not. */
784+int
785+valid_tag (part_tag, tag)
786+char *part_tag;
787+char *tag;
788+{
789+ if (tag == NULL)
790+ tag = xstrdup ("HEAD");
791+
792+ if (strcmp (part_tag, "ALL") == 0)
793+ return (1);
794+
795+ if (strcmp (tag, part_tag) == 0)
796+ return (1);
797+ else
798+ return (0);
799+}
800+
801+/* Returns 1 if successful, 0 if not. */
802+int
803+valid_perm (part_perms, perm)
804+char *part_perms;
805+int perm;
806+{
807+ char *perms;
808+ int retval = 0;
809+
810+ perms = get_perms (part_perms);
811+
812+ /* Allow, if nothing found. */
813+ if (perms[0] == '\0')
814+ return (1);
815+
816+
817+ if (strstr (perms, "n"))
818+ retval = 0; /* no access allowed, exit */
819+ if (strstr (perms, "p"))
820+ retval = 1; /* admin rights */
821+ else if (strstr (perms, "a") && perm != 8)
822+ retval = 1; /* all access allowed, exit */
823+ else
824+ switch (perm)
825+ {
826+ case 3: /* write permission */
827+ if (strstr (perms, "w"))
828+ retval = 1;
829+ break;
830+ case 4: /* tag permission */
831+ if (strstr (perms, "t"))
832+ retval = 1;
833+ break;
834+ case 5: /* read permission */
835+ if (strstr (perms, "w") || strstr (perms, "t") || strstr (perms, "c") ||
836+ strstr (perms, "d") || strstr (perms, "r"))
837+ retval = 1;
838+ break;
839+ case 6: /* create permission */
840+ if (strstr (perms, "c"))
841+ retval = 1;
842+ break;
843+ case 7: /* delete permission */
844+ if (strstr (perms, "d"))
845+ retval = 1;
846+ break;
847+ case 8: /* permission change */
848+ if (strstr (perms, "p"))
849+ retval = 1;
850+ break;
851+ default:
852+ retval = 0; /* never reached */
853+ break;
854+ }
855+
856+ return (retval);
857+}
858+
859+char *
860+get_perms (part_perms)
861+char *part_perms;
862+
863+{
864+ char *username;
865+ char *xperms;
866+ size_t xperms_len = 1;
867+
868+ FILE *groupfp;
869+
870+ char *usr;
871+ char *per;
872+ char *founduser = NULL;
873+ char *foundall = NULL;
874+ int default_checked = 0;
875+
876+ aclconfig_default_used = 0;
877+
878+ xperms = xmalloc (xperms_len);
879+ xperms[0] = '\0';
880+
881+ username = getcaller ();
882+
883+ /* no defined acl, no default acl in access file,
884+ or no access file at all */
885+ if (part_perms == NULL)
886+ if (cvs_acl_default_permissions)
887+ {
888+ aclconfig_default_used = 1;
889+ return (cvs_acl_default_permissions);
890+ }
891+ else
892+ return (xperms);
893+
894+check_default:
895+ founduser = strstr (part_perms, username);
896+ foundall = strstr (part_perms, "ALL!");
897+
898+ if (founduser)
899+ {
900+ usr = strtok (founduser, "!\t");
901+ per = strtok (NULL, ",\t");
902+
903+ if (strcmp (usr, username) == 0)
904+ {
905+ xperms = xstrdup (per);
906+ xperms_len = strlen (xperms);
907+
908+ userfound = 1;
909+ }
910+ }
911+ else
912+ {
913+ if (use_system_groups) {
914+ struct group *griter;
915+ setgrent ();
916+ while (griter = getgrent ()) {
917+ char **users=griter->gr_mem;
918+ int index = 0;
919+ char *userchk = users [index++];
920+ while(userchk != NULL) {
921+ if(strcmp (userchk, username) == 0)
922+ break;
923+ userchk = users[index++];
924+ }
925+ if (userchk != NULL) {
926+ char *grp;
927+ if ((grp = strstr (part_perms, griter->gr_name)) && grp[strlen (griter->gr_name)] == '!') {
928+ char *gperm = strtok (grp, "!\t");
929+ gperm = strtok (NULL, ",\t");
930+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
931+
932+ groupfound = 1;
933+ }
934+ }
935+ }
936+ endgrent ();
937+ }
938+ else if (use_cvs_groups) {
939+ groupfp = open_groupfile ("r");
940+ if (groupfp != NULL)
941+ {
942+ char *line = NULL;
943+ size_t line_allocated = 0;
944+
945+ while (getline (&line, &line_allocated, groupfp) >= 0)
946+ {
947+ if (strstr (line, username))
948+ {
949+ char *temp;
950+ temp = strstr (line, username);
951+
952+ if (temp[strlen (username)] == ','
953+ || temp[strlen (username)] == ' '
954+ || temp[strlen (username)] == '\n')
955+ {
956+ char *tmp;
957+ tmp = strtok (line, ":\t");
958+ if (strcmp (tmp, username) != 0)
959+ {
960+ char *grp;
961+ if ((grp = strstr (part_perms, tmp)))
962+ if (grp[strlen (tmp)] == '!')
963+ {
964+ char *gperm;
965+ gperm = strtok (grp, "!\t");
966+ gperm = strtok (NULL, ",\t");
967+
968+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
969+
970+ groupfound = 1;
971+ }
972+ }
973+ }
974+ }
975+ }
976+ if (fclose (groupfp) == EOF)
977+ error (1, errno, "cannot close 'group' file");
978+ }
979+ }
980+ }
981+
982+ if (foundall && (!groupfound && !userfound))
983+ {
984+ usr = strtok (strstr (part_perms, "ALL!"), "!\t");
985+ per = strtok (NULL, ",\t");
986+
987+ if (!default_checked)
988+ default_perms_object = xstrdup (per);
989+
990+ if (xperms[0] == '\0')
991+ {
992+ xperms = xstrdup (per);
993+ xperms_len = strlen (xperms);
994+ }
995+ }
996+ else if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
997+ {
998+ part_perms = xstrdup (default_part_perms_accessfile);
999+ default_checked = 1;
1000+
1001+ goto check_default;
1002+ }
1003+
1004+ if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
1005+ {
1006+ if (default_perms_object)
1007+ xperms = xstrdup (default_perms_object);
1008+ else if (default_part_perms_accessfile)
1009+ {
1010+ part_perms = default_part_perms_accessfile;
1011+ default_checked = 1;
1012+ goto check_default;
1013+ }
1014+ else if (cvs_acl_default_permissions)
1015+ {
1016+ aclconfig_default_used = 1;
1017+ xperms = xstrdup (cvs_acl_default_permissions);
1018+ }
1019+ }
1020+
1021+ if (xperms[0] == '\0' && cvs_acl_default_permissions)
1022+ {
1023+ aclconfig_default_used = 1;
1024+ xperms = xstrdup (cvs_acl_default_permissions);
1025+ }
1026+
1027+ return (xperms);
1028+}
1029+
1030+
1031+int
1032+cvsacl (argc, argv)
1033+int argc;
1034+char **argv;
1035+{
1036+ char *chdirrepository;
1037+ int c;
1038+ int err = 0;
1039+ int usetag = 0;
1040+ int recursive = 0;
1041+
1042+ int k;
1043+
1044+ int which;
1045+ char *where;
1046+
1047+ is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
1048+
1049+ if (argc == -1)
1050+ usage (is_racl ? racl_usage : acl_usage);
1051+
1052+ /* parse the args */
1053+ optind = 0;
1054+
1055+ while ((c = getopt (argc, argv, "Rr:dfl")) != -1)
1056+ {
1057+ switch (c)
1058+ {
1059+ case 'R':
1060+ recursive = 1;
1061+ break;
1062+ case 'r':
1063+ tag = xstrdup (optarg);
1064+ break;
1065+ case 'd':
1066+ acldir = 1;
1067+ break;
1068+ case 'f':
1069+ aclfile = 1;
1070+ break;
1071+ case 'l':
1072+ listacl = 1;
1073+ break;
1074+ case '?':
1075+ default:
1076+ usage (is_racl ? racl_usage : acl_usage);
1077+ break;
1078+ }
1079+ }
1080+
1081+ argc -= optind;
1082+ argv += optind;
1083+
1084+ if (!acldir && !aclfile)
1085+ usage (is_racl ? racl_usage : acl_usage);
1086+ if (acldir && aclfile)
1087+ usage (is_racl ? racl_usage : acl_usage);
1088+
1089+ if (listacl)
1090+ if (strstr (argv[0], ":"))
1091+ usage (is_racl ? racl_usage : acl_usage);
1092+ if (!listacl)
1093+ if (!strstr (argv[0], ":"))
1094+ usage (is_racl ? racl_usage : acl_usage);
1095+
1096+ if (argc < (is_racl ? 1 : 1))
1097+ usage (is_racl ? racl_usage : acl_usage);
1098+
1099+#ifdef CLIENT_SUPPORT
1100+
1101+ if (current_parsed_root->isremote)
1102+ {
1103+ start_server ();
1104+ ign_setup ();
1105+
1106+ if(recursive)
1107+ send_arg ("-R");
1108+
1109+ if (acldir)
1110+ send_arg ("-d");
1111+
1112+ if (aclfile)
1113+ send_arg ("-f");
1114+
1115+ if (listacl)
1116+ send_arg ("-l");
1117+
1118+ if(tag)
1119+ {
1120+ send_arg ("-r");
1121+ send_arg (tag);
1122+ }
1123+
1124+ send_arg ("--");
1125+
1126+ if (!listacl)
1127+ {
1128+ send_arg (argv[0]);
1129+
1130+ argc--;
1131+ argv++;
1132+ }
1133+
1134+ if (is_racl)
1135+ {
1136+ int i;
1137+ for (i = 0; i < argc; ++i)
1138+ send_arg (argv[i]);
1139+
1140+ send_to_server ("racl\012",0);
1141+ }
1142+ else
1143+ {
1144+ send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
1145+ send_file_names (argc, argv, SEND_EXPAND_WILD);
1146+ send_to_server ("acl\012", 0);
1147+ }
1148+
1149+ return get_responses_and_close ();
1150+ }
1151+#endif
1152+
1153+#ifdef SERVER_SUPPORT
1154+
1155+ if (!listacl)
1156+ {
1157+ muser = strtok (argv[0], ":\t");
1158+ mperms = strtok (NULL, ":\t");
1159+
1160+ /* if set to 'default' */
1161+ if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
1162+ mperms = xstrdup ("x");
1163+
1164+ /* Check that the given permissions are valid. */
1165+ if (!given_perms_valid (mperms))
1166+ error (1,0,"Invalid permissions: '%s'", mperms);
1167+
1168+ argc--;
1169+ argv++;
1170+ }
1171+
1172+
1173+ if (!tag)
1174+ tag = xstrdup ("HEAD");
1175+
1176+ if (!cvs_casecmp (argv[0], "ALL"))
1177+ {
1178+ argv[0] = xstrdup (".");
1179+ defaultperms = 1;
c52fdbcd 1180+ if (!use_separate_acl_file_for_each_dir)
09f63587 1181+ {
1182+ recursive = 0;
1183+ }
1184+
1185+ }
1186+
1187+ if (is_racl)
1188+ {
1189+ DBM *db;
1190+ int i;
1191+ db = open_module ();
1192+ for (i = 0; i < argc; i++)
1193+ {
1194+ err += do_module (db, argv[i], MISC, "ACL ing: ",
1195+ racl_proc, (char *) NULL, 0, !recursive, 0,
1196+ 0, NULL);
1197+ }
1198+ close_module (db);
1199+ }
1200+ else
1201+ {
1202+ err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive, NULL,
1203+ NULL);
1204+ }
1205+ if (err)
1206+ error (1, 0, "an error accured");
1207+
1208+ return (err);
1209+
1210+#endif
1211+}
1212+
1213+static int
1214+racl_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg)
1215+int argc;
1216+char **argv;
1217+char *xwhere;
1218+char *mwhere;
1219+char *mfile;
1220+int shorten;
1221+int local;
1222+char *mname;
1223+char *msg;
1224+{
1225+ char *myargv[2];
1226+ int err = 0;
1227+ int which;
1228+ char *repository;
1229+ char *where;
1230+
1231+ if (is_racl)
1232+ {
1233+ repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
1234+ + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
1235+
1236+ (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
1237+ where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
1238+ + 1);
1239+ (void) strcpy (where, argv[0]);
1240+
1241+ /* if mfile isn't null, we need to set up to do only part of the module */
1242+ if (mfile != NULL)
1243+ {
1244+ char *cp;
1245+ char *path;
1246+
1247+ /* if the portion of the module is a path, put the dir part on repos */
1248+ if ((cp = strrchr (mfile, '/')) != NULL)
1249+ {
1250+ *cp = '\0';
1251+ (void) strcat (repository, "/");
1252+ (void) strcat (repository, mfile);
1253+ (void) strcat (where, "/");
1254+ (void) strcat (where, mfile);
1255+ mfile = cp + 1;
1256+ }
1257+
1258+ /* take care of the rest */
1259+ path = xmalloc (strlen (repository) + strlen (mfile) + 5);
1260+ (void) sprintf (path, "%s/%s", repository, mfile);
1261+ if (isdir (path))
1262+ {
1263+ /* directory means repository gets the dir tacked on */
1264+ (void) strcpy (repository, path);
1265+ (void) strcat (where, "/");
1266+ (void) strcat (where, mfile);
1267+ }
1268+ else
1269+ {
1270+ myargv[0] = argv[0];
1271+ myargv[1] = mfile;
1272+ argc = 2;
1273+ argv = myargv;
1274+ }
1275+ free (path);
1276+ }
1277+
1278+ /* cd to the starting repository */
1279+ if ( CVS_CHDIR (repository) < 0)
1280+ {
1281+ error (0, errno, "cannot chdir to %s", repository);
1282+ free (repository);
1283+ return (1);
1284+ }
1285+
1286+ /* End section which is identical to patch_proc. */
1287+
1288+ which = W_REPOS | W_ATTIC;
1289+ }
1290+ else
1291+ {
1292+ where = NULL;
1293+ which = W_LOCAL | W_REPOS | W_ATTIC;
1294+ }
1295+ if (listacl)
1296+ err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL, NULL,
1297+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1298+ repository);
1299+ else
1300+ err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
1301+ argc - 1, argv + 1, local, which, 0, 0, (char *) where, 1,
1302+ repository);
1303+
1304+ return (err);
1305+}
1306+
1307+
1308+static int
1309+acl_fileproc (callerdat, finfo)
1310+void *callerdat;
1311+struct file_info *finfo;
1312+{
1313+ Vers_TS *vers;
1314+
1315+ FILE *accessfp;
1316+
1317+ char *filefullname;
1318+
1319+ char *founduserpart = NULL;
1320+ char *newuserpart = NULL;
1321+ char *otheruserparts = NULL;
1322+ size_t otherslen = 0;
1323+
1324+ const char *frepository;
1325+ int foundline = 0;
1326+
1327+ char *line = NULL;
1328+ size_t line_allocated = 0;
1329+ int linelen;
1330+
1331+ char *part_type = NULL;
1332+ char *part_object = NULL;
1333+ char *part_tag = NULL;
1334+ char *part_perms = NULL;
1335+ char *wperms;
1336+ char *userpart;
1337+
1338+ char *errmsg;
1339+
1340+ int pos;
1341+
1342+ if (!aclfile)
1343+ return (0);
1344+
1345+ frepository = Short_Repository (finfo->repository);
1346+
1347+ filefullname = xmalloc (strlen (frepository)
1348+ + strlen (finfo->file)
1349+ + 2);
1350+ strcpy (filefullname, frepository);
1351+ strcat (filefullname, "/");
1352+ strcat (filefullname, finfo->file);
1353+
1354+ if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos, 0))
1355+ error (1,0,"You do not have acl admin rights on '%s'", frepository);
1356+
1357+ if (line != NULL)
1358+ {
1359+ part_type = strtok (line, ":\t");
1360+ part_object = strtok (NULL, ":\t");
1361+ part_tag = strtok (NULL, ":\t");
1362+ part_perms = strtok (NULL, ":\t");
1363+
1364+ foundline = 1;
1365+ userpart = strtok (part_perms, ",\t");
1366+
1367+ if (strstr (userpart, muser))
1368+ founduserpart = xstrdup (userpart);
1369+ else
1370+ {
1371+ otheruserparts = xstrdup (userpart);
1372+ otherslen = strlen (otheruserparts);
1373+ }
1374+
1375+ while ((userpart = strtok (NULL, ",\t")) != NULL)
1376+ {
1377+ if (strncmp (userpart, muser, strlen (muser)) == 0)
1378+ founduserpart = xstrdup (userpart);
1379+ else
1380+ {
1381+ if (otheruserparts != NULL)
1382+ {
1383+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1384+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1385+ }
1386+ else
1387+ {
1388+ otheruserparts = xstrdup (userpart);
1389+ otherslen = strlen (otheruserparts);
1390+ }
1391+ }
1392+ }
1393+ }
1394+
1395+ wperms = make_perms (mperms, founduserpart, &errmsg);
1396+ if (wperms == NULL)
1397+ {
1398+ if (errmsg)
1399+ error (0, 0, "%s %s", filefullname, errmsg);
1400+
1401+ return (0);
1402+ }
1403+ else
1404+ {
1405+ cvs_output ("X ", 0);
1406+ cvs_output (filefullname, 0);
1407+ cvs_output ("\n", 0);
1408+
1409+ write_perms (muser, wperms, founduserpart, foundline,
1410+ otheruserparts, "f", filefullname, tag, pos, finfo->repository);
1411+ }
1412+
1413+ return (0);
1414+}
1415+
1416+static Dtype
1417+acl_dirproc (callerdat, dir, repos, update_dir, entries)
1418+void *callerdat;
1419+const char *dir;
1420+const char *repos;
1421+const char *update_dir;
1422+List *entries;
1423+{
1424+ const char *drepository;
1425+ char *founduserpart = NULL;
1426+ char *newuserpart = NULL;
1427+ char *otheruserparts = NULL;
1428+ size_t otherslen = 0;
1429+ int foundline = 0;
1430+
1431+ char *line = NULL;
1432+ size_t line_allocated = 0;
1433+ int linelen;
1434+
1435+ FILE *accessfp;
1436+ char *part_type = NULL;
1437+ char *part_object = NULL;
1438+ char *part_tag = NULL;
1439+ char *part_perms = NULL;
1440+ char *wperms;
1441+ int i = 0;
1442+ char *userpart;
1443+ int pos;
1444+
1445+ char *errmsg;
1446+
1447+ if (repos[0] == '\0')
1448+ repos = Name_Repository (dir, NULL);
1449+
1450+ if (!acldir)
1451+ return (0);
1452+
1453+ if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
1454+ error (1,0,"You do not have admin rights on '%s'", Short_Repository (repos));
1455+
1456+ drepository = Short_Repository (repos);
1457+
1458+ if (line != NULL)
1459+ {
1460+ part_type = strtok (line, ":\t");
1461+ part_object = strtok (NULL, ":\t");
1462+ part_tag = strtok (NULL, ":\t");
1463+ part_perms = strtok (NULL, ":\t");
1464+
1465+ foundline = 1;
1466+ userpart = strtok (part_perms, ",\t");
1467+
1468+ if (strstr (userpart, muser))
1469+ founduserpart = xstrdup (userpart);
1470+ else
1471+ {
1472+ otheruserparts = xstrdup (userpart);
1473+ otherslen = strlen (otheruserparts);
1474+ }
1475+
1476+ while ((userpart = strtok (NULL, ",\t")) != NULL)
1477+ {
1478+ if (strncmp (userpart, muser, strlen (muser)) == 0)
1479+ founduserpart = xstrdup (userpart);
1480+ else
1481+ {
1482+ if (otheruserparts != NULL)
1483+ {
1484+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
1485+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
1486+ }
1487+ else
1488+ {
1489+ otheruserparts = xstrdup (userpart);
1490+ otherslen = strlen (otheruserparts);
1491+ }
1492+ }
1493+ }
1494+ }
1495+
1496+ wperms = make_perms (mperms, founduserpart, &errmsg);
1497+ if (wperms == NULL)
1498+ {
1499+ if (errmsg)
1500+ error (0, 0, "%s %s", drepository, errmsg);
1501+
1502+ return (0);
1503+ }
1504+ else
1505+ {
1506+ if (defaultperms)
1507+ {
1508+ cvs_output ("X ", 0);
1509+ cvs_output ("ALL", 0);
1510+ cvs_output ("\n", 0);
1511+ write_perms (muser, wperms, founduserpart, foundline,
67ba4c3a 1512+ otheruserparts, "d", "ALL", tag, pos, drepository);//baris
09f63587 1513+
1514+ }
1515+ else
1516+ {
1517+ cvs_output ("X ", 0);
1518+ cvs_output (drepository, 0);
1519+ cvs_output ("\n", 0);
1520+ write_perms (muser, wperms, founduserpart, foundline,
67ba4c3a 1521+ otheruserparts, "d", drepository, tag, pos, drepository);//baris `repos`
09f63587 1522+ }
1523+ }
1524+
1525+ return (0);
1526+}
1527+
1528+/* Open CVSROOT/access or defined CVSACLFileLocation file. */
1529+FILE *
1530+open_accessfile (fmode, adir, fname)
1531+char *fmode;
67ba4c3a 1532+const char *adir;
09f63587 1533+char **fname;
1534+{
1535+ char *accessfile;
1536+ FILE *accessfp;
1537+
c52fdbcd 1538+ if (!use_separate_acl_file_for_each_dir)
09f63587 1539+ {
1540+ if (cvs_acl_file_location == NULL)
1541+ {
1542+ accessfile = xmalloc (strlen (current_parsed_root->directory)
1543+ + sizeof (CVSROOTADM)
1544+ + sizeof (CVSROOTADM_ACCESS)
1545+ + 3);
1546+
1547+ strcpy (accessfile, current_parsed_root->directory);
1548+ strcat (accessfile, "/");
1549+ strcat (accessfile, CVSROOTADM);
1550+ strcat (accessfile, "/");
1551+ strcat (accessfile, CVSROOTADM_ACCESS);
1552+ }
1553+ else
1554+ {
1555+ accessfile = xmalloc (strlen (cvs_acl_file_location));
1556+ strcpy (accessfile, cvs_acl_file_location);
1557+ }
1558+ }
1559+ else
1560+ {
1561+ accessfile = xmalloc (strlen (current_parsed_root->directory)
1562+ + strlen (adir)
1563+ + strlen ("access")
1564+ + 3);
1565+
1566+ strcpy (accessfile, current_parsed_root->directory);
1567+ strcat (accessfile, "/");
1568+ strcat (accessfile, adir);
1569+ strcat (accessfile, "/");
1570+ strcat (accessfile, "access");
1571+ }
1572+
1573+ accessfp = CVS_FOPEN (accessfile, fmode);
1574+
1575+ if (accessfp == NULL)
1576+ error (0, 0, "cannot open file: %s", accessfile);
1577+
1578+ if (fname != NULL)
1579+ *fname = xstrdup (accessfile);
1580+
1581+ free (accessfile);
1582+
1583+ return (accessfp);
1584+}
1585+
1586+/* Open /etc/group file if UseSystemGroups=yes in config file. */
1587+/* Open CVSROOT/group file if UseCVSGroups=yes in config file. */
1588+FILE *
1589+open_groupfile (fmode)
1590+char *fmode;
1591+{
1592+ char *groupfile;
1593+ FILE *groupfp;
1594+
1595+ if (use_cvs_groups)
1596+ {
1597+ if (cvs_groups_file_location != NULL)
1598+ {
1599+ groupfile = xmalloc (strlen (cvs_groups_file_location));
1600+ strcpy (groupfile, cvs_groups_file_location);
1601+ }
1602+ else
1603+ {
1604+ groupfile = xmalloc (strlen (current_parsed_root->directory)
1605+ + sizeof (CVSROOTADM)
1606+ + sizeof (CVSROOTADM_GROUP)
1607+ + 3);
1608+
1609+ strcpy (groupfile, current_parsed_root->directory);
1610+ strcat (groupfile, "/");
1611+ strcat (groupfile, CVSROOTADM);
1612+ strcat (groupfile, "/");
1613+ strcat (groupfile, CVSROOTADM_GROUP);
1614+ }
1615+ }
1616+
1617+ else
1618+ {
1619+ return (NULL);
1620+ }
1621+
1622+ groupfp = CVS_FOPEN (groupfile, "r");
1623+
1624+ if (groupfp == NULL)
1625+ error (0, 0, "cannot open file: %s", groupfile);
1626+
1627+ free (groupfile);
1628+
1629+ return (groupfp);
1630+}
1631+
1632+
1633+/* Check whether given permissions are valid or not. */
1634+/* Returns 1 if permissions are valid. */
1635+/* Returns 0 if permissions are NOT valid. */
1636+int
1637+given_perms_valid (cperms)
1638+char *cperms;
1639+{
1640+ int cperms_len;
1641+ int retval;
1642+ int index, i;
1643+
1644+ if (cperms[0] == '+' || cperms[0] == '-')
1645+ index = 1;
1646+ else
1647+ index = 0;
1648+
1649+ cperms_len = strlen (cperms);
1650+
1651+ switch (cperms[index])
1652+ {
1653+ case 'x':
1654+ if ((cperms_len - index) == 1 && cperms_len == 1)
1655+ retval = 1;
1656+ else
1657+ retval = 0;
1658+ break;
1659+ case 'n':
1660+ if ((cperms_len - index) == 1 && cperms_len == 1)
1661+ retval = 1;
1662+ else
1663+ retval = 0;
1664+ break;
1665+ case 'p':
1666+ if ((cperms_len - index) == 1)
1667+ retval = 1;
1668+ else
1669+ retval = 0;
1670+ break;
1671+ case 'a':
1672+ if ((cperms_len - index) == 1)
1673+ retval = 1;
1674+ else
1675+ for (i = index + 1; i < cperms_len; i++)
1676+ if (cperms[i] == 'p')
1677+ retval = 1;
1678+ else
1679+ retval = 0;
1680+ break;
1681+ case 'r':
1682+ if ((cperms_len - index) == 1)
1683+ retval = 1;
1684+ else
1685+ for (i = index + 1; i < cperms_len; i++)
1686+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1687+ retval = 1;
1688+ else
1689+ retval = 0;
1690+ break;
1691+ case 'w':
1692+ if ((cperms_len - index) == 1)
1693+ retval = 1;
1694+ else
1695+ for (i = index + 1; i < cperms_len; i++)
1696+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
1697+ retval = 1;
1698+ else
1699+ retval = 0;
1700+ break;
1701+ case 't':
1702+ if ((cperms_len - index) == 1)
1703+ retval = 1;
1704+ else
1705+ for (i = index + 1; i < cperms_len; i++)
1706+ if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
1707+ retval = 1;
1708+ else
1709+ retval = 0;
1710+ break;
1711+ case 'c':
1712+ if ((cperms_len - index) == 1)
1713+ retval = 1;
1714+ else
1715+ for (i = index + 1; i < cperms_len; i++)
1716+ if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
1717+ retval = 1;
1718+ else
1719+ retval = 0;
1720+ break;
1721+ case 'd':
1722+ if ((cperms_len - index) == 1)
1723+ retval = 1;
1724+ else
1725+ for (i = index + 1; i < cperms_len; i++)
1726+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
1727+ retval = 1;
1728+ else
1729+ retval = 0;
1730+ break;
1731+ default:
1732+ retval = 0;
1733+ break;
1734+ }
1735+ return (retval);
1736+}
1737+
1738+char *
1739+make_perms (perms, founduserpart, xerrmsg)
1740+char *perms;
1741+char *founduserpart;
1742+char **xerrmsg;
1743+{
1744+ char *fperms;
1745+ size_t perms_len;
1746+ size_t fperms_len;
1747+ char *retperms = NULL;
1748+ char *xperms;
1749+ int i, j;
1750+ int err = 0;
1751+ char *errmsg = NULL;
1752+ size_t retperms_len = 1;
1753+
1754+ retperms = xmalloc (retperms_len);
1755+ retperms[0] = '\0';
1756+
1757+ perms_len = strlen (perms);
1758+
1759+ if (perms[0] == '+' || perms[0] == '-')
1760+ {
1761+ if (founduserpart)
1762+ {
1763+ char *temp;
1764+ temp = strtok (founduserpart, "!\t");
1765+ fperms = strtok (NULL, "!\t");
1766+ fperms_len = strlen (fperms);
1767+
1768+ if (strncmp (fperms, "x", 1) == 0)
1769+ {
1770+ err = 1;
1771+ if (perms[0] == '+')
1772+ *xerrmsg = xstrdup ("cannot add default permission 'x'");
1773+ else
1774+ *xerrmsg = xstrdup ("cannot remove default permission 'x'");
1775+ }
1776+
1777+ for (i = 1; i < perms_len && !err; i++)
1778+ {
1779+ switch (perms[i])
1780+ {
1781+ case 'n':
1782+ err = 1;
1783+ break;
1784+ case 'p':
1785+ if (perms[0] == '+')
1786+ fperms = xstrdup ("p");
1787+ else if (perms[0] == '-')
1788+ {
1789+ fperms_len = 1;
1790+ fperms = xmalloc (fperms_len);
1791+ fperms[0] = '\0';
1792+ }
1793+ break;
1794+ case 'a':
1795+ for (j = 0; j < fperms_len; j++)
1796+ {
1797+ if (fperms[j] == 'p')
1798+ {
1799+ err = 1;
1800+ *xerrmsg = xstrdup ("user has admin rights, cannot use +/- permissions");
1801+ }
1802+ else if (fperms[j] == 'a' && perms[0] == '+')
1803+ {
1804+ err = 1;
1805+ *xerrmsg = xstrdup ("user already has all ('a') permission");
1806+ }
1807+ else if (fperms[j] != 'a' && perms[0] == '-')
1808+ {
1809+ err = 1;
1810+ *xerrmsg = xstrdup ("user does not have all ('a') permission");
1811+ }
1812+ }
1813+ if (perms[0] == '+')
1814+ {
1815+ fperms = xstrdup ("a");
1816+ fperms_len = strlen (fperms);
1817+ }
1818+ else if (perms[0] == '-')
1819+ {
1820+ fperms_len = 1;
1821+ fperms = xmalloc (fperms_len);
1822+ fperms[0] = '\0';
1823+ }
1824+
1825+ break;
1826+ case 'r':
1827+ for (i = 0; i < fperms_len; i++)
1828+ {
1829+ if (fperms[i] == 'n' && perms[0] == '+')
1830+ {
1831+ fperms = xstrdup ("r");
1832+ fperms_len = strlen (fperms);
1833+ }
1834+ else if (fperms[i] == 'r' && perms[0] == '-')
1835+ {
1836+ fperms_len = 1;
1837+ fperms = xmalloc (fperms_len);
1838+ fperms[0] = '\0';
1839+ }
1840+ else if (perms[0] == '-')
1841+ {
1842+ err = 1;
1843+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1844+ }
1845+ else
1846+ {
1847+ err = 1;
1848+ *xerrmsg = xstrdup ("user has other permissions, cannot remove read ('r') permission");
1849+ }
1850+ }
1851+ break;
1852+ case 'w':
1853+ {
1854+ char *tempfperms;
1855+ size_t tempfperms_len = 1;
1856+
1857+ tempfperms = xmalloc (tempfperms_len);
1858+ tempfperms[0] = '\0';
1859+
1860+ for (j = 0; j < fperms_len; j++)
1861+ {
1862+ if (fperms[j] == 't' || fperms[j] == 'c' || fperms[j] == 'd')
1863+ {
1864+ char *temp;
1865+ temp = xmalloc (2);
1866+ temp[0] = fperms[j];
1867+ temp[1] = '\0';
1868+
1869+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1870+ free (temp);
1871+ }
1872+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1873+ {
1874+ err = 1;
1875+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- write permissions");
1876+ }
1877+ else if (fperms[j] == 'n' || fperms[j] == 'r')
1878+ {
1879+ if (perms[0] == '-')
1880+ {
1881+ err = 1;
1882+ *xerrmsg = xstrdup ("user does not have write ('w') permission");
1883+ }
1884+ }
1885+ }
1886+
1887+ fperms = xstrdup (tempfperms);
1888+ fperms_len = strlen (fperms);
1889+ free (tempfperms);
1890+
1891+ if (perms[0] == '+')
1892+ {
1893+ xrealloc_and_strcat (&fperms, &fperms_len, "w");
1894+ }
1895+ }
1896+ break;
1897+ case 't':
1898+ {
1899+ char *tempfperms;
1900+ size_t tempfperms_len = 1;
1901+
1902+ tempfperms = xmalloc (tempfperms_len);
1903+ tempfperms[0] = '\0';
1904+
1905+ for (j = 0; j < fperms_len; j++)
1906+ {
1907+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 'd')
1908+ {
1909+ char *temp;
1910+ temp = xmalloc (2);
1911+ temp[0] = fperms[j];
1912+ temp[1] = '\0';
1913+
1914+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1915+ free (temp);
1916+ }
1917+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1918+ {
1919+ err = 1;
1920+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- tag permissions");
1921+ }
1922+ else if (fperms[i] == 'n' || fperms[i] == 'r')
1923+ {
1924+ if (perms[0] == '-')
1925+ *xerrmsg = xstrdup ("user does not have tag ('t') permission");
1926+ }
1927+ }
1928+
1929+ fperms = xstrdup (tempfperms);
1930+ fperms_len = strlen (fperms);
1931+ free (tempfperms);
1932+
1933+ if (perms[0] == '+')
1934+ {
1935+ xrealloc_and_strcat (&fperms, &fperms_len, "t");
1936+ }
1937+ }
1938+ break;
1939+ case 'c':
1940+ {
1941+ char *tempfperms;
1942+ size_t tempfperms_len = 1;
1943+
1944+ tempfperms = xmalloc (tempfperms_len);
1945+ tempfperms[0] = '\0';
1946+
1947+ for (j = 0; j < fperms_len; j++)
1948+ {
1949+ if (fperms[j] == 'w' || fperms[j] == 't' || fperms[j] == 'd')
1950+ {
1951+ char *temp;
1952+ temp = xmalloc (2);
1953+ temp[0] = fperms[j];
1954+ temp[1] = '\0';
1955+
1956+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
1957+ free (temp);
1958+ }
1959+ else if (fperms[j] == 'a' || fperms[j] == 'p')
1960+ {
1961+ err = 1;
1962+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- create permissions");
1963+ }
1964+ else if (fperms[i] == 'n' || fperms[i] == 'r')
1965+ {
1966+ if (perms[0] == '-')
1967+ err = 1;
1968+ *xerrmsg = xstrdup ("user does not have create ('c') permission");
1969+ }
1970+
1971+ }
1972+
1973+ fperms = xstrdup (tempfperms);
1974+ fperms_len = strlen (fperms);
1975+ free (tempfperms);
1976+
1977+ if (perms[0] == '+')
1978+ {
1979+ xrealloc_and_strcat (&fperms, &fperms_len, "c");
1980+ }
1981+ }
1982+ break;
1983+ case 'd':
1984+ {
1985+ char *tempfperms;
1986+ size_t tempfperms_len = 1;
1987+
1988+ tempfperms = xmalloc (tempfperms_len);
1989+ tempfperms[0] = '\0';
1990+
1991+ for (j = 0; j < fperms_len; j++)
1992+ {
1993+ if (fperms[j] == 'w' || fperms[j] == 'c' || fperms[j] == 't')
1994+ {
1995+ char *temp;
1996+ temp = xmalloc (2);
1997+ temp[0] = fperms[j];
1998+ temp[1] = '\0';
1999+
2000+ xrealloc_and_strcat (&tempfperms, &tempfperms_len, temp);
2001+ free (temp);
2002+ }
2003+ else if (fperms[j] == 'a' || fperms[j] == 'p')
2004+ {
2005+ err = 1;
2006+ *xerrmsg = xstrdup ("user has higher permissions, cannot use +/- delete permissions");
2007+ }
2008+ else if (fperms[i] == 'n' || fperms[i] == 'r')
2009+ {
2010+ if (perms[0] == '-')
2011+ err = 1;
2012+ *xerrmsg = xstrdup ("user does not have delete ('d') permission");
2013+ }
2014+ }
2015+
2016+ fperms = xstrdup (tempfperms);
2017+ fperms_len = strlen (fperms);
2018+ free (tempfperms);
2019+
2020+ if (perms[0] == '+')
2021+ {
2022+ xrealloc_and_strcat (&fperms, &fperms_len, "d");
2023+ }
2024+ }
2025+ break;
2026+ default:
2027+ err = 1;
2028+ *xerrmsg = xstrdup ("error in 'access' file format");
2029+ break;
2030+ }
2031+ if (fperms[0] == '\0')
2032+ retperms = xstrdup ("none");
2033+ else
2034+ retperms = xstrdup (fperms);
2035+ }
2036+ }
2037+ else
2038+ {
2039+ err = 1;
2040+ *xerrmsg = xstrdup("user is not given any permissions to remove/add");
2041+ }
2042+ }
2043+
2044+ else
2045+ {
2046+ retperms = xstrdup (perms);
2047+ }
2048+
2049+ if (err)
2050+ return (NULL);
2051+ else
2052+ return (retperms);
2053+}
2054+
2055+int
2056+write_perms (user, perms, founduserpart, foundline, otheruserparts,
2057+ part_type, part_object, part_tag, pos, arepos)
2058+char *user;
2059+char *perms;
2060+char *founduserpart;
2061+int foundline;
2062+char *otheruserparts;
2063+char *part_type;
2064+char *part_object;
2065+char *part_tag;
2066+int pos;
2067+char *arepos;
2068+{
09f63587 2069+ char *accessfile;
2070+ char *tmpaccessout;
2071+ FILE *accessfpin;
2072+ FILE *accessfpout;
2073+
2074+ char *newline = NULL;
2075+ size_t newlinelen = 1;
2076+
2077+ char *line = NULL;
2078+ size_t line_allocated = 0;
2079+
2080+ newline = xmalloc (newlinelen);
2081+ newline[0] = '\0';
2082+
2083+ if (!cvs_casecmp (part_tag, "ALL"))
2084+ part_tag = xstrdup ("ALL");
2085+
2086+ xrealloc_and_strcat (&newline, &newlinelen, part_type);
2087+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2088+ xrealloc_and_strcat (&newline, &newlinelen, part_object);
2089+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2090+ xrealloc_and_strcat (&newline, &newlinelen, part_tag);
2091+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2092+
2093+ if (strncmp (perms, "none", 4) != 0)
2094+ {
2095+ xrealloc_and_strcat (&newline, &newlinelen, user);
2096+ xrealloc_and_strcat (&newline, &newlinelen, "!");
2097+ xrealloc_and_strcat (&newline, &newlinelen, perms);
2098+ if (otheruserparts != NULL)
2099+ xrealloc_and_strcat (&newline, &newlinelen, ",");
2100+ }
2101+
2102+ if (otheruserparts != NULL)
2103+ {
2104+ if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
2105+ otheruserparts[strlen (otheruserparts) - 1] = '\0';
2106+
2107+ xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
2108+ }
2109+
2110+ xrealloc_and_strcat (&newline, &newlinelen, ":");
2111+
2112+ if (foundline)
2113+ {
2114+ accessfpout = cvs_temp_file (&tmpaccessout);
2115+ accessfpin = open_accessfile ("r", arepos, &accessfile);
2116+
2117+ while (getline (&line, &line_allocated, accessfpin) >= 0)
2118+ {
2119+ if (pos != ftell (accessfpin))
2120+ {
2121+ if (fprintf (accessfpout, line) < 0)
2122+ error (1, errno, "writing temporary file: %s", tmpaccessout);
2123+ }
2124+ else
2125+ {
2126+ if (fprintf (accessfpout, "%s\n", newline) < 0)
2127+ error (1, errno, "writing temporary file: %s", tmpaccessout);
2128+ }
2129+
2130+ }
2131+ if (fclose (accessfpin) == EOF)
2132+ error (1, errno, "cannot close access file: %s", accessfile);
2133+
2134+ if (fclose (accessfpout) == EOF)
2135+ error (1, errno, "cannot close temporary file: %s", tmpaccessout);
2136+
2137+ if (CVS_UNLINK (accessfile) < 0)
2138+ error (0, errno, "cannot remove %s", accessfile);
2139+
2140+ copy_file (tmpaccessout, accessfile);
2141+
2142+ if (CVS_UNLINK (tmpaccessout) < 0)
2143+ error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
2144+ }
2145+ else
2146+ {
2147+ accessfpout = open_accessfile ("r+", arepos, &accessfile);
2148+
2149+ if (accessfpout == NULL)
2150+ {
2151+ if (existence_error (errno))
2152+ {
2153+ accessfpout = open_accessfile ("w+", arepos, &accessfile);
2154+ }
2155+ }
67ba4c3a 2156+ else {
2157+ if (fseek (accessfpout, 0, 2) != 0)
2158+ error (1, errno, "cannot fseek access file: %s", accessfile);
2159+ }
09f63587 2160+
2161+ if (fprintf (accessfpout, "%s\n", newline) < 0)
2162+ error (1, errno, "writing access file: %s", accessfile);
2163+
2164+ if (fclose (accessfpout) == EOF)
2165+ error (1, errno, "cannot close access file: %s", accessfile);
2166+ }
2167+
2168+ free (newline);
2169+
2170+ chmod(accessfile, 0644);
2171+
2172+ return (0);
2173+}
2174+
2175+
2176+static int
2177+acllist_fileproc (callerdat, finfo)
2178+void *callerdat;
2179+struct file_info *finfo;
2180+{
2181+
2182+ char *filefullname;
2183+ const char *frepository;
2184+ char *line = NULL;
2185+ int pos;
2186+
2187+ if (!aclfile)
2188+ return (0);
2189+
2190+ frepository = Short_Repository (finfo->repository);
2191+
2192+ filefullname = xmalloc (strlen (frepository)
2193+ + strlen (finfo->file)
2194+ + 2);
2195+ strcpy (filefullname, frepository);
2196+ strcat (filefullname, "/");
2197+ strcat (filefullname, finfo->file);
2198+
2199+ if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos, 0))
2200+ error (1,0,"You do not have admin rights on '%s'", frepository);
2201+
09f63587 2202+ acllist_print (line, filefullname);
2203+
2204+ return (0);
2205+}
2206+
2207+static Dtype
2208+acllist_dirproc (callerdat, dir, repos, update_dir, entries)
2209+void *callerdat;
2210+const char *dir;
2211+const char *repos;
2212+const char *update_dir;
2213+List *entries;
2214+{
2215+
2216+ char *line = NULL;
2217+ const char *drepository;
2218+ int pos;
2219+
2220+ if (repos[0] == '\0')
2221+ repos = Name_Repository (dir, NULL);
2222+
2223+ if (!acldir)
2224+ return (0);
2225+
2226+ drepository = Short_Repository (repos);
2227+
2228+ if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
2229+ error (1, 0, "You do not have admin rights on '%s'", drepository);
2230+
2231+ acllist_print (line, drepository);
2232+
2233+ return (0);
2234+}
2235+
2236+
2237+void
2238+acllist_print (line, obj)
2239+char *line;
2240+const char *obj;
2241+{
2242+ char *temp;
2243+ char *temp2;
2244+ int x;
2245+ int c = 0;
2246+
2247+ char *printedusers[255];
2248+ printedusers[0] = NULL;
2249+
2250+ if (line != NULL)
2251+ {
2252+ temp = strtok (line, ":\t");
2253+
2254+ if (acldir)
2255+ cvs_output ("d ", 0);
2256+ else if (aclfile)
2257+ cvs_output ("f ", 0);
2258+
2259+ temp = strtok (NULL, ":\t");
2260+
2261+ cvs_output(obj, 0);
2262+ cvs_output (" | ", 0);
2263+
2264+ temp = strtok (NULL, ":\t");
2265+ cvs_output (temp, 0);
2266+ cvs_output (" | ", 0);
2267+
2268+ while ((temp = strtok (NULL, "!\t")) != NULL)
2269+ {
2270+ if (strncmp (temp, ":", 1) == 0)
2271+ break;
2272+
2273+ if (strcmp (temp, "ALL") == 0)
2274+ {
2275+ temp = strtok (NULL, ",\t");
2276+ continue;
2277+ }
2278+
2279+ cvs_output (temp, 0);
2280+ cvs_output (":", 0);
2281+
2282+ while (printedusers[c] != NULL)
2283+ c++;
2284+
2285+ printedusers[c] = xstrdup (temp);
2286+ c++;
2287+ printedusers[c] = NULL;
2288+
2289+ temp = strtok (NULL, ",\t");
2290+
2291+ if (temp != NULL && temp[strlen (temp) - 2] == ':')
2292+ temp[strlen (temp) - 2] = '\0';
2293+
2294+ cvs_output (temp, 0);
2295+ cvs_output (" ", 0);
2296+ }
2297+
2298+ if (default_perms_object)
2299+ {
2300+ cvs_output ("| defaults ", 0);
2301+ cvs_output ("ALL:", 0);
2302+ cvs_output (default_perms_object, 0);
2303+ }
2304+ else if (default_part_perms_accessfile)
2305+ {
2306+ size_t i;
2307+ i = strlen (default_part_perms_accessfile);
2308+ xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
2309+
2310+ free(line);
2311+ line = xstrdup(default_part_perms_accessfile);
2312+
2313+ cvs_output ("| defaults ", 0);
2314+
2315+ temp = strtok (line, "!\t");
2316+ cvs_output (temp, 0);
2317+ cvs_output (":", 0);
2318+
2319+ temp = strtok (NULL, ",\t");
2320+
2321+ cvs_output (temp, 0);
2322+ cvs_output (" ", 0);
2323+
2324+ while ((temp = strtok (NULL, "!\t")) != NULL)
2325+ {
2326+ int printed = 0;
2327+ int c2 = 0;
2328+ while (printedusers[c2] != NULL && printed == 0)
2329+ {
2330+ if (strcmp (printedusers[c2], temp) == 0)
2331+ {
2332+ printed = 1;
2333+ break;
2334+ }
2335+ c2++;
2336+ }
2337+
2338+ if (printed == 0)
2339+ {
2340+ cvs_output (temp, 0);
2341+ cvs_output (":", 0);
2342+ }
2343+
2344+ temp = strtok (NULL, ",\t");
2345+
2346+ if (temp[strlen (temp) - 2] == ':')
2347+ temp[strlen (temp) - 2] = '\0';
2348+
2349+ if (printed == 0)
2350+ {
2351+ cvs_output (temp, 0);
2352+ cvs_output (" ", 0);
2353+ }
2354+ }
2355+ }
2356+ else if (cvs_acl_default_permissions)
2357+ {
2358+ cvs_output ("| defaults ", 0);
2359+ cvs_output ("ALL: ", 0);
2360+ cvs_output (cvs_acl_default_permissions, 0);
2361+ }
2362+
2363+ cvs_output ("\n", 0);
2364+
2365+ }
2366+ else
2367+ {
2368+ if (acldir)
2369+ cvs_output ("d ", 0);
2370+ else if (aclfile)
2371+ cvs_output ("f ", 0);
2372+ cvs_output (obj, 0);
2373+ cvs_output (" | ", 0);
2374+ cvs_output (tag, 0);
2375+ cvs_output (" | ", 0);
2376+
2377+ if (default_perms_object)
2378+ {
2379+ cvs_output ("| defaults ", 0);
2380+ cvs_output ("ALL:", 0);
2381+ cvs_output (default_perms_object, 0);
2382+ cvs_output ("\n", 0);
2383+ }
2384+ else if (default_part_perms_accessfile)
2385+ {
2386+ free(line);
2387+ line = xstrdup(default_part_perms_accessfile);
2388+
2389+ cvs_output ("| defaults ", 0);
2390+
2391+ temp = strtok (line, "!\t");
2392+ cvs_output (temp, 0);
2393+ cvs_output (":", 0);
2394+
2395+ temp = strtok (NULL, ",\t");
2396+
2397+ if (temp[strlen (temp) - 2] == ':')
2398+ temp[strlen (temp) - 2] = '\0';
2399+
2400+ cvs_output (temp, 0);
2401+ cvs_output (" ", 0);
2402+
2403+ while ((temp = strtok (NULL, "!\t")) != NULL)
2404+ {
2405+ cvs_output (temp, 0);
2406+ cvs_output (":", 0);
2407+
2408+ temp = strtok (NULL, ",\t");
2409+
2410+ if (temp[strlen (temp) - 2] == ':')
2411+ temp[strlen (temp) - 2] = '\0';
2412+
2413+ cvs_output (temp, 0);
2414+ cvs_output (" ", 0);
2415+ }
2416+ cvs_output ("\n", 0);
2417+ }
2418+ else if (cvs_acl_default_permissions)
2419+ {
2420+ cvs_output ("| defaults ", 0);
2421+ cvs_output ("ALL: ", 0);
2422+ cvs_output (cvs_acl_default_permissions, 0);
2423+ cvs_output ("\n", 0);
2424+ }
2425+ else
2426+ cvs_output ("default:p (no perms)\n", 0);
2427+ }
2428+
2429+}
4905fec9 2430diff -urN cvs-1.11.18.orig/src/add.c cvs-1.11.18/src/add.c
2431--- cvs-1.11.18.orig/src/add.c 2004-10-19 22:13:23.000000000 +0200
2432+++ cvs-1.11.18/src/add.c 2004-11-14 14:00:39.000000000 +0100
c52fdbcd 2433@@ -400,6 +400,24 @@
09f63587 2434 }
2435 else
2436 {
2437+/* cvsacl patch */
2438+#ifdef SERVER_SUPPORT
2439+ if (use_cvs_acl && server_active)
2440+ {
2441+ if (!access_allowed (finfo.file, repository, vers->tag, 6,
2442+ NULL, NULL, 1))
2443+ {
2444+ if (stop_at_first_permission_denied)
2445+ error (1, 0, "permission denied for %s",
2446+ Short_Repository (finfo.repository));
2447+ else
2448+ error (0, 0, "permission denied for %s/%s",
2449+ Short_Repository (finfo.repository), finfo.file);
2450+
2451+ return (0);
2452+ }
2453+ }
2454+#endif
2455 /* There is a user file, so build the entry for it */
2456 if (build_entry (repository, finfo.file, vers->options,
2457 message, entries, vers->tag) != 0)
4905fec9 2458@@ -674,6 +692,26 @@
09f63587 2459 && isdir (finfo.file)
2460 && !wrap_name_has (finfo.file, WRAP_TOCVS))
2461 {
2462+
2463+/* cvsacl patch */
2464+#ifdef SERVER_SUPPORT
2465+ if (use_cvs_acl && server_active)
2466+ {
2467+ if (!access_allowed (NULL, repository, NULL, 6,
2468+ NULL, NULL, 1))
2469+ {
2470+ if (stop_at_first_permission_denied)
2471+ error (1, 0, "permission denied for %s",
2472+ Short_Repository (finfo.repository));
2473+ else
2474+ error (0, 0, "permission denied for %s/%s",
2475+ Short_Repository (finfo.repository), finfo.file);
2476+
2477+ return (0);
2478+ }
2479+ }
2480+#endif
2481+
2482 err += add_directory (&finfo);
2483 }
2484 else
4905fec9 2485diff -urN cvs-1.11.18.orig/src/annotate.c cvs-1.11.18/src/annotate.c
2486--- cvs-1.11.18.orig/src/annotate.c 2004-03-22 16:44:27.000000000 +0100
2487+++ cvs-1.11.18/src/annotate.c 2004-11-14 14:00:39.000000000 +0100
09f63587 2488@@ -276,6 +276,25 @@
2489 if (version == NULL)
2490 return 0;
2491
2492+/* cvsacl patch */
2493+#ifdef SERVER_SUPPORT
2494+ if (use_cvs_acl && server_active)
2495+ {
2496+ if (!access_allowed (finfo->file, finfo->repository, version, 5,
2497+ NULL, NULL, 1))
2498+ {
2499+ if (stop_at_first_permission_denied)
2500+ error (1, 0, "permission denied for %s",
2501+ Short_Repository (finfo->repository));
2502+ else
2503+ error (0, 0, "permission denied for %s/%s",
2504+ Short_Repository (finfo->repository), finfo->file);
2505+
2506+ return (0);
2507+ }
2508+ }
2509+#endif
2510+
2511 /* Distinguish output for various files if we are processing
2512 several files. */
2513 cvs_outerr ("\nAnnotations for ", 0);
4905fec9 2514diff -urN cvs-1.11.18.orig/src/commit.c cvs-1.11.18/src/commit.c
2515--- cvs-1.11.18.orig/src/commit.c 2004-10-29 21:55:14.000000000 +0200
2516+++ cvs-1.11.18/src/commit.c 2004-11-14 14:00:39.000000000 +0100
c52fdbcd 2517@@ -1299,6 +1299,34 @@
2518 return 0;
09f63587 2519
2520 ci = p->data;
2521+
2522+/* cvsacl patch */
2523+#ifdef SERVER_SUPPORT
2524+ if (use_cvs_acl && server_active)
2525+ {
2526+ int whichperm;
2527+ if (ci->status == T_MODIFIED)
2528+ whichperm = 3;
2529+ else if (ci->status == T_ADDED)
2530+ whichperm = 6;
2531+ else if (ci->status == T_REMOVED)
2532+ whichperm = 7;
2533+
2534+ if (!access_allowed (finfo->file, finfo->repository, ci->tag, whichperm,
2535+ NULL, NULL, 1))
2536+ {
2537+ if (stop_at_first_permission_denied)
2538+ error (1, 0, "permission denied for %s",
2539+ Short_Repository (finfo->repository));
2540+ else
2541+ error (0, 0, "permission denied for %s/%s",
2542+ Short_Repository (finfo->repository), finfo->file);
2543+
2544+ return (0);
2545+ }
2546+ }
2547+#endif
2548+
2549 if (ci->status == T_MODIFIED)
2550 {
2551 if (finfo->rcs == NULL)
4905fec9 2552diff -urN cvs-1.11.18.orig/src/cvs.h cvs-1.11.18/src/cvs.h
2553--- cvs-1.11.18.orig/src/cvs.h 2004-11-14 13:58:05.000000000 +0100
2554+++ cvs-1.11.18/src/cvs.h 2004-11-14 14:00:39.000000000 +0100
c52fdbcd 2555@@ -195,6 +195,11 @@
09f63587 2556 #define CVSROOTADM_PASSWD "passwd"
2557 #define CVSROOTADM_CONFIG "config"
2558
2559+/* cvsacl patch */
2560+#define CVSROOTADM_ACLCONFIG "aclconfig"
2561+#define CVSROOTADM_ACCESS "access"
2562+#define CVSROOTADM_GROUP "group"
2563+
2564 #define CVSNULLREPOS "Emptydir" /* an empty directory */
2565
2566 /* Other CVS file names */
4905fec9 2567@@ -567,6 +572,18 @@
09f63587 2568 /* LockDir setting from CVSROOT/config. */
2569 extern char *lock_dir;
2570
2571+/* cvsacl patch */
2572+/* ACL Patch settings from CVSROOT/config */
2573+extern int use_cvs_acl;
2574+extern char *cvs_acl_default_permissions;
2575+extern int use_cvs_groups;
2576+extern int use_system_groups;
c52fdbcd 2577+extern int use_separate_acl_file_for_each_dir;
09f63587 2578+extern char *cvs_acl_file_location;
2579+extern char *cvs_groups_file_location;
2580+extern char *cvs_server_run_as;
2581+extern int stop_at_first_permission_denied;
2582+
2583 void Scratch_Entry PROTO((List * list, const char *fname));
2584 void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
2585 void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
4905fec9 2586@@ -862,6 +879,10 @@
09f63587 2587 int editors PROTO ((int argc, char **argv));
2588 int watchers PROTO ((int argc, char **argv));
2589 extern int annotate PROTO ((int argc, char **argv));
2590+
2591+/* cvsacl patch */
2592+extern int cvsacl PROTO ((int argc, char **argv));
2593+
2594 extern int add PROTO ((int argc, char **argv));
2595 extern int admin PROTO ((int argc, char **argv));
2596 extern int checkout PROTO ((int argc, char **argv));
4905fec9 2597diff -urN cvs-1.11.18.orig/src/diff.c cvs-1.11.18/src/diff.c
2598--- cvs-1.11.18.orig/src/diff.c 2004-03-20 03:06:45.000000000 +0100
2599+++ cvs-1.11.18/src/diff.c 2004-11-14 14:00:39.000000000 +0100
09f63587 2600@@ -474,6 +474,43 @@
2601 {
2602 /* Skip all the following checks regarding the user file; we're
2603 not using it. */
2604+
2605+/* cvsacl patch */
2606+#ifdef SERVER_SUPPORT
2607+ if (use_cvs_acl && server_active)
2608+ {
2609+ if (diff_rev1)
2610+ {
2611+ if (!access_allowed (NULL, finfo->repository, diff_rev1, 5,
2612+ NULL, NULL, 1))
2613+ {
2614+ if (stop_at_first_permission_denied)
2615+ error (1, 0, "permission denied for %s",
2616+ Short_Repository (finfo->repository));
2617+ else
2618+ error (0, 0, "permission denied for %s/%s",
2619+ Short_Repository (finfo->repository), finfo->file);
2620+
2621+ return (0);
2622+ }
2623+ }
2624+ if (diff_rev2)
2625+ {
2626+ if (!access_allowed (NULL, finfo->repository, diff_rev2, 5))
2627+ {
2628+ if (stop_at_first_permission_denied)
2629+ error (1, 0, "permission denied for %s",
2630+ Short_Repository (finfo->repository));
2631+ else
2632+ error (0, 0, "permission denied for %s/%s",
2633+ Short_Repository (finfo->repository), finfo->file);
2634+
2635+ return (0);
2636+ }
2637+ }
2638+ }
2639+#endif
2640+
2641 }
2642 else if (vers->vn_user == NULL)
2643 {
2644@@ -827,6 +864,42 @@
2645 if (!isdir (dir))
2646 return (R_SKIP_ALL);
2647
2648+/* cvsacl patch */
2649+#ifdef SERVER_SUPPORT
2650+ if (use_cvs_acl && server_active)
2651+ {
2652+ if (diff_rev1)
2653+ {
2654+ if (!access_allowed (NULL, update_dir, diff_rev1, 5,
2655+ NULL, NULL, 1))
2656+ {
2657+ if (stop_at_first_permission_denied)
2658+ error (1, 0, "permission denied for %s",
2659+ Short_Repository (update_dir));
2660+ else
2661+ error (0, 0, "permission denied for %s/%s",
2662+ Short_Repository (update_dir), update_dir);
2663+
2664+ return (0);
2665+ }
2666+ }
2667+ if (diff_rev2)
2668+ {
2669+ if (!access_allowed (NULL, update_dir, diff_rev2, 5))
2670+ {
2671+ if (stop_at_first_permission_denied)
2672+ error (1, 0, "permission denied for %s",
2673+ Short_Repository (update_dir));
2674+ else
2675+ error (0, 0, "permission denied for %s/%s",
2676+ Short_Repository (update_dir), update_dir);
2677+
2678+ return (0);
2679+ }
2680+ }
2681+ }
2682+#endif
2683+
2684 if (!quiet)
2685 error (0, 0, "Diffing %s", update_dir);
2686 return (R_PROCESS);
4905fec9 2687diff -urN cvs-1.11.18.orig/src/import.c cvs-1.11.18/src/import.c
2688--- cvs-1.11.18.orig/src/import.c 2004-10-29 21:55:14.000000000 +0200
2689+++ cvs-1.11.18/src/import.c 2004-11-14 14:00:39.000000000 +0100
2690@@ -314,6 +314,20 @@
09f63587 2691 error (1, 0, "attempt to import the repository");
2692 }
2693
2694+/* cvsacl patch */
2695+#ifdef SERVER_SUPPORT
2696+ if (use_cvs_acl && server_active)
2697+ {
2698+ if (!access_allowed (NULL, repository, argv[1], 6, NULL, NULL, 1))
2699+ {
2700+ error (stop_at_first_permission_denied, 0, "permission denied for %s",
2701+ Short_Repository (repository));
2702+
2703+ return (0);
2704+ }
2705+ }
2706+#endif
2707+
2708 /*
2709 * Make all newly created directories writable. Should really use a more
2710 * sophisticated security mechanism here.
4905fec9 2711diff -urN cvs-1.11.18.orig/src/log.c cvs-1.11.18/src/log.c
2712--- cvs-1.11.18.orig/src/log.c 2004-05-10 15:37:16.000000000 +0200
2713+++ cvs-1.11.18/src/log.c 2004-11-14 14:00:39.000000000 +0100
09f63587 2714@@ -837,6 +837,25 @@
2715 return 1;
2716 }
2717
2718+/* cvsacl patch */
2719+#ifdef SERVER_SUPPORT
2720+ if (use_cvs_acl && server_active)
2721+ {
2722+ if (!access_allowed (finfo->file, finfo->repository, NULL, 5,
2723+ NULL, NULL, 1))
2724+ {
2725+ if (stop_at_first_permission_denied)
2726+ error (1, 0, "permission denied for %s",
2727+ Short_Repository (finfo->repository));
2728+ else
2729+ error (0, 0, "permission denied for %s/%s",
2730+ Short_Repository (finfo->repository), finfo->file);
2731+
2732+ return (0);
2733+ }
2734+ }
2735+#endif
2736+
2737 if (log_data->sup_header || !log_data->nameonly)
2738 {
2739
4905fec9 2740diff -urN cvs-1.11.18.orig/src/main.c cvs-1.11.18/src/main.c
2741--- cvs-1.11.18.orig/src/main.c 2004-11-14 13:58:05.000000000 +0100
2742+++ cvs-1.11.18/src/main.c 2004-11-14 14:00:39.000000000 +0100
2743@@ -97,6 +97,10 @@
09f63587 2744 } cmds[] =
2745
2746 {
2747+ /* cvsacl patch */
2748+ { "acl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2749+ { "racl", NULL, NULL, cvsacl, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2750+
2751 { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2752 { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
2753 { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR },
4905fec9 2754@@ -959,6 +963,9 @@
09f63587 2755 if we didn't, then there would be no way to check in a new
2756 CVSROOT/config file to fix the broken one! */
2757 parse_config (current_parsed_root->directory);
2758+
2759+ /* cvsacl patch */
2760+ parse_aclconfig (current_parsed_root->directory);
2761 }
2762
2763 #ifdef CLIENT_SUPPORT
4905fec9 2764diff -urN cvs-1.11.18.orig/src/mkmodules.c cvs-1.11.18/src/mkmodules.c
2765--- cvs-1.11.18.orig/src/mkmodules.c 2004-02-03 15:39:40.000000000 +0100
2766+++ cvs-1.11.18/src/mkmodules.c 2004-11-14 14:00:39.000000000 +0100
09f63587 2767@@ -311,6 +311,44 @@
2768 NULL
2769 };
2770
2771+/* cvsacl patch */
2772+static const char *const aclconfig_contents[] = {
2773+ "# Set `UseCVSACL' to yes to use CVSACL feature.\n",
2774+ "UseCVSACL=yes\n",
2775+ "\n",
2776+ "# Default CVSACL Permission to use.\n",
2777+ "#CVSACLDefaultPermissions=p\n",
2778+ "\n",
2779+ "# Default file location for CVS ACL file (access) is CVSROOT/access.\n",
2780+ "# If you want to use a different location, define it below.\n",
2781+ "#CVSACLFileLocation=/path/to/cvs/access\n",
2782+ "\n",
2783+ "# Set `UseSystemGroups' to yes to use system group definitions (/etc/group).\n",
2784+ "UseSystemGroups=yes\n",
2785+ "\n",
2786+ "# Set `UseCVSGroups' to yes to use another group file.\n",
2787+ "#UseCVSGroups=yes\n",
2788+ "\n",
2789+ "# Default file location for CVS groups file is CVSROOT/group.\n",
2790+ "# If you want to use a different location, define it below.\n",
2791+ "#CVSGroupsFileLocation=/path/to/cvs/group\n",
2792+ "\n",
c52fdbcd 2793+ "# Set UseSeparateACLFileForEachDir to yes in order to use a\n",
2794+ "# separate 'access' file for each directory.\n",
09f63587 2795+ "# This increased the performance if you have really big repository.\n",
c52fdbcd 2796+ "#UseSeparateACLFileForEachDir=no\n",
09f63587 2797+ "\n",
2798+ "# If StopAtFirstPermissionDenied is set to yes\n",
2799+ "# operation will stop at first permission denied message.\n",
2800+ "# Default is no.\n",
2801+ "#StopAtFirstPermissionDenied=no\n",
2802+ "\n",
2803+ "# Set CVSServerRunAsUser to a system user, in order CVS server\n",
2804+ "# to run as.\n",
2805+ "#CVSServerRunAsUser=runascvsuser",
2806+ NULL
2807+};
2808+
2809 static const struct admin_file filelist[] = {
2810 {CVSROOTADM_LOGINFO,
2811 "no logging of 'cvs commit' messages is done without a %s file",
2812@@ -373,7 +411,12 @@
2813 {CVSROOTADM_CONFIG,
2814 "a %s file configures various behaviors",
2815 config_contents},
2816- {NULL, NULL, NULL}
2817+
2818+ /* cvsacl patch */
2819+ {CVSROOTADM_ACLCONFIG,
2820+ "a %s file configures Access Control List behaviors",
2821+ aclconfig_contents},
2822+ {NULL, NULL, NULL}
2823 };
2824
2825 /* Rebuild the checked out administrative files in directory DIR. */
2826@@ -957,6 +1000,26 @@
2827 because xchmod() is too shy. */
2828 chmod (info, 0666);
2829 }
2830+
2831+ /* cvsacl patch */
2832+ /* Make an empty 'CVSROOT/access' file */
2833+ strcpy (info, adm);
2834+ strcat (info, "/");
2835+ strcat (info, CVSROOTADM_ACCESS);
2836+ if (!isfile (info))
2837+ {
2838+ FILE *fp;
2839+
2840+ fp = open_file (info, "w");
2841+ if (fputs ("# CVS ACL definitions file. DO NOT EDIT MANUALLY\n",
2842+ fp) < 0)
2843+ error (1, errno, "cannot write %s", info);
2844+
2845+ if (fclose (fp) < 0)
2846+ error (1, errno, "cannot close %s", info);
2847+
2848+ chmod (info, 0644);
2849+ }
2850
2851 /* Make an empty val-tags file to prevent problems creating it later. */
2852 strcpy (info, adm);
4905fec9 2853diff -urN cvs-1.11.18.orig/src/parseinfo.c cvs-1.11.18/src/parseinfo.c
2854--- cvs-1.11.18.orig/src/parseinfo.c 2004-03-19 21:36:39.000000000 +0100
2855+++ cvs-1.11.18/src/parseinfo.c 2004-11-14 14:00:39.000000000 +0100
09f63587 2856@@ -448,3 +448,192 @@
2857 free (line);
2858 return -1;
2859 }
2860+/* cvsacl patch */
2861+int
2862+parse_aclconfig (cvsroot)
2863+ char *cvsroot;
2864+{
2865+ char *infopath;
2866+ FILE *fp_info;
2867+ char *line = NULL;
2868+ size_t line_allocated = 0;
2869+ size_t len;
2870+ char *p;
2871+ /* FIXME-reentrancy: If we do a multi-threaded server, this would need
2872+ to go to the per-connection data structures. */
2873+ static int parsed = 0;
2874+
2875+ /* Authentication code and serve_root might both want to call us.
2876+ Let this happen smoothly. */
2877+ if (parsed)
2878+ return 0;
2879+ parsed = 1;
2880+
2881+ infopath = xmalloc (strlen (cvsroot)
2882+ + sizeof (CVSROOTADM_ACLCONFIG)
2883+ + sizeof (CVSROOTADM)
2884+ + 10);
2885+ if (infopath == NULL)
2886+ {
2887+ error (0, 0, "out of memory; cannot allocate infopath");
2888+ goto error_return;
2889+ }
2890+
2891+ strcpy (infopath, cvsroot);
2892+ strcat (infopath, "/");
2893+ strcat (infopath, CVSROOTADM);
2894+ strcat (infopath, "/");
2895+ strcat (infopath, CVSROOTADM_ACLCONFIG);
2896+
2897+ fp_info = CVS_FOPEN (infopath, "r");
2898+ if (fp_info == NULL)
2899+ {
2900+ /* If no file, don't do anything special. */
2901+ if (!existence_error (errno))
2902+ {
2903+ /* Just a warning message; doesn't affect return
2904+ value, currently at least. */
2905+ error (0, errno, "cannot open %s", infopath);
2906+ }
2907+ free (infopath);
2908+ return 0;
2909+ }
2910+
2911+ while (getline (&line, &line_allocated, fp_info) >= 0)
2912+ {
2913+ /* Skip comments. */
2914+ if (line[0] == '#')
2915+ continue;
2916+
2917+ len = strlen (line) - 1;
2918+ if (line[len] == '\n')
2919+ line[len] = '\0';
2920+
2921+ /* Skip blank lines. */
2922+ if (line[0] == '\0')
2923+ continue;
2924+
2925+ /* The first '=' separates keyword from value. */
2926+ p = strchr (line, '=');
2927+ if (p == NULL)
2928+ {
2929+ /* Probably should be printing line number. */
2930+ error (0, 0, "syntax error in %s: line '%s' is missing '='",
2931+ infopath, line);
2932+ goto error_return;
2933+ }
2934+
2935+ *p++ = '\0';
2936+
2937+ if (strcmp (line, "UseCVSACL") == 0)
2938+ {
2939+ if (strcmp (p, "no") == 0)
2940+ use_cvs_acl = 0;
2941+ else if (strcmp (p, "yes") == 0)
2942+ use_cvs_acl = 1;
2943+ else
2944+ {
2945+ error (0, 0, "unrecognized value '%s' for UseCVSACL", p);
2946+ goto error_return;
2947+ }
2948+ }
c52fdbcd 2949+ else if (strcmp (line, "UseSeparateACLFileForEachDir") == 0)
09f63587 2950+ {
2951+ if (strcmp (p, "no") == 0)
c52fdbcd 2952+ use_separate_acl_file_for_each_dir = 0;
09f63587 2953+ else if (strcmp (p, "yes") == 0)
c52fdbcd 2954+ use_separate_acl_file_for_each_dir = 1;
09f63587 2955+ else
2956+ {
c52fdbcd 2957+ error (0, 0, "unrecognized value '%s' for UseSeparateACLFileForEachDir", p);
09f63587 2958+ goto error_return;
2959+ }
2960+ }
2961+ else if (strcmp (line, "StopAtFirstPermissionDenied") == 0)
2962+ {
2963+ if (strcmp (p, "no") == 0)
2964+ stop_at_first_permission_denied = 0;
2965+ else if (strcmp (p, "yes") == 0)
2966+ stop_at_first_permission_denied = 1;
2967+ else
2968+ {
2969+ error (0, 0, "unrecognized value '%s' for StopAtFirstPermissionDenied", p);
2970+ goto error_return;
2971+ }
2972+ }
2973+ else if (strcmp (line, "CVSACLDefaultPermissions") == 0)
2974+ {
2975+ if (cvs_acl_default_permissions != NULL)
2976+ free (cvs_acl_default_permissions);
2977+ if (!given_perms_valid (p))
2978+ error (1,0,"Invalid CVS ACL Default Permissions: '%s' in CVSROOT/aclconfig", p);
2979+ cvs_acl_default_permissions = xstrdup (p);
2980+ }
2981+ else if (strcmp (line, "UseCVSGroups") == 0)
2982+ {
2983+ if (strcmp (p, "no") == 0)
2984+ use_cvs_groups = 0;
2985+ else if (strcmp (p, "yes") == 0)
2986+ use_cvs_groups = 1;
2987+ else
2988+ {
2989+ error (0, 0, "unrecognized value '%s' for UseCVSGroups", p);
2990+ goto error_return;
2991+ }
2992+ }
2993+ else if (strcmp (line, "UseSystemGroups") == 0)
2994+ {
2995+ if (strcmp (p, "no") == 0)
2996+ use_system_groups = 0;
2997+ else if (strcmp (p, "yes") == 0)
2998+ use_system_groups = 1;
2999+ else
3000+ {
3001+ error (0, 0, "unrecognized value '%s' for UseSystemGroups", p);
3002+ goto error_return;
3003+ }
3004+ }
3005+ else if (strcmp (line, "CVSACLFileLocation") == 0)
3006+ {
3007+ if (cvs_acl_file_location != NULL)
3008+ free (cvs_acl_file_location);
3009+ cvs_acl_file_location = xstrdup (p);
3010+ }
3011+ else if (strcmp (line, "CVSGroupsFileLocation") == 0)
3012+ {
3013+ if (cvs_groups_file_location != NULL)
3014+ free (cvs_groups_file_location);
3015+ cvs_groups_file_location = xstrdup (p);
3016+ }
3017+ else if (strcmp (line, "CVSServerRunAsUser") == 0)
3018+ {
3019+ if (cvs_server_run_as != NULL)
3020+ free (cvs_server_run_as);
3021+ cvs_server_run_as = xstrdup (p);
3022+ }
3023+
3024+ }
3025+
3026+ if (ferror (fp_info))
3027+ {
3028+ error (0, errno, "cannot read %s", infopath);
3029+ goto error_return;
3030+ }
3031+ if (fclose (fp_info) < 0)
3032+ {
3033+ error (0, errno, "cannot close %s", infopath);
3034+ goto error_return;
3035+ }
3036+ free (infopath);
3037+ if (line != NULL)
3038+ free (line);
3039+ return 0;
3040+
3041+ error_return:
3042+ if (infopath != NULL)
3043+ free (infopath);
3044+ if (line != NULL)
3045+ free (line);
3046+ return -1;
3047+}
3048+
4905fec9 3049diff -urN cvs-1.11.18.orig/src/patch.c cvs-1.11.18/src/patch.c
3050--- cvs-1.11.18.orig/src/patch.c 2004-04-02 21:25:32.000000000 +0200
3051+++ cvs-1.11.18/src/patch.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3052@@ -498,6 +498,43 @@
3053 goto out2;
3054 }
3055
3056+/* cvsacl patch */
3057+#ifdef SERVER_SUPPORT
3058+ if (use_cvs_acl && server_active)
3059+ {
3060+ if (rev1)
3061+ {
3062+ if (!access_allowed (finfo->file, finfo->repository, rev1, 5,
3063+ NULL, NULL, 1))
3064+ {
3065+ if (stop_at_first_permission_denied)
3066+ error (1, 0, "permission denied for %s",
3067+ Short_Repository (finfo->repository));
3068+ else
3069+ error (0, 0, "permission denied for %s/%s",
3070+ Short_Repository (finfo->repository), finfo->file);
3071+
3072+ return (0);
3073+ }
3074+ }
3075+ if (rev2)
3076+ {
3077+ if (!access_allowed (finfo->file, finfo->repository, rev2, 5,
3078+ NULL, NULL, 1))
3079+ {
3080+ if (stop_at_first_permission_denied)
3081+ error (1, 0, "permission denied for %s",
3082+ Short_Repository (finfo->repository));
3083+ else
3084+ error (0, 0, "permission denied for %s/%s",
3085+ Short_Repository (finfo->repository), finfo->file);
3086+
3087+ return (0);
3088+ }
3089+ }
3090+ }
3091+#endif
3092+
3093 /* Create 3 empty files. I'm not really sure there is any advantage
3094 * to doing so now rather than just waiting until later.
3095 *
4905fec9 3096diff -urN cvs-1.11.18.orig/src/remove.c cvs-1.11.18/src/remove.c
3097--- cvs-1.11.18.orig/src/remove.c 2004-03-20 03:34:32.000000000 +0100
3098+++ cvs-1.11.18/src/remove.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3099@@ -250,6 +250,25 @@
3100 {
3101 char *fname;
3102
3103+/* cvsacl patch */
3104+#ifdef SERVER_SUPPORT
3105+ if (use_cvs_acl && server_active)
3106+ {
3107+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 7,
3108+ NULL, NULL, 1))
3109+ {
3110+ if (stop_at_first_permission_denied)
3111+ error (1, 0, "permission denied for %s",
3112+ Short_Repository (finfo->repository));
3113+ else
3114+ error (0, 0, "permission denied for %s/%s",
3115+ Short_Repository (finfo->repository), finfo->file);
3116+
3117+ return (0);
3118+ }
3119+ }
3120+#endif
3121+
3122 /* Re-register it with a negative version number. */
3123 fname = xmalloc (strlen (vers->vn_user) + 5);
3124 (void) strcpy (fname, "-");
4905fec9 3125diff -urN cvs-1.11.18.orig/src/server.c cvs-1.11.18/src/server.c
3126--- cvs-1.11.18.orig/src/server.c 2004-11-14 13:58:05.000000000 +0100
3127+++ cvs-1.11.18/src/server.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3128@@ -773,6 +773,10 @@
3129 nothing. But for rsh, we need to do it now. */
3130 parse_config (current_parsed_root->directory);
3131
3132+ /* cvsacl patch */
3133+ parse_aclconfig (current_parsed_root->directory);
3134+
3135+
3136 path = xmalloc (strlen (current_parsed_root->directory)
3137 + sizeof (CVSROOTADM)
3138 + 2);
c52fdbcd 3139@@ -3761,6 +3765,23 @@
09f63587 3140 do_cvs_command ("rlog", cvslog);
3141 }
3142
3143+/* cvsacl patch */
3144+static void
3145+serve_acl (arg)
3146+ char *arg;
3147+{
3148+ do_cvs_command ("acl", cvsacl);
3149+}
3150+
3151+/* cvsacl patch */
3152+static void
3153+serve_racl (arg)
3154+ char *arg;
3155+{
c52fdbcd 3156+ cvs_cmd_name = "racl";
09f63587 3157+ do_cvs_command ("racl", cvsacl);
3158+}
3159+
3160 static void
3161 serve_add (arg)
3162 char *arg;
4905fec9 3163@@ -4821,6 +4842,11 @@
09f63587 3164 REQ_LINE("diff", serve_diff, 0),
3165 REQ_LINE("log", serve_log, 0),
3166 REQ_LINE("rlog", serve_rlog, 0),
3167+
3168+ /* cvsacl patch */
3169+ REQ_LINE("acl", serve_acl, 0),
3170+ REQ_LINE("racl", serve_racl, 0),
3171+
3172 REQ_LINE("add", serve_add, 0),
3173 REQ_LINE("remove", serve_remove, 0),
3174 REQ_LINE("update-patches", serve_ignore, 0),
4905fec9 3175@@ -5294,6 +5320,10 @@
09f63587 3176 {
3177 struct passwd *pw;
3178
3179+ /* cvsacl patch */
3180+ if (use_cvs_acl && cvs_server_run_as)
3181+ username = cvs_server_run_as;
3182+
3183 pw = getpwnam (username);
3184 if (pw == NULL)
3185 {
4905fec9 3186@@ -5876,6 +5906,9 @@
09f63587 3187 in a new CVSROOT/config file to fix the broken one! */
3188 parse_config (repository);
3189
3190+ /* cvsacl patch */
3191+ parse_aclconfig (repository);
3192+
3193 /* We need the real cleartext before we hash it. */
3194 descrambled_password = descramble (password);
3195 host_user = check_password (username, descrambled_password, repository);
4905fec9 3196diff -urN cvs-1.11.18.orig/src/status.c cvs-1.11.18/src/status.c
3197--- cvs-1.11.18.orig/src/status.c 2004-03-20 02:40:12.000000000 +0100
3198+++ cvs-1.11.18/src/status.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3199@@ -128,7 +128,27 @@
3200
3201 status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
3202 1, 0, &vers, 0);
3203- sstat = "Classify Error";
3204+
3205+/* cvsacl patch */
3206+#ifdef SERVER_SUPPORT
3207+ if (use_cvs_acl && server_active)
3208+ {
3209+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3210+ NULL, NULL, 1))
3211+ {
3212+ if (stop_at_first_permission_denied)
3213+ error (1, 0, "permission denied for %s",
3214+ Short_Repository (finfo->repository));
3215+ else
3216+ error (0, 0, "permission denied for %s/%s",
3217+ Short_Repository (finfo->repository), finfo->file);
3218+
3219+ return (0);
3220+ }
3221+ }
3222+#endif
3223+
3224+ sstat = "Classify Error";
3225 switch (status)
3226 {
3227 case T_UNKNOWN:
4905fec9 3228diff -urN cvs-1.11.18.orig/src/tag.c cvs-1.11.18/src/tag.c
3229--- cvs-1.11.18.orig/src/tag.c 2004-08-24 18:32:48.000000000 +0200
3230+++ cvs-1.11.18/src/tag.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3231@@ -660,6 +660,25 @@
3232 * correctly without breaking your link!
3233 */
3234
3235+/* cvsacl patch */
3236+#ifdef SERVER_SUPPORT
3237+ if (use_cvs_acl && server_active)
3238+ {
3239+ if (!access_allowed (finfo->file, finfo->repository, numtag, 4,
3240+ NULL, NULL, 1))
3241+ {
3242+ if (stop_at_first_permission_denied)
3243+ error (1, 0, "permission denied for %s",
3244+ Short_Repository (finfo->repository));
3245+ else
3246+ error (0, 0, "permission denied for %s/%s",
3247+ Short_Repository (finfo->repository), finfo->file);
3248+
3249+ return (0);
3250+ }
3251+ }
3252+#endif
3253+
3254 if (delete_flag)
3255 return (rtag_delete (rcsfile));
3256
3257@@ -880,6 +899,21 @@
3258 if (nversion == NULL)
3259 goto free_vars_and_return;
3260 }
3261+
3262+/* cvsacl patch */
3263+#ifdef SERVER_SUPPORT
3264+ if (use_cvs_acl && server_active)
3265+ {
3266+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 4,
3267+ NULL, NULL, 1))
3268+ {
3269+ error (0, 0, "permission denied for %s/%s",
3270+ Short_Repository (finfo->repository), finfo->file);
3271+ return (0);
3272+ }
3273+ }
3274+#endif
3275+
3276 if (delete_flag)
3277 {
3278
4905fec9 3279diff -urN cvs-1.11.18.orig/src/update.c cvs-1.11.18/src/update.c
3280--- cvs-1.11.18.orig/src/update.c 2004-10-29 21:55:17.000000000 +0200
3281+++ cvs-1.11.18/src/update.c 2004-11-14 14:00:39.000000000 +0100
c52fdbcd 3282@@ -596,6 +596,26 @@
09f63587 3283 status = Classify_File (finfo, tag, date, options, force_tag_match,
3284 aflag, &vers, pipeout);
3285
3286+
3287+/* cvsacl patch */
3288+#ifdef SERVER_SUPPORT
3289+ if (use_cvs_acl && server_active)
3290+ {
3291+ if (!access_allowed (finfo->file, finfo->repository, vers->tag, 5,
3292+ NULL, NULL, 1))
3293+ {
3294+ if (stop_at_first_permission_denied)
3295+ error (1, 0, "permission denied for %s",
3296+ Short_Repository (finfo->repository));
3297+ else
3298+ error (0, 0, "permission denied for %s/%s",
3299+ Short_Repository (finfo->repository), finfo->file);
3300+
3301+ return (0);
3302+ }
3303+ }
3304+#endif
3305+
3306 /* Keep track of whether TAG is a branch tag.
3307 Note that if it is a branch tag in some files and a nonbranch tag
3308 in others, treat it as a nonbranch tag. It is possible that case
4905fec9 3309diff -urN cvs-1.11.18.orig/src/version.c cvs-1.11.18/src/version.c
3310--- cvs-1.11.18.orig/src/version.c 2004-02-03 15:37:56.000000000 +0100
3311+++ cvs-1.11.18/src/version.c 2004-11-14 14:00:39.000000000 +0100
09f63587 3312@@ -26,7 +26,8 @@
3313 #endif
3314 #endif
3315
3316-
3317+/* cvsacl patch */
67ba4c3a 3318+char *aclpatch_string = "with CVSACL Patch 1.2.1 (cvsacl.sourceforge.net)\n";
09f63587 3319
3320 static const char *const version_usage[] =
3321 {
3322@@ -63,6 +64,8 @@
3323 released. */
3324 (void) fputs (PACKAGE_STRING, stdout);
3325 (void) fputs (config_string, stdout);
3326+ /* cvsacl patch */
3327+ (void) fputs (aclpatch_string, stdout);
3328
3329 #ifdef CLIENT_SUPPORT
3330 if (current_parsed_root && current_parsed_root->isremote)
This page took 0.612964 seconds and 4 git commands to generate.