Files
Arquivotheca.AIX-4.1.3/bos/usr/bin/setgroups/setgroups.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

898 lines
19 KiB
C

static char sccsid[] = "@(#)66 1.18.1.2 src/bos/usr/bin/setgroups/setgroups.c, cmdsuser, bos411, 9428A410j 12/9/93 19:28:34";
/*
* COMPONENT_NAME: CMDSUSER
*
* FUNCTIONS: addgrps
* addtougroups
* backtologin
* delgrps
* drophead
* getpgroups
* getsets
* getugroups
* isvalidgroup
* main
* printgrps
* resetgroups
* resetgrps
* resetreal
* setpgroups
*
* ORIGINS: 27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1989,1993
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include <stdio.h> /* for printf() */
#include <sys/audit.h> /* for auditing */
#include <limits.h> /* for NGROUPS_MAX */
#include <sys/priv.h> /* for privilege */
#include <locale.h> /* for setlocale() */
#include <userpw.h> /* for PW_NAMELEN */
#include <stdlib.h>
#include "tcbauth.h" /* for local flags */
/* local defines */
static void addgrps(int flag,char *groups);
static void delgrps(int flag,char *groups);
static void resetgrps(int flag,char *newgrpset);
static void resetreal(int flag,char *newgrp);
static void printgrps(int flag);
static void getugroups(char **groups);
static void setpgroups(int flag,char *groups);
static char **getpgroups(void);
static void getsets(char **ugroups,char **pgroups);
static void resetgroups(char *newgrpset,char *ugroups,char **finalgrpset);
static void drophead(char *cgroups,char **groups);
static void addtougroups(int,char *,char *,char *,char **);
static void backtologin();
static int isvalidgroup(char *);
/*
*
* NAME: setgroups
*
* FUNCTION: resets the groupset of the session
*
* USAGE: setgroups [-] [-a | -d | -r] [groupset]
* where:
* - specifies that the environment is to be
* reinitialized
* groupset specifies one or more groups to which the user
* belongs
* -a specifies that the groupset is to be added to
* the concurrent group set
* -d specifies that the groupset is to be deleted
* from the concurrent groupset.
* -r specifies that the real group ID is to be
* changed.
* RETURNS: does not return; if an error, one of the following will result:
*
* EINVAL if an invalid flag is specified
* if -r is specified with >1 group
* if the # of grps in the groupset > NGROUPS_MAX
* ENOENT if the group(s) does not exist
* EACCES if the invoker doesn't have read_access to the user
* database.
* EPERM if the invoker doesn't belong to one of the groups
* which are being added to the groupset.
* errno if system error.
*/
main (int argc, char *argv[])
{
register int c;
register int flag = 0;
(void ) setlocale(LC_ALL,"");
catd = catopen(MF_TCBAUTH, NL_CAT_LOCALE);
/* suspend auditing */
auditproc(0,AUDIT_STATUS,AUDIT_SUSPEND,0);
/* suspend privilege */
privilege(PRIV_LAPSE);
/* check for execution at a terminal */
if (checkfortty())
{
fprintf(stderr,TERMINAL,SETGROUPS);
exitex(SETGRAUD,ENOTTY,NULL,NULL,NOPRINT);
}
/*
* Check for '-' flag. Remember, we could
* have a groupname of 1 character.
*/
if (argv[1] && (!strcmp(argv[1],"-")))
{
/*
* we want to reset the groupset to
* its original login state
*/
flag |= INIT;
if (argv[2] == NULL)
backtologin();
argv++;
}
else if (argv[1])
flag |= DELTA;
/* get the other flag */
while ((c = getopt(argc,argv,"adr")) != EOF)
{
switch (c)
{
case 'a': addgrps(flag,argv[optind]);
case 'd': delgrps(flag,argv[optind]);
case 'r': if (isvalidgroup(argv[optind]))
resetreal(flag,argv[optind]);
else
xusage(SETGRUSAGE,SETGRAUD,NULL);
default : xusage(SETGRUSAGE,SETGRAUD,NULL);
}
}
/*
* These routines never return so
* no need to check return codes.
*/
if(argv[1])
resetgrps(flag,argv[1]);
else
printgrps(flag);
}
/*
*
* FUNCTION: isvalidgroup
*
* DESCRIPTION: checks for valid group name
*
* RETURNS: True or False.
*
*/
int
isvalidgroup(char *name)
{
return( (strlen(name)<PW_NAMELEN) && (!strchr(name,',')) );
}
/*
*
* FUNCTION: addgrps
*
* DESCRIPTION: adds the new groupset to the current process groupset
*
* RETURNS: No return.
*
* PASSED:
* int flag INIT or DELTA
* char *newgroups new groupset for process
*
*/
static void
addgrps(int flag,char *newgroups)
{
char *ugroups; /* current user groupset */
char *pgroups; /* current process groupset */
char *finalgrpset; /* final groupset */
char err[50];
if (!newgroups)
xusage(SETGRUSAGE,SETGRAUD,NULL);
/* get user and process groupset */
getsets(&ugroups,&pgroups);
/* check for valid groups and build final groupset string */
if (flag & INIT)
{
if (listlen(newgroups)+listlen(ugroups)<=NGROUPS_MAX)
addtougroups(flag,ugroups,(char *)NULL,newgroups,
&finalgrpset);
else
{
sprintf(err,"%d",NGROUPS_MAX);
fprintf(stderr,GRPTOLG,err);
exitex(SETGRAUD,0,NULL,NULL,NOPRINT);
}
}
else
{
if (listlen(newgroups)+listlen(pgroups)<=NGROUPS_MAX)
addtougroups(flag,pgroups,ugroups,newgroups,
&finalgrpset);
else
{
sprintf(err,"%d",NGROUPS_MAX);
fprintf(stderr,GRPTOLG,err);
exitex(SETGRAUD,0,NULL,NULL,NOPRINT);
}
}
/* run new process with new groupset */
setpgroups(flag,finalgrpset);
}
/*
* FUNCTION: delgrps
*
* DESCRIPTION: gets current groupset and deletes the newgrpset from it.
* the groups are checked for membership in the current
* groupset.
*
* PASSED: flag = INIT or DELTA, groups = groups to delete.
*
* RETURNS: No return.
*
*/
static void
delgrps(int flag,char *groups)
{
char *ugroups; /* current user groupset */
char *pgroups; /* current process groupset */
char *finalgrpset; /* final groupset */
if (!groups)
xusage(SETGRUSAGE,SETGRAUD,NULL);
/* get user and process groupset */
getsets(&ugroups,&pgroups);
/*
* if INIT, take the group out of the user's groupset
* otherwise, take the user out of the process groupset
* We are not trying to delete our primary group
* so go ahead and call delmems.
*/
if (flag & INIT)
{
if (delmems(HEADER,ugroups,groups,&finalgrpset))
{
fprintf(stderr,GRPNINST,finalgrpset);
exitex(SETGRAUD,ENOENT,finalgrpset,ugroups,NOPRINT);
}
}
else
{
if (delmems(HEADER,pgroups,groups,&finalgrpset))
{
fprintf(stderr,GRPNINST,finalgrpset);
exitex(SETGRAUD,ENOENT,finalgrpset,pgroups,NOPRINT);
}
}
/*
* If this is the last group, reset back all groups
* and print error message.
*/
if (!listlen(finalgrpset + strlen(HEADER)))
{
strcat(finalgrpset,pgroups);
fprintf(stderr,LASTGRP);
}
/* run new process with new groupset */
setpgroups(flag,finalgrpset);
}
/*
*
* FUNCTION: resetreal
*
* DESCRIPTION: changes process' real group to new groupset.
*
* PASSED: flag = INIT or DELTA, newgrp = new real group for process
*
* RETURNS: No return.
*
*/
static void
resetreal(int flag,char *newgrp)
{
char *ugroups; /* current user groupset */
char *pgroups; /* current process groupset */
char *finalgrpset; /* final groupset */
/*
* A NULL newgrp here will be handled by
* the getreal() routine and does not
* need checking here.
*/
/* get user and process groupset */
getsets(&ugroups,&pgroups);
/* check for valid groups and build final groupset string */
if (flag & INIT)
getreal(flag,ugroups,ugroups,newgrp,&finalgrpset);
else
getreal(flag,pgroups,ugroups,newgrp,&finalgrpset);
/* run new process with new groupset */
setpgroups(flag,finalgrpset);
}
/*
*
* FUNCTION: resetgrps
*
* DESCRIPTION: resets the current groupset.
*
* PASSED: flag = INIT or RESET, newgrpset = new process groupset
*
* RETURNS: No return.
*
*/
static void
resetgrps(int flag,char *newgrpset)
{
char *ugroups; /* current user groupset */
char *finalgrpset; /* final groupset */
/* get current user groupset */
getugroups(&ugroups);
/* check for valid groups and build final groupset string */
resetgroups(newgrpset,ugroups,&finalgrpset);
/* run new process with new groupset */
setpgroups(flag,finalgrpset);
}
/*
*
* FUNCTION: printgrps
*
* DESCRIPTION: lists the current user and process groupset.
*
* RETURNS: No return.
*
*/
static void
printgrps(int flag)
{
char *pgroups;
char *ugroups;
char *name; /* user name */
uid_t uid;
/* get real users name */
uid = getuid();
if ((name = (char *)IDtouser(uid)) == NULL)
{
fprintf(stderr,USRINFO);
fprintf (stderr, CHECK, PASSWD);
exitex(SETGRAUD,errno,NULL,NULL,NOPRINT);
}
/* get user and process groupset */
getsets(&ugroups,&pgroups);
printf ("%s:\n",name);
printf(CURUSE,ugroups);
printf(CURPROC,pgroups);
printf("\n");
exitex(SETGRAUD,0,NULL,NULL,NOPRINT);
}
/*
*
* FUNCTION: getsets
*
* DESCRIPTION: returns the user's and the process' groupsets
*
* PASSED: ugroups = place to put user groupset, pgroups = place to put
* process groupset.
*
* RETURNS: user groupset and process groupset
*
*/
static void
getsets(char **ugroups,char **pgroups)
{
char **currgrpset;
/* get current user's groupset */
getugroups(ugroups);
/* get current process' groupset */
currgrpset = getpgroups();
/* drop the GROUPS= */
drophead(*currgrpset,pgroups);
}
/*
* FUNCTION: getugroups
*
* DESCRIPTION: get the user's current groupset.
*
* PASSED: groups = place to put the groupset.
*
* RETURNS: groupset in groups and exits on error.
*/
static void
getugroups(char **groups)
{
char *val; /* return value from getuserattr() */
char *name; /* user name */
uid_t uid;
/* get real users name */
uid = getuid();
if ((name = (char *)IDtouser(uid)) == NULL)
{
fprintf(stderr,USRINFO);
fprintf (stderr, CHECK, PASSWD);
exitex(SETGRAUD,errno,NULL,NULL,NOPRINT);
}
/* get his groupset from /etc/group */
if(getuserattr(name,S_GROUPS,(void *)&val,SEC_LIST))
{
fprintf(stderr,GETUSRGRPS,name);
fprintf (stderr, CHECK , GROUP);
exitex(SETGRAUD,errno,NULL,NULL,NOPRINT);
}
/* turn NULL separated string to comma separated */
*groups = listocom(val);
}
/*
*
* FUNCTION: getpgroups
*
* DESCRIPTION: get current process' groupset.
*
* RETURNS: pointer to current group set.
*
*/
static char **
getpgroups(void)
{
char **groups; /* place to store groupset */
/* reacquire privilege that was dropped earlier */
privilege(PRIV_ACQUIRE);
/* get process' groupset */
if ((groups = getpcred(CRED_GROUPS)) == NULL)
{
fprintf(stderr,GETPCRED);
exitex(SETGRAUD,errno,groups,NULL,NOPRINT);
}
/* lapse privilege again */
privilege(PRIV_LAPSE);
return(groups);
}
/*
*
* FUNCTION: setpgroups
*
* DESCRIPTION: uses setpcred to set the current groupset.
*
* PASSED: flag = INIT or DELTA, groups = new process' groupset.
*
* RETURNS: No return.
*
*/
static void
setpgroups(int flag,char *groups)
{
char *creds[3]; /* new groupset */
char group[PW_NAMELEN]; /* real group name */
char *ptr; /* to increment through groups string */
register int siz; /* space to get */
register int siz1; /* space to get */
/* set up REAL_GROUP string */
drophead(groups,&ptr);
getrealgroup(ptr,group);
siz = strlen(REAL_GROUP) + strlen(group) + 1;
if ((ptr = malloc(siz)) == NULL)
{
fprintf(stderr,MALLOC);
exitex(SETGRAUD,errno,group,groups,NOPRINT);
}
strcpy(ptr,REAL_GROUP);
strcat(ptr,group);
/* set up new group array */
creds[0] = ptr;
creds[1] = groups;
creds[2] = (char *)NULL;
/* reacquire lapsed privilege */
privilege(PRIV_ACQUIRE);
/* audit credential change */
siz = strlen(group) + 1;
siz1 = strlen(groups) + 1;
auditwrite(SETGRAUD,AUDIT_OK,group,siz,groups,siz1,0);
/* set process credentials with new groupset */
if(setpcred((char *)NULL,creds))
{
fprintf(stderr,SETPCRED);
exitex(SETGRAUD,errno,group,groups,PRINT);
}
/* run new shell */
exitex(SETGRAUD,0,NULL,NULL,NOPRINT);
}
/*
*
* FUNCTION: addtougroups
*
* DESCRIPTION: checks whether the newgroups are in user's current groupset,
* whether any are already in the process' current groupset.
*
* RETURNS: None.
*
* PASSED:
* char *ugroups current user or process groupset
* char *agroups current available groupset
* char *newgrpset newgroups to add
* char **finalgrpset place to put final groupset.
*
*/
static void
addtougroups(int flag,char *ugroups,char *agroups,
char *newgrpset,char **finalgrpset)
{
register int i = 0;
register int found = 0;
int c = 0;
int pflag = 0;
int id;
int ag = 0;
int ug,n;
char **ugrps;
char **agrps = (char **)NULL;
char **news;
char group[PW_NAMELEN];
register int siz;
/* get real group for auditing */
getrealgroup(ugroups,group);
/*
* Get some space to hold the new string. Since
* we had comma-separated lists (ugroups and newgrpset),
* the commas are already counted, so we need space
* for only one more comma to separate the strings
* and one NULL.
*/
siz = strlen(HEADER) + strlen(ugroups) + strlen(newgrpset) + 2;
if((*finalgrpset = malloc(siz)) == NULL)
{
fprintf(stderr,MALLOC);
exitex(SETGRAUD,errno,group,newgrpset,NOPRINT);
}
/* turn strings into arrays */
ugrps = comtoarray(ugroups,&ug);
news = comtoarray(newgrpset,&n);
if (agroups)
agrps = comtoarray(agroups,&ag);
/* copy in GROUPS= , real group, and a comma */
strcpy(*finalgrpset,HEADER);
strcat(*finalgrpset,ugrps[0]);
strcat(*finalgrpset,COMMA);
while(news[i])
{
/* Check for groups's length < PW_NAMELEN */
if(strlen(news[i]) > PW_NAMELEN - 1)
{
fprintf(stderr,LONGGROUP,news[i]);
exitex(SETGRAUD,ENAMETOOLONG,news[i],NULL,NOPRINT);
}
/*
* if newgroup is real skip
* it because we've already copied it in
*/
if(!strcmp(news[i],ugrps[0]))
break;
/*
* see if the groups are allowed to be added
* to the user's process groupset by
* checking the user's available groups
*/
if (flag & DELTA)
{
for (c = 0; c < ag; c++)
{
if(!strcmp(news[i],agrps[c]))
{
found = 1;
/*
* copy in the new group and
* add a comma to end
*/
strcat(*finalgrpset, news[i]);
strcat(*finalgrpset,COMMA);
break;
}
}
/* if not in user's groupset --> error */
if(!found)
{
fprintf(stderr,GRPNINST,news[i]);
if (getgroupattr(news[i],S_ID,(void *)&id,
SEC_INT))
exitex(SETGRAUD,ENOENT,group,newgrpset,
NOPRINT);
else
exitex(SETGRAUD,EPERM,group,newgrpset,
NOPRINT);
}
found = 0;
}
/*
* Go through the user's groupset to see
* if the new group is in it.
* If it is remove it from the groups
* to be copied in at the end and
* copy it in to the final groupset.
* If it isn't print error.
*/
for (c = 1; c < ug; c++)
{
if(!strcmp(news[i],ugrps[c]))
{
found = 1;
/*
* copy in the new group and
* delete it from the groups that
* remain in the user group string
*/
if (flag & INIT)
{
strcat(*finalgrpset, news[i]);
strcat(*finalgrpset,COMMA);
}
ugrps[c] = NULL;
break;
}
}
/* if not in user's groupset --> error */
if (flag & INIT)
{
if(!found)
{
if (getgroupattr(news[i],S_ID,(void *)&id,SEC_INT))
{
fprintf(stderr,GRPNINST,news[i]);
exitex(SETGRAUD,ENOENT,group,newgrpset,
NOPRINT);
}
fprintf(stderr,GRPNINST,news[i]);
exitex(SETGRAUD,EPERM,group,newgrpset,NOPRINT);
}
}
found = 0;
i++;
}
/*
* Copy in the groups that are left.
*/
for (c = 1; c < ug; c++)
{
if(ugrps[c])
{
strcat(*finalgrpset, ugrps[c]);
strcat(*finalgrpset,COMMA);
}
}
/*
* This was the last member to be added, so back up
* finalptr and null terminate the list.
*/
*finalgrpset--;
**finalgrpset = '\0';
}
/*
*
* FUNCTION: resetgroups
*
* DESCRIPTION: builds the new groupset.
*
* PASSED: newgrpset = new group set, ugroups = current user groupset,
* finalgrpset = final group set.
*
* RETURNS: None.
*
*/
static void
resetgroups(char *newgrpset,char *ugroups,char **finalgrpset)
{
int i=0, ug = 0, g = 0, c = 0, match = 0,id;
char **grps;
char **ugrps;
char group[PW_NAMELEN];
register int siz;
/* separate out real group for auditing */
getrealgroup(newgrpset,group);
siz = strlen(HEADER) + strlen(newgrpset) + 1;
if((*finalgrpset = malloc(siz)) == NULL)
{
fprintf(stderr,MALLOC);
exitex(SETGRAUD,errno,group,newgrpset,NOPRINT);
}
/* copy in GROUPS= and new groupset */
strcpy(*finalgrpset,HEADER);
strcat(*finalgrpset,newgrpset);
/* turn group strings into arrays */
ugrps = comtoarray(ugroups,&ug);
grps = comtoarray(newgrpset,&g);
while(grps[i])
{
/* Check for groups's length < PW_NAMELEN */
if(strlen(grps[i]) > PW_NAMELEN - 1)
{
fprintf(stderr,LONGGROUP,grps[i]);
exitex(SETGRAUD,ENAMETOOLONG,grps[i],NULL,NOPRINT);
}
/* is newgroup member in the current user groupset */
for (c = 0; c < ug; c++)
{
if(strcmp(ugrps[c],grps[i]) == 0)
{
match=1;
break;
}
}
if (!match)
{
fprintf(stderr,GRPNINST,grps[i]);
if (getgroupattr(grps[i],S_ID,(void *)&id,SEC_INT))
exitex(SETGRAUD,ENOENT,group,newgrpset,
NOPRINT);
else
exitex(SETGRAUD,EPERM,group,newgrpset,NOPRINT);
}
match = 0;
i++;
}
}
/*
*
* FUNCTION: drophead
*
* DESCRIPTION: drops the "GROUPS="
*
* RETURNS: None.
*
*/
static void
drophead(char *cgroups,char **groups)
{
char *value;
char *ptr;
if ((value = strchr(cgroups,'=')) == NULL)
{
fprintf(stderr,GETPCRED);
exitex(SETGRAUD,errno,cgroups,NULL,NOPRINT);
}
/* truncate at first space */
ptr = ++value;
if (ptr && *ptr)
if (ptr = strchr(ptr,' '))
*ptr = '\0';
*groups = value;
}
/*
*
* FUNCTION: backtologin
*
* DESCRIPTION: resets the groupset back to its state at login
*
* RETURNS: No return.
*
*/
static void
backtologin()
{
char **logname;
uid_t uid;
char *name;
char u_name[PW_NAMELEN];
/* reacquire the privilege dropped earlier */
privilege(PRIV_ACQUIRE);
uid = getuid();
if ((name = (char*)IDtouser(uid)) == NULL)
{
fprintf(stderr,USRINFO);
fprintf (stderr, CHECK, PASSWD);
exitex(SETGRAUD,errno,NULL,NULL,NOPRINT);
}
/*
* copy into a safe place because
* the name pointer might be overwritten
*/
if (strlen (name) > PW_NAMELEN - 1)
{
fprintf(stderr,LONGNAME,name);
exitex(SETGRAUD,ENAMETOOLONG,name,NULL,NOPRINT);
}
strcpy (u_name,name);
/* get the login user name from cred */
if ((logname = getpcred(CRED_LUID)) == NULL)
{
fprintf(stderr,GETPCRED);
exitex(SETGRAUD,errno,NULL,NULL,NOPRINT);
}
/* set process credentials: uid,gid,groupset etc. */
if (setpcred (u_name, logname))
{
fprintf(stderr,SETPCRED);
exitex(SETGRAUD,errno,NULL,NULL,PRINT);
}
privilege(PRIV_DROP);
exitex(SETGRAUD,0,NULL,NULL,NOPRINT);
}