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 /* for printf() */ #include /* for auditing */ #include /* for NGROUPS_MAX */ #include /* for privilege */ #include /* for setlocale() */ #include /* for PW_NAMELEN */ #include #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 - 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); }