/*
* Copyright (C) 2006 The Free Software Foundation, Inc.
*
* Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net>
* <http://cvsacl.sourceforge.net>
*
*
* You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS source distribution.
*
*
*
* CVS ACCESS CONTROL LIST EXTENSION
*
* It provides advanced access control definitions per modules,
* directories, and files on branch/tag for remote cvs repository
* connections.Execution of all CVS subcommands can be controlled
* with eight different permissions.
*
* Permission Types:
* - no permission (n) (1)
* - all permissions (a) (2)
* - write permission (w) (3)
* - tag permission (t) (4)
* - read permission (r) (5)
* - add permission (c) (6)
* - remove permission (d) (7)
* - permission change (p) (8)
*
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: acl.c,v 1.6 2016/05/17 14:00:09 christos Exp $");
#include "cvs.h"
#include "getline.h"
#include <pwd.h>
#include <grp.h>
static int acl_fileproc (void *callerdat, struct file_info *finfo);
static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos,
const char *update_dir, List *entries);
static int acllist_fileproc (void *callerdat, struct file_info *finfo);
static Dtype acllist_dirproc (void *callerdat, const char *dir,
const char *repos, const char *update_dir,
List *entries);
static void acllist_print (char *line, const char *obj);
static int racl_proc (int argc, char **argv, char *xwhere,
char *mwhere, char *mfile, int shorten,
int local_specified, char *mname, char *msg);
static FILE *open_accessfile (char *xmode, const char *repos, char **fname);
static FILE *open_groupfile (char *xmode);
static char *get_perms (const char *xperms);
static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
static char *findusername (const char *string1, const char *string2);
static char *findgroupname (const char *string1, const char *string2);
static int valid_tag (const char *part_tag, const char *tag);
static int valid_perm (const char *part_perms, int perm);
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);
static char *cache_repository;
static int cache_retval;
static int founddeniedfile;
static int cache_perm;
static int is_racl;
static int debug = 0;
int use_cvs_acl = 0;
char *cvs_acl_default_permissions;
int use_cvs_groups = 0;
int use_system_groups = 0;
int use_separate_acl_file_for_each_dir = 0;
char *cvs_acl_file_location = NULL;
char *cvs_groups_file_location = NULL;
char *cvs_server_run_as = NULL;
int stop_at_first_permission_denied = 0;
char *tag = NULL;
char *muser;
char *mperms;
static int defaultperms;
static char *default_perms_object;
char *default_part_perms_accessfile;
int aclconfig_default_used;
int acldir = 0;
int aclfile = 0;
int listacl = 0;
int userfound = 0;
int groupfound = 0;
/* directory depth ... */
char *dirs[255];
static const char *const acl_usage[] =
{
"Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n",
"\t-R\tProcess directories recursively.\n",
"\t-r rev\tExisting revision/tag.\n",
"\t-l\tList defined ACLs.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
static const char *const racl_usage[] =
{
"Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...]"
" [files...]\n",
"\t-R\tProcess directories recursively.\n",
"\t-r rev\tExisting revision/tag.\n",
"\t-l\tList defined ACLs.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
int
access_allowed (const char *file, const char *repos, const char *tag,
int perm, char **mline, int *mpos, int usecache)
{
int retval = 0;
int foundline = 0;
FILE *accessfp;
int flag = 1;
char *iline;
char *tempv;
char *tempc;
size_t tempsize;
int intcount;
int accessfilecount;
int signlevel = -1;
int dadmin = 0;
const char *repository;
char *filefullname = NULL;
userfound = 0;
groupfound = 0;
if (defaultperms)
{
repository = xstrdup ("ALL");
}
else {
if (strlen(repository = Short_Repository (repos)) == 0)
{
repository = xstrdup (".");
}
}
/* cache */
if (usecache && cache_repository != NULL &&
strcmp (cache_repository, repository) == 0 && !founddeniedfile
&& perm == cache_perm)
return (cache_retval);
else
{
free (cache_repository);
cache_repository = xstrdup (repository);
cache_perm = perm;
}
iline = xstrdup(repository);
tempv = strtok(iline, "/\t");
tempc = xstrdup(tempv);
tempsize = ( tempc != NULL ) ? strlen(tempc) : 0;
intcount = 0;
/* store paths from object to cvsroot */
dirs[intcount] = xstrdup(tempc);
while ((tempv = strtok(NULL, "/\t")) != NULL)
{
intcount++;
xrealloc_and_strcat(&tempc, &tempsize, "/");
xrealloc_and_strcat(&tempc, &tempsize, tempv);
dirs[intcount] = xstrdup(tempc);
}
/* free not needed variables here */
free (tempv);
free (tempc);
free (iline);
/* accessfilecount will used
* if UseSeparateACLFile keyword is set to yes*/
accessfilecount = intcount;
/* if file is not null add it to dirs array */
if (file != NULL)
{
filefullname = Xasprintf("%s/%s", repository, file);
intcount++;
dirs[intcount] = xstrdup(filefullname);
}
for (; accessfilecount >= 0 && flag; accessfilecount--)
{
if (!use_separate_acl_file_for_each_dir) {
flag = 0;
accessfp = open_accessfile ("r", repository, NULL);
}
else
{
flag = 1;
accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
}
if (accessfp != NULL)
{
char *line = NULL;
size_t line_allocated = 0;
char *xline;
char *part_type = NULL;
char *part_object = NULL;
char *part_tag = NULL;
char *part_perms = NULL;
int x;
while (getline (&line, &line_allocated, accessfp) >= 0)
{
if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
continue;
xline = xstrdup (line);
part_type = strtok (line, ":\t");
part_object = strtok (NULL, ":\t");
part_tag = strtok (NULL, ":\t");
part_perms = strtok (NULL, ":\t");
if (part_type == NULL || part_object == NULL ||
part_tag == NULL || part_perms == NULL)
{
free (line);
error(1, 0, "access file is corrupted or has invalid"
" format");
}
if (debug) fprintf (stderr, "type %s object %s tag %s perms"
"%s\n", part_type, part_object, part_tag,
part_perms);
for (x = intcount; x >= signlevel && x != -1; x--)
{
if (debug) fprintf (stderr, "dirs[%d] = %s, part_object="
"%s\n", x, dirs[x], part_object);
if (strcmp (dirs[x], part_object) == 0)
{
if (debug) fprintf(stderr, "tag %s \n", tag);
if (valid_tag (part_tag, tag))
{
foundline = 1;
if (debug) fprintf(stderr, "foundline\n");
if (listacl || ((acldir || aclfile) &&
x == intcount) &&
strcmp(part_tag, tag) == 0)
{
*mline = xstrdup (xline);
*mpos = ftell (accessfp);
}
if (debug) fprintf(stderr, "perm %d\n", perm);
if (valid_perm (part_perms, perm))
{
if (debug) fprintf(stderr, "signlevel=%d "
" x=%d, aclconfig_default_used=%d\n",
signlevel, x, aclconfig_default_used);
if (signlevel == x)
{
if (strcmp(part_tag, "ALL") != 0 &&
!aclconfig_default_used) {
retval = 1;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
}
}
else if (!aclconfig_default_used)
{
signlevel = x;
retval = 1;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
}
else {
/* nothing... */
}
}
else
{
if (signlevel == x)
{
if (strcmp(part_tag, "ALL") != 0 &&
!aclconfig_default_used) {
retval = 0;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
}
}
else if (!aclconfig_default_used)
{
signlevel = x;
retval = 0;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
if (strncmp (part_type, "f", 1) == 0)
founddeniedfile = 1;
}
else {
}
}
}
}
}
if (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline,
groupfound, userfound);
if (strncmp (xline, "d:ALL:", 6) == 0 &&
((!groupfound && !userfound) || listacl))
{
if (debug) fprintf (stderr, "ALL tag = %s\n", tag);
/* a default found */
if (valid_tag (part_tag, tag) > 0)
{
foundline = 1;
default_part_perms_accessfile = xstrdup (part_perms);
if (debug) fprintf (stderr, "valid perm = %d\n", perm);
if (valid_perm (part_perms, perm))
{
retval = 1;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
if (perm == 8)
dadmin = 1;
}
else {
retval = 0;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
}
}
}
}
if (fclose (accessfp) == EOF)
error (1, errno, "cannot close 'access' file");
}
}
if (!foundline)
{
if (debug) fprintf(stderr, "not found line\n");
/* DEFAULT */
if (valid_perm (NULL, perm)) {
retval = 1;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
} else {
retval = 0;
if (debug) fprintf(stderr,
"%s, %d: %d\n", __FILE__, __LINE__,
retval);
}
}
/* acl admin rigths 'p' */
if (dadmin)
{
retval = dadmin;
}
cache_retval = retval;
free (filefullname);
/* free directories array */
while (intcount >= 0)
{
free (dirs[intcount]);
intcount--;
}
return retval;
}
/* Returns 1 if tag is valid, 0 if not */
static int
valid_tag (const char *part_tag, const char *tag)
{
int retval;
if (tag == NULL)
tag = "HEAD";
if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0)
retval = 1;
else
retval = 0;
return retval;
}
/* Returns 1 if successful, 0 if not. */
static int
valid_perm (const char *part_perms, int perm)
{
char *perms;
int retval = 0;
perms = get_perms (part_perms);
/* Allow, if nothing found. */
if (perms[0] == '\0')
return (1);
/* no access allowed, exit */
if (strstr (perms, "n"))
retval = 0;
if (strstr (perms, "p"))
/* admin rights */
retval = 1;
else if (strstr (perms, "a") && perm != 8)
/* all access allowed, exit */
retval = 1;
else
switch (perm)
{
case 3:/* write permission */
if (strstr (perms, "w"))
retval = 1;
break;
case 4:/* tag permission */
if (strstr (perms, "t"))
retval = 1;
break;
case 5:/* read permission */
if (strstr (perms, "w") || strstr (perms, "t") ||
strstr (perms, "c") || strstr (perms, "d") ||
strstr (perms, "r"))
retval = 1;
break;
case 6:/* create permission */
if (strstr (perms, "c"))
retval = 1;
break;
case 7:/* delete permission */
if (strstr (perms, "d"))
retval = 1;
break;
case 8:/* permission change */
if (strstr (perms, "p"))
retval = 1;
break;
default:/* never reached */
retval = 0;
break;
}
free (perms);
return (retval);
}
/* returns permissions found */
char *
get_perms (const char *part_perms)
{
char *username;
char *xperms;
size_t xperms_len = 1;
FILE *groupfp;
char *founduser = NULL;
char *foundall = NULL;
int default_checked = 0;
if (debug) fprintf (stderr, "get_perms %s...", part_perms);
aclconfig_default_used = 0;
xperms = xmalloc (xperms_len);
xperms[0] = '\0';
/* use CVS_Username if set */
if (CVS_Username == NULL)
username = getcaller ();
else
username = CVS_Username;
/* no defined acl, no default acl in access file,
* or no access file at all */
if (part_perms == NULL) {
if (cvs_acl_default_permissions)
{
aclconfig_default_used = 1;
if (debug) fprintf (stderr, "default %s\n",
cvs_acl_default_permissions);
return xstrdup(cvs_acl_default_permissions);
}
else {
if (debug) fprintf (stderr, "early %s\n", xperms);
return xperms;
}
}
check_default:
founduser = findusername (part_perms, username);
foundall = strstr (part_perms, "ALL!");
if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n",
founduser, foundall);
if (founduser)
{
char *usr;
char *per;
usr = strtok (founduser, "!\t");
per = strtok (NULL, ",\t");
free(xperms);
xperms = xstrdup (per);
xperms_len = strlen (xperms);
userfound = 1;
free (founduser);
}
else
{
if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups);
if (use_system_groups) {
struct group *griter;
struct passwd *pwd;
gid_t gid = (pwd = getpwnam(username)) != NULL ? pwd->pw_gid : -1;
setgrent ();
while (griter = getgrent ())
{
char *userchk;
if (gid == griter->gr_gid) {
userchk = username;
} else {
char **users = griter->gr_mem;
int index = 0;
userchk = users [index++];
while(userchk != NULL) {
if(strcmp (userchk, username) == 0)
break;
userchk = users[index++];
}
}
if (userchk != NULL) {
char *grp;
if ((grp = findusername (part_perms, griter->gr_name)))
{
char *gperm = strtok (grp, "!\t");
if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n",
userchk, grp);
gperm = strtok (NULL, ",\t");
xrealloc_and_strcat (&xperms, &xperms_len, gperm);
groupfound = 1;
free (grp);
}
}
}
endgrent ();
}
else if (use_cvs_groups) {
groupfp = open_groupfile ("r");
if (groupfp != NULL)
{
char *line = NULL;
char *grp;
char *gperm;
int read;
size_t line_allocated = 0;
while ((read = getline (&line, &line_allocated, groupfp)) >= 0)
{
char *user;
if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
continue;
if (line[read - 1] == '\n')
line[--read] = '\0';
if ((grp = findgroupname (line, username)) &&
(user = findusername (part_perms, grp)))
{
gperm = strtok (user, "!\t");
gperm = strtok (NULL, ",\t");
xrealloc_and_strcat (&xperms, &xperms_len, gperm);
groupfound = 1;
free (grp);
free (user);
}
}
free (line);
if (fclose (groupfp) == EOF)
error (1, errno, "cannot close 'group' file");
}
}
}
if (foundall)
{
char *usr;
char *per;
usr = strtok (strstr (part_perms, "ALL!"), "!\t");
per = strtok (NULL, ",\t");
if (!default_checked)
default_perms_object = xstrdup (per);
if (xperms[0] == '\0')
{
xperms = xstrdup (per);
xperms_len = strlen (xperms);
}
/* You don't free pointers from strtok()! */
//free(usr);
//free(per);
}
if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
{
part_perms = xstrdup (default_part_perms_accessfile);
default_checked = 1;
goto check_default;
}
if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
{
if (default_perms_object)
xperms = xstrdup (default_perms_object);
else if (default_part_perms_accessfile)
{
part_perms = default_part_perms_accessfile;
default_checked = 1;
goto check_default;
}
else if (cvs_acl_default_permissions)
{
aclconfig_default_used = 1;
xperms = xstrdup (cvs_acl_default_permissions);
}
}
if (xperms[0] == '\0' && cvs_acl_default_permissions)
{
aclconfig_default_used = 1;
xperms = xstrdup (cvs_acl_default_permissions);
}
if (debug) fprintf (stderr, "late %s\n", xperms);
return xperms;
}
int
cvsacl (int argc, char **argv)
{
char *chdirrepository;
int c;
int err = 0;
int usetag = 0;
int recursive = 0;
int which;
char *where;
is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
if (argc == -1)
usage (is_racl ? racl_usage : acl_usage);
/* parse the args */
optind = 0;
while ((c = getopt (argc, argv, "dRr:l")) != -1)
{
switch (c)
{
case 'd':
debug++;
break;
case 'R':
recursive = 1;
break;
case 'r': // baris
tag = xstrdup (optarg);
break;
case 'l':
listacl = 1;
break;
case '?':
default:
usage (is_racl ? racl_usage : acl_usage);
break;
}
}
argc -= optind;
argv += optind;
if (argc < (is_racl ? 1 : 1))
usage (is_racl ? racl_usage : acl_usage);
if (listacl) {
if (strstr (argv[0], ":"))
usage (is_racl ? racl_usage : acl_usage);
} else {
if (!strstr (argv[0], ":"))
usage (is_racl ? racl_usage : acl_usage);
}
#ifdef CLIENT_SUPPORT
if (current_parsed_root->isremote)
{
start_server ();
ign_setup ();
if(recursive)
send_arg ("-R");
if (listacl)
send_arg ("-l");
if(tag)
{
option_with_arg ("-r", tag);
}
send_arg ("--");
if (!listacl)
{
send_arg (argv[0]);
argc--;
argv++;
}
if (is_racl)
{
int i;
for (i = 0; i < argc; ++i)
send_arg (argv[i]);
send_to_server ("racl\012",0);
}
else
{
send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("acl\012", 0);
}
return get_responses_and_close ();
}
#endif
#ifdef SERVER_SUPPORT
if (!listacl)
{
muser = strtok (argv[0], ":\t");
mperms = strtok (NULL, ":\t");
/* if set to 'default' */
if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
mperms = xstrdup ("x");
/* Check that the given permissions are valid. */
if (!given_perms_valid (mperms))
error (1,0,"Invalid permissions: `%s'", mperms);
argc--;
argv++;
}
if (!tag)
tag = xstrdup ("HEAD");
if (!strcasecmp (argv[0], "ALL"))
{
argv[0] = xstrdup (".");
defaultperms = 1;
if (!use_separate_acl_file_for_each_dir)
{
recursive = 0;
}
}
if (is_racl)
{
DBM *db;
int i;
db = open_module ();
for (i = 0; i < argc; i++)
{
err += do_module (db, argv[i], MISC, "ACL ing: ",
racl_proc, NULL, 0, !recursive, 0,
0, NULL);
}
close_module (db);
}
else
{
err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive,
NULL, NULL);
}
return err;
#endif
}
static int
racl_proc (int argc, char **argv, char *xwhere, char *mwhere,
char *mfile, int shorten, int local, char *mname, char *msg)
{
char *myargv[2];
int err = 0;
int which;
char *repository;
char *where;
char *obj;
size_t objlen = 0;
if (!use_cvs_acl)
{
error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'"
" in aclconfig file");
}
if (is_racl)
{
char *v;
repository = Xasprintf ("%s/%s", current_parsed_root->directory,
argv[0]);
where = xstrdup (argv[0]);
/* if mfile isn't null, we need to set up to do only part of the
* module */
if (mfile != NULL)
{
char *cp;
char *path;
/* if the portion of the module is a path, put the dir part on
* repos */
if ((cp = strrchr (mfile, '/')) != NULL)
{
*cp = '\0';
v = Xasprintf ("%s/%s", repository, mfile);
free (repository);
repository = v;
v = Xasprintf ("%s/%s", where, mfile);
free(where);
where = v;
mfile = cp + 1;
}
/* take care of the rest */
path = Xasprintf ("%s/%s", repository, mfile);
if (isdir (path))
{
/* directory means repository gets the dir tacked on */
free(repository);
repository = path;
v = Xasprintf ("%s/%s", where, mfile);
free(where);
where = v;
}
else
{
free (path);
myargv[0] = argv[0];
myargv[1] = mfile;
argc = 2;
argv = myargv;
}
}
/* cd to the starting repository */
if ( CVS_CHDIR (repository) < 0)
{
error (0, errno, "cannot chdir to %s", repository);
free (repository);
free (where);
return 1;
}
/* End section which is identical to patch_proc. */
which = W_REPOS | W_ATTIC;
if (argc > 1)
{
obj = Xasprintf ("%s/%s", repository, argv[1]);
}
else
{
obj = xstrdup(repository);
}
}
else
{
where = NULL;
repository = NULL;
which = W_LOCAL | W_REPOS | W_ATTIC;
obj = xstrdup (argv[1]);
}
if (isdir (obj))
acldir = 1;
else if (isfile (obj))
aclfile = 1;
else
error(1, 0, "no such file or directory");
free (obj);
if (listacl)
err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL,
NULL, argc - 1, argv + 1, local, which, 0, 0,
where, 1, repository);
else
err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
argc - 1, argv + 1, local, which, 0, 0,
where, 1, repository);
if (repository != NULL)
free (repository);
if (where != NULL)
free (where);
return err;
}
static int
acl_fileproc (void *callerdat, struct file_info *finfo)
{
char *filefullname;
char *founduserpart = NULL;
char *otheruserparts = NULL;
size_t otherslen = 0;
const char *frepository;
int foundline = 0;
char *line = NULL;
size_t line_allocated = 0;
int linelen;
char *wperms;
char *errmsg;
int pos;
if (!aclfile)
return 0;
frepository = Short_Repository (finfo->repository);
filefullname = Xasprintf("%s/%s", frepository, finfo->file);
if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos,
0))
error (1, 0, "You do not have acl admin rights on '%s'", frepository);
if (line != NULL)
{
char *part_type = NULL;
char *part_object = NULL;
char *part_tag = NULL;
char *part_perms = NULL;
char *userpart;
part_type = strtok (line, ":\t");
part_object = strtok (NULL, ":\t");
part_tag = strtok (NULL, ":\t");
part_perms = strtok (NULL, ":\t");
foundline = 1;
userpart = strtok (part_perms, ",\t");
do
{
if (strncmp (userpart, muser, strlen (muser)) == 0)
founduserpart = xstrdup (userpart);
else
{
if (otheruserparts != NULL)
{
xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
}
else
{
otheruserparts = xstrdup (userpart);
otherslen = strlen (otheruserparts);
}
}
} while ((userpart = strtok (NULL, ",\t")) != NULL);
free (userpart);
}
wperms = make_perms (mperms, founduserpart, &errmsg);
if (wperms == NULL)
{
if (errmsg)
error (0, 0, "`%s' %s", filefullname, errmsg);
}
else
{
cvs_output ("X ", 0);
cvs_output (filefullname, 0);
cvs_output ("\n", 0);
write_perms (muser, wperms, founduserpart, foundline,
otheruserparts, "f", filefullname, tag, pos,
Short_Repository(finfo->repository));
}
free (line);
free (founduserpart);
free (otheruserparts);
free (wperms);
free (filefullname);
return 0;
}
static Dtype
acl_dirproc (void *callerdat, const char *dir, const char *repos,
const char *update_dir, List *entries)
{
const char *drepository;
char *founduserpart = NULL;
char *otheruserparts = NULL;
size_t otherslen = 0;
int foundline = 0;
char *line = NULL;
size_t line_allocated = 0;
int linelen;
int pos;
char *wperms;
char *errmsg;
if (!acldir)
return 0;
if (repos[0] == '\0')
repos = Name_Repository (dir, NULL);
if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
error (1, 0, "You do not have admin rights on '%s'",
Short_Repository (repos));
drepository = Short_Repository (repos);
if (line != NULL)
{
char *part_type = NULL;
char *part_object = NULL;
char *part_tag = NULL;
char *part_perms = NULL;
char *userpart;
part_type = strtok (line, ":\t");
part_object = strtok (NULL, ":\t");
part_tag = strtok (NULL, ":\t");
part_perms = strtok (NULL, ":\t");
foundline = 1;
userpart = strtok (part_perms, ",\t");
do
{
if (strncmp (userpart, muser, strlen (muser)) == 0)
founduserpart = xstrdup (userpart);
else
{
if (otheruserparts != NULL)
{
xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
}
else
{
otheruserparts = xstrdup (userpart);
otherslen = strlen (otheruserparts);
}
}
} while ((userpart = strtok (NULL, ",\t")) != NULL);
}
wperms = make_perms (mperms, founduserpart, &errmsg);
if (wperms == NULL)
{
if (errmsg)
error (0, 0, "`%s' %s", drepository, errmsg);
}
else
{
if (defaultperms)
{
cvs_output ("X ", 0);
cvs_output ("ALL", 0);
cvs_output ("\n", 0);
write_perms (muser, wperms, founduserpart, foundline,
otheruserparts, "d", "ALL", tag, pos, drepository);
}
else
{
cvs_output ("X ", 0);
cvs_output (drepository, 0);
cvs_output ("\n", 0);
write_perms (muser, wperms, founduserpart, foundline,
otheruserparts, "d", drepository, tag, pos,
drepository);
}
}
free (line);
free (founduserpart);
free (otheruserparts);
free (wperms);
return 0;
}
/* Open CVSROOT/access or defined CVSACLFileLocation file
* Open access file In each directory if UseSeparateACLFileForEachDir=yes
* returns file pointer to access file or NULL if access file not found */
FILE *
open_accessfile (char *fmode, const char *adir, char **fname)
{
char *accessfile = NULL;
FILE *accessfp;
if (!use_separate_acl_file_for_each_dir)
{
if (cvs_acl_file_location == NULL)
{
accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_ACCESS);
}
else
{
accessfile = xstrdup(cvs_acl_file_location);
}
}
else
{
size_t accessfilelen = 0;
xrealloc_and_strcat (&accessfile, &accessfilelen,
current_parsed_root->directory);
xrealloc_and_strcat (&accessfile, &accessfilelen, "/");
xrealloc_and_strcat (&accessfile, &accessfilelen, adir);
xrealloc_and_strcat (&accessfile, &accessfilelen, "/access");
}
accessfp = CVS_FOPEN (accessfile, fmode);
if (fname != NULL)
*fname = xstrdup (accessfile);
free (accessfile);
return accessfp;
}
/* Open /etc/group file if UseSystemGroups=yes in config file
* Open CVSROOT/group file if UseCVSGroups=yes in config file
* Open group file if specified in CVSGroupsFileLocation
* returns group file pointer if UseSystemGroups=yes
* returns NULL if UseSystemGroups=no or group file not found */
FILE *
open_groupfile (char *fmode)
{
char *groupfile;
FILE *groupfp;
if (use_cvs_groups)
{
if (cvs_groups_file_location != NULL)
{
groupfile = xstrdup (cvs_groups_file_location);
}
else
{
groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_GROUP);
}
}
else
{
return NULL;
}
groupfp = CVS_FOPEN (groupfile, "r");
if (groupfp == NULL)
error (0, 0, "cannot open file: %s", groupfile);
free (groupfile);
return groupfp;
}
/* Check whether given permissions are valid or not
* Returns 1 if permissions are valid
* Returns 0 if permissions are NOT valid */
int
given_perms_valid (const char *cperms)
{
int cperms_len;
int retval;
int index, i;
if (cperms[0] == '+' || cperms[0] == '-')
index = 1;
else
index = 0;
cperms_len = strlen (cperms);
switch (cperms[index])
{
case 'x':
if ((cperms_len - index) == 1 && cperms_len == 1)
retval = 1;
else
retval = 0;
break;
case 'n':
if ((cperms_len - index) == 1 && cperms_len == 1)
retval = 1;
else
retval = 0;
break;
case 'p':
if ((cperms_len - index) == 1)
retval = 1;
else
retval = 0;
break;
case 'a':
if ((cperms_len - index) == 1)
retval = 1;
else
retval = 0;
break;
case 'r':
if ((cperms_len - index) == 1)
retval = 1;
else
retval = 0;
break;
case 'w':
if ((cperms_len - index) == 1)
retval = 1;
else
for (i = index + 1; i < cperms_len; i++)
if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
retval = 1;
else
retval = 0;
break;
case 't':
if ((cperms_len - index) == 1)
retval = 1;
else
for (i = index + 1; i < cperms_len; i++)
if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
retval = 1;
else
retval = 0;
break;
case 'c':
if ((cperms_len - index) == 1)
retval = 1;
else
for (i = index + 1; i < cperms_len; i++)
if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
retval = 1;
else
retval = 0;
break;
case 'd':
if ((cperms_len - index) == 1)
retval = 1;
else
for (i = index + 1; i < cperms_len; i++)
if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
retval = 1;
else
retval = 0;
break;
default:
retval = 0;
break;
}
return retval;
}
/* prepare permsissions string to be written to access file
* returns permissions or NULL if */
char *
make_perms (char *perms, char *founduserpart, char **xerrmsg)
{
char *fperms = NULL;
size_t perms_len;
size_t fperms_len;
int i, j;
int err = 0;
char *errmsg = NULL;
char *retperms;
size_t retperms_len;
perms_len = strlen (perms);
if (perms[0] == '+' || perms[0] == '-')
{
retperms = xmalloc (retperms_len);
retperms[0] = '\0';
retperms_len = 1;
if (founduserpart)
{
char *tempfperms;
size_t tempfperms_len;
char *temp;
int per = 0;
temp = strtok (founduserpart, "!\t");
fperms = strtok (NULL, "!\t");
fperms_len = strlen (fperms);
if (strncmp (fperms, "x", 1) == 0)
{
err = 1;
if (perms[0] == '+')
*xerrmsg = xstrdup ("cannot add default permission 'x'");
else
*xerrmsg = xstrdup ("cannot remove default permission 'x'");
}
/* go through perms */
for (i = 1; i < perms_len && !err; i++)
{
switch (perms[i])
{
case 'n':
err = 1;
break;
case 'p':
if (perms[0] == '+')
fperms = xstrdup ("p");
else if (perms[0] == '-')
{
fperms_len = 1;
fperms = xmalloc (fperms_len);
fperms[0] = '\0';
}
break;
case 'a':
for (j = 0; j < fperms_len; j++)
{
if (fperms[j] == 'p')
{
err = 1;
*xerrmsg = xstrdup ("user have admin rights,"
" cannot use +/- permissions");
}
else if (fperms[j] == 'a' && perms[0] == '+')
{
err = 1;
*xerrmsg = xstrdup ("user already has all ('a')"
" permission");
}
else if (fperms[j] != 'a' && perms[0] == '-')
{
err = 1;
*xerrmsg = xstrdup ("user does not have all "
"('a') permission");
}
}
if (perms[0] == '+')
{
fperms = xstrdup ("a");
fperms_len = strlen (fperms);
}
else if (perms[0] == '-')
{
fperms_len = 1;
fperms = xmalloc (fperms_len);
fperms[0] = '\0';
}
break;
case 'r':
for (i = 0; i < fperms_len; i++)
{
if (fperms[i] == 'n' && perms[0] == '+')
{
fperms = xstrdup ("r");
fperms_len = strlen (fperms);
}
else if (fperms[i] == 'r' && perms[0] == '-')
{
fperms_len = 1;
fperms = xmalloc (fperms_len);
fperms[0] = '\0';
}
else if (perms[0] == '-')
{
err = 1;
*xerrmsg = xstrdup ("user has other permissions,"
" cannot remove read ('r')"
" permission");
}
else
{
err = 1;
*xerrmsg = xstrdup ("user has other permissions,"
" cannot remove read ('r')"
" permission");
}
}
break;
case 'w':
{
tempfperms_len = 1;
tempfperms = xmalloc (tempfperms_len);
tempfperms[0] = '\0';
for (j = 0; j < fperms_len; j++)
{
if (fperms[j] == 't' || fperms[j] == 'c' ||
fperms[j] == 'd')
{
char *temp;
temp = xmalloc (2);
temp[0] = fperms[j];
temp[1] = '\0';
xrealloc_and_strcat (&tempfperms,
&tempfperms_len, temp);
free (temp);
}
else if (fperms[j] == 'a' || fperms[j] == 'p')
{
err = 1;
*xerrmsg = xstrdup ("user has higher"
" permissions, cannot use"
" +/- write permissions");
}
else if (fperms[j] == 'n' || fperms[j] == 'r')
{
if (perms[0] == '-')
{
err = 1;
*xerrmsg = xstrdup ("user does not have"
" write ('w')"
" permission");
}
}
else if (fperms[j] == 'w')
{
per = 1;
if (perms[0] == '+') {
err = 1;
*xerrmsg = xstrdup ("user already have"
" write ('w')"
"permission");
}
}
}
fperms = tempfperms;
fperms_len = strlen (fperms);
if (!per && !err && (perms[0] == '-')) {
err = 1;
*xerrmsg = xstrdup ("user does not have write"
" ('w') permission");
}
if (perms[0] == '+')
{
xrealloc_and_strcat (&fperms, &fperms_len, "w");
}
}
break;
case 't':
{
tempfperms_len = 1;
tempfperms = xmalloc (tempfperms_len);
tempfperms[0] = '\0';
for (j = 0; j < fperms_len; j++)
{
if (fperms[j] == 'w' || fperms[j] == 'c' ||
fperms[j] == 'd')
{
char *temp;
temp = xmalloc (2);
temp[0] = fperms[j];
temp[1] = '\0';
xrealloc_and_strcat (&tempfperms,
&tempfperms_len, temp);
free (temp);
}
else if (fperms[j] == 'a' || fperms[j] == 'p')
{
err = 1;
*xerrmsg = xstrdup ("user has higher"
" permissions, cannot use"
" +/- tag permissions");
}
else if (fperms[j] == 'n' || fperms[i] == 'r')
{
if (perms[0] == '-')
*xerrmsg = xstrdup ("user does not have tag"
" ('t') permission");
}
else if (fperms[j] == 't')
{
per = 1;
if (perms[0] == '+')
{
err = 1;
*xerrmsg = xstrdup ("user already have tag"
" ('t') permission");
}
}
}
fperms = tempfperms;
fperms_len = strlen (fperms);
if (!per && !err && (perms[0] == '-'))
{
err = 1;
*xerrmsg = xstrdup ("user does not have tag ('t')"
" permission");
}
if (perms[0] == '+')
{
xrealloc_and_strcat (&fperms, &fperms_len, "t");
}
}
break;
case 'c':
{
tempfperms_len = 1;
tempfperms = xmalloc (tempfperms_len);
tempfperms[0] = '\0';
for (j = 0; j < fperms_len; j++)
{
if (fperms[j] == 'w' || fperms[j] == 't' ||
fperms[j] == 'd')
{
char *temp;
temp = xmalloc (2);
temp[0] = fperms[j];
temp[1] = '\0';
xrealloc_and_strcat (&tempfperms,
&tempfperms_len, temp);
free (temp);
}
else if (fperms[j] == 'a' || fperms[j] == 'p')
{
err = 1;
*xerrmsg = xstrdup ("user has higher"
" permissions, cannot use"
" +/- create permissions");
}
else if (fperms[j] == 'n' || fperms[i] == 'r')
{
if (perms[0] == '-')
err = 1;
*xerrmsg = xstrdup ("user does not have create"
" ('c') permission");
}
else if (fperms[j] == 'c')
{
per = 1;
if (perms[0] == '+') {
err = 1;
*xerrmsg = xstrdup ("user already have"
" create ('c')"
" permission");
}
}
}
fperms = tempfperms;
fperms_len = strlen (fperms);
if (!per && !err && (perms[0] == '-')) {
err = 1;
*xerrmsg = xstrdup ("user does not have create"
" ('c') permission");
}
if (perms[0] == '+')
{
xrealloc_and_strcat (&fperms, &fperms_len, "c");
}
}
break;
case 'd':
{
tempfperms_len = 1;
tempfperms = xmalloc (tempfperms_len);
tempfperms[0] = '\0';
for (j = 0; j < fperms_len; j++)
{
if (fperms[j] == 'w' || fperms[j] == 'c' ||
fperms[j] == 't')
{
char *temp;
temp = xmalloc (2);
temp[0] = fperms[j];
temp[1] = '\0';
xrealloc_and_strcat (&tempfperms,
&tempfperms_len, temp);
free (temp);
}
else if (fperms[j] == 'a' || fperms[j] == 'p')
{
err = 1;
*xerrmsg = xstrdup ("user has higher"
" permissions, cannot use"
" +/- delete permissions");
}
else if (fperms[j] == 'n' || fperms[i] == 'r')
{
if (perms[0] == '-')
err = 1;
*xerrmsg = xstrdup ("user does not have delete"
" ('d') permission");
}
else if (fperms[j] == 'd')
{
per = 1;
if (perms[0] == '+') {
err = 1;
*xerrmsg = xstrdup ("user already have"
" delete ('d')"
" permission");
}
}
}
fperms = tempfperms;
fperms_len = strlen (fperms);
if (!per && !err && (perms[0] == '-')) {
err = 1;
*xerrmsg = xstrdup ("user does not have delete"
" ('d') permission");
}
if (perms[0] == '+')
{
xrealloc_and_strcat (&fperms, &fperms_len, "d");
}
}
break;
default:
err = 1;
*xerrmsg = xstrdup ("error in 'access' file format");
break;
}
if (fperms[0] == '\0')
retperms = xstrdup ("none");
else
retperms = xstrdup (fperms);
}
}
else
{
err = 1;
*xerrmsg = xstrdup("user is not given any permissions to remove/add");
}
}
else
{
retperms = xstrdup (perms);
}
if (fperms)
free (fperms);
if (err && retperms)
free (retperms);
return (err ? NULL : retperms);
}
/* prepare and write resulting permissions to access file */
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)
{
char *accessfile;
char *tmpaccessout;
FILE *accessfpin;
FILE *accessfpout;
char *newline = NULL;
size_t newlinelen = 1;
char *object;
char *line = NULL;
size_t line_allocated = 0;
newline = xmalloc (newlinelen);
newline[0] = '\0';
if (!strcasecmp (part_tag, "ALL"))
part_tag = "ALL";
/* strip any trailing slash if found */
object = xstrdup (part_object);
if (object[strlen (object) - 1] == '/')
object[strlen (object) - 1] = '\0';
/* first parts, part type, object, and tag */
xrealloc_and_strcat (&newline, &newlinelen, part_type);
xrealloc_and_strcat (&newline, &newlinelen, ":");
xrealloc_and_strcat (&newline, &newlinelen, object);
xrealloc_and_strcat (&newline, &newlinelen, ":");
xrealloc_and_strcat (&newline, &newlinelen, part_tag);
xrealloc_and_strcat (&newline, &newlinelen, ":");
if (strncmp (perms, "none", 4) != 0)
{
xrealloc_and_strcat (&newline, &newlinelen, user);
xrealloc_and_strcat (&newline, &newlinelen, "!");
xrealloc_and_strcat (&newline, &newlinelen, perms);
if (otheruserparts != NULL)
xrealloc_and_strcat (&newline, &newlinelen, ",");
}
if (otheruserparts != NULL)
{
if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
otheruserparts[strlen (otheruserparts) - 1] = '\0';
xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
}
xrealloc_and_strcat (&newline, &newlinelen, ":");
if (foundline)
{
accessfpout = cvs_temp_file (&tmpaccessout);
if (accessfpout == NULL)
error (1, errno, "cannot open temporary file: %s", tmpaccessout);
accessfpin = open_accessfile ("r", arepos, &accessfile);
if (accessfpout == NULL)
error (1, errno, "cannot open access file: %s", accessfile);
while (getline (&line, &line_allocated, accessfpin) >= 0)
{
if (pos != ftell (accessfpin))
{
if (fprintf (accessfpout, "%s", line) < 0)
error (1, errno, "writing temporary file: %s", tmpaccessout);
}
else
{
if (fprintf (accessfpout, "%s\n", newline) < 0)
error (1, errno, "writing temporary file: %s", tmpaccessout);
}
}
if (fclose (accessfpin) == EOF)
error (1, errno, "cannot close access file: %s", accessfile);
if (fclose (accessfpout) == EOF)
error (1, errno, "cannot close temporary file: %s", tmpaccessout);
if (CVS_UNLINK (accessfile) < 0)
error (0, errno, "cannot remove %s", accessfile);
copy_file (tmpaccessout, accessfile);
if (CVS_UNLINK (tmpaccessout) < 0)
error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
}
else
{
accessfpout = open_accessfile ("r+", arepos, &accessfile);
if (accessfpout == NULL)
{
if (existence_error (errno))
{
accessfpout = open_accessfile ("w+", arepos, &accessfile);
}
if (accessfpout == NULL)
error (1, errno, "cannot open access file: %s", accessfile);
}
else {
if (fseek (accessfpout, 0, 2) != 0)
error (1, errno, "cannot fseek access file: %s", accessfile);
}
if (fprintf (accessfpout, "%s\n", newline) < 0)
error (1, errno, "writing access file: %s", accessfile);
if (fclose (accessfpout) == EOF)
error (1, errno, "cannot close access file: %s", accessfile);
}
free (line);
free (newline);
chmod (accessfile, 0644);
return 0;
}
static int
acllist_fileproc (void *callerdat, struct file_info *finfo)
{
char *filefullname;
const char *frepository;
char *line = NULL;
int pos;
if (!aclfile)
return 0;
frepository = Short_Repository (finfo->repository);
filefullname = Xasprintf("%s/%s", frepository, finfo->file);
/* check that user, which run acl/racl command, has admin permisson,
* and also return the line with permissions from access file. */
if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos,
0))
error (1, 0, "You do not have admin rights on '%s'", frepository);
acllist_print (line, filefullname);
free (filefullname);
return 0;
}
static Dtype
acllist_dirproc (void *callerdat, const char *dir, const char *repos,
const char *update_dir, List *entries)
{
char *line = NULL;
const char *drepository;
int pos;
if (repos[0] == '\0')
repos = Name_Repository (dir, NULL);
if (!acldir)
return 0;
drepository = Short_Repository (repos);
/* check that user, which run acl/racl command, has admin permisson,
* and also return the line with permissions from access file. */
if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
error (1, 0, "You do not have admin rights on '%s'", drepository);
acllist_print (line, drepository);
return 0;
}
/* Prints permissions to screen with -l option */
void
acllist_print (char *line, const char *obj)
{
char *temp;
int c = 0;
int def = 0;
char *printedusers[255];
printedusers[0] = NULL;
if (line != NULL)
{
temp = strtok (line, ":\t");
if (acldir)
cvs_output ("d ", 0);
else if (aclfile)
cvs_output ("f ", 0);
temp = strtok (NULL, ":\t");
cvs_output(obj, 0);
cvs_output (" | ", 0);
temp = strtok (NULL, ":\t");
cvs_output (temp, 0);
cvs_output (" | ", 0);
while ((temp = strtok (NULL, "!\t")) != NULL)
{
if (strncmp (temp, ":", 1) == 0)
break;
if (strcmp (temp, "ALL") == 0)
{
temp = strtok (NULL, ",\t");
continue;
}
cvs_output (temp, 0);
cvs_output (":", 0);
while (printedusers[c] != NULL)
c++;
printedusers[c] = xstrdup (temp);
c++;
printedusers[c] = NULL;
temp = strtok (NULL, ",\t");
if (temp != NULL && temp[strlen (temp) - 2] == ':')
temp[strlen (temp) - 2] = '\0';
cvs_output (temp, 0);
cvs_output (" ", 0);
}
if (default_perms_object)
{
cvs_output ("| defaults ", 0);
cvs_output ("ALL:", 0);
cvs_output (default_perms_object, 0);
def = 1;
}
if (default_part_perms_accessfile)
{
size_t i;
i = strlen (default_part_perms_accessfile);
xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
free (line);
line = xstrdup (default_part_perms_accessfile);
if (!def)
cvs_output ("| defaults ", 0);
else
cvs_output (" ", 0);
temp = strtok (line, "!\t");
cvs_output (temp, 0);
cvs_output (":", 0);
temp = strtok (NULL, ",\t");
cvs_output (temp, 0);
cvs_output (" ", 0);
while ((temp = strtok (NULL, "!\t")) != NULL)
{
int printed = 0;
int c2 = 0;
while (printedusers[c2] != NULL && printed == 0)
{
if (strcmp (printedusers[c2], temp) == 0)
{
printed = 1;
break;
}
c2++;
}
if (printed == 0)
{
cvs_output (temp, 0);
cvs_output (":", 0);
}
temp = strtok (NULL, ",\t");
if (temp[strlen (temp) - 2] == ':')
temp[strlen (temp) - 2] = '\0';
if (printed == 0)
{
cvs_output (temp, 0);
cvs_output (" ", 0);
}
}
def = 1;
}
else if (cvs_acl_default_permissions)
{
cvs_output ("| defaults ", 0);
cvs_output ("ALL: ", 0);
cvs_output (cvs_acl_default_permissions, 0);
}
}
else
{
if (acldir)
cvs_output ("d ", 0);
else if (aclfile)
cvs_output ("f ", 0);
cvs_output (obj, 0);
cvs_output (" | ", 0);
cvs_output (tag, 0);
cvs_output (" | ", 0);
if (default_perms_object)
{
cvs_output ("| defaults ", 0);
cvs_output ("ALL:", 0);
cvs_output (default_perms_object, 0);
def = 1;
}
if (default_part_perms_accessfile)
{
free (line);
line = xstrdup (default_part_perms_accessfile);
if (!def)
cvs_output ("| defaults ", 0);
else
cvs_output (" ", 0);
temp = strtok (line, "!\t");
cvs_output (temp, 0);
cvs_output (":", 0);
temp = strtok (NULL, ",\t");
if (temp[strlen (temp) - 2] == ':')
temp[strlen (temp) - 2] = '\0';
cvs_output (temp, 0);
cvs_output (" ", 0);
while ((temp = strtok (NULL, "!\t")) != NULL)
{
cvs_output (temp, 0);
cvs_output (":", 0);
if ((temp = strtok (NULL, ",\t")) != NULL)
{
if (temp[strlen (temp) - 2] == ':')
temp[strlen (temp) - 2] = '\0';
cvs_output (temp, 0);
cvs_output (" ", 0);
}
}
cvs_output ("\n", 0);
}
else if (cvs_acl_default_permissions)
{
cvs_output ("| defaults ", 0);
cvs_output ("ALL: ", 0);
cvs_output (cvs_acl_default_permissions, 0);
}
else
cvs_output ("default:p (no perms)", 0);
}
cvs_output ("\n", 0);
while (c >= 0) {
free (printedusers[c]);
c--;
}
free (line);
}
/* find username
* returns username with its permissions if user found
* returns NULL if user not found */
char *findusername (const char *string1, const char *string2)
{
char *tmp1, *tmp2;
if (string1 != NULL && string2 != NULL)
{
tmp1 = xstrdup (string1);
tmp2 = strtok (tmp1, ",\t");
do
{
if (strncmp (tmp2, string2, strlen (string2)) == 0 &&
tmp2[strlen (string2)] == '!')
{
tmp2 = xstrdup (tmp2);
free (tmp1);
return tmp2;
}
tmp2 = strtok (NULL, ",\t");
}
while (tmp2 != NULL);
free (tmp1);
return NULL;
}
else
return NULL;
}
/* find user name in group file
* returns group name if user found
* returns NULL if user not found */
char *findgroupname (const char *string1, const char *string2)
{
char *tmp1, *tmp2;
char *grpname;
if (string1 != NULL && string2 != NULL)
{
tmp1 = xstrdup (string1);
grpname = strtok (tmp1, ":\t");
while (tmp2 = strtok(NULL, ",\t"))
{
if (strcmp (tmp2, string2) == 0)
{
grpname = xstrdup (grpname);
free (tmp1);
return grpname;
}
}
free (tmp1);
return NULL;
}
else
return NULL;
}