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