#include "unixpriv.h" /**************************************************** C-GUL ****************************************************/ char * cgul_process_identity_oneline(void) { int t = 0; int stored_errno = 0; char * line_buf = NULL; struct passwd * p = NULL; struct group * g = NULL; int ngroups = 0; gid_t * list = NULL; uid_t uid = getuid(); uid_t euid = geteuid(); gid_t gid = getgid(); gid_t egid = getegid(); /* Allocate write buffer, must be free'd */ if (!(line_buf = calloc (sizeof (char), 1024 + 1))) return NULL; /* Real User ID */ if((p = getpwuid (uid))){ snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), "uid=%d(%s)", uid, p -> pw_name); } else { snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), "uid=%d", uid); } /* Effective User ID */ if((p = getpwuid (euid))){ snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",euid=%d(%s)", euid, p -> pw_name); } else { snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",euid=%d", euid); } /* Real Group ID */ if((g = getgrgid (gid))){ snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",gid=%d(%s)", gid, g -> gr_name); } else { snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",gid=%d", gid); } /* Effective Group ID */ if((g = getgrgid (egid))){ snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",egid=%d(%s)", egid, g -> gr_name); } else { snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",egid=%d", egid); } /* Get the number of secondary group IDs for root */ if ((ngroups = getgroups(0, NULL)) < 0) { stored_errno = errno; free (line_buf); errno = stored_errno; return NULL; } list = (gid_t *) malloc(ngroups * sizeof(gid_t)); /* Get the secondary group IDs for root */ if (getgroups(ngroups, list) < 0) { stored_errno = errno; free (line_buf); errno = stored_errno; return NULL; } /* Make a oneliner out of all the secondary GIDs */ for (t = 0; t < ngroups; t++) { /* Secondary Group ID */ if((g = getgrgid (list[t]))){ snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",sgid=%d(%s)", list[t], g -> gr_name); } else { snprintf (&line_buf[strlen(line_buf)], 1024 - strlen(line_buf), ",sgid=%d", list[t]); } } /* Memory liberation */ if (list) free(list); list=(gid_t *) NULL; return line_buf; } uid_t threadsafe_getuid_from_name (const char * username) { struct passwd * p = NULL; uid_t uid = -1; int errno_save = 0; #define HAVE_GETPWNAM_R #if defined HAVE_GETPWNAM_R || defined _LIBC char * pwtmpbuf = NULL; struct passwd pwbuf; size_t buflen = 1024; #ifdef _SC_GETPW_R_SIZE_MAX buflen = sysconf (_SC_GETPW_R_SIZE_MAX); if ((buflen == -1) && (errno != 0)) { buflen = 1024; } #endif /* Allocate the buffer for getpwnam_r() */ pwtmpbuf = (char *) calloc (1, buflen); /* Get Passwd Info for Username */ while (getpwnam_r (username, &pwbuf, pwtmpbuf, buflen, &p) != 0) { /* If the errno is anything different then ERANGE, something is wrong or the ID is not available */ if (errno != ERANGE) { errno_save = errno; p = NULL; break; } /* ERANGE is left over, which means that there is insufficient buffer space. Increasing buffer side and try again */ buflen *= 2; free (pwtmpbuf); /* Allocate the buffer for getpwnam_r() */ if (!(pwtmpbuf = (char *) calloc (1, buflen))) { /* System ran out of memory */ if (errno == ENOMEM) { /* No memory available, bail out */ p = NULL; errno_save = errno; break; } } } #else p = getpwnam (username); #endif /* If there is an entry found, fetch the UID info */ if (p) { uid = p -> pw_uid; } /* Remove the buffer for the getpwnam_r() */ free (pwtmpbuf); errno = errno_save; return uid; } gid_t threadsafe_getgid_from_name (const char * groupname) { struct group * p = NULL; gid_t gid = -1; int errno_save = 0; #define HAVE_GETPWNAM_R #if defined HAVE_GETPWNAM_R || defined _LIBC char * grtmpbuf = NULL; struct group grbuf; size_t buflen = 1024; #ifdef _SC_GETGR_R_SIZE_MAX buflen = sysconf (_SC_GETGR_R_SIZE_MAX); if ((buflen == -1) && (errno != 0)) { buflen = 1024; } #endif /* Allocate the buffer for getpwnam_r() */ grtmpbuf = (char *) calloc (1, buflen); /* Get Passwd Info for Username */ while (getgrnam_r (groupname, &grbuf, grtmpbuf, buflen, &p) != 0) { /* If the errno is anything different then ERANGE, something is wrong or the ID is not available */ if (errno != ERANGE) { errno_save = errno; p = NULL; break; } /* ERANGE is left over, which means that there is insufficient buffer space. Increasing buffer side and try again */ buflen *= 2; free (grtmpbuf); /* Allocate the buffer for getpwnam_r() */ if (!(grtmpbuf = (char *) calloc (1, buflen))) { /* System ran out of memory */ if (errno == ENOMEM) { /* No memory available, bail out */ p = NULL; errno_save = errno; break; } } } #else /* If the platform doesn't have a getgrnam_r() function */ p = getgrnam (username); #endif /* If there is an entry found, fetch the GID info */ if (p) { gid = p -> gr_gid; } /* Remove the buffer for the getgrnam_r() */ free (grtmpbuf); errno = errno_save; return gid; } /* When the proxy is located on an NFS mount and on the server side the root squash * option has been enabled, the effective uid is mapped to user 'nobody' which should * not be able to read the proxy file. To work around this problem, the effective * uid of the process is changed to that of the calling user and once glexec is done, * the saved uid is used to restore the identity of the process, */ #if 0 Example: uid_t stored_real_uid = -1; uid_t stored_eff_uid = -1; /* Downgrade effective privileges to cope with NFS mounted file systems with root squashing */ downgradeEffectiveToRealUid (&stored_real_uid, &stored_eff_uid); /* Read PEM string */ fopen(proxyfile, "r"); /* Restore privileges to previous state */ upgradeEffectiveToRealUid (stored_real_uid, stored_eff_uid); #endif int downgradeEffectiveToRealUid (uid_t * real_uid, uid_t * saved_uid) { *real_uid = getuid(); if (*real_uid != 0) { /* Save it */ *saved_uid = geteuid(); if (seteuid(*real_uid)) { fprintf (stderr, "Error on downsizing with seteuid()\n"); return 1; } } return 0; } int upgradeEffectiveToRealUid (uid_t real_uid, uid_t saved_uid) { /* Do not forget to put back the original effective uid on the process. */ if (real_uid != 0) { if (seteuid(saved_uid)) { fprintf (stderr, "Error on returning seteuid()\n"); return 1; } } return 0; } /****************************************************************************** Function: get_gidlist() Description: Finds the list of gids for user in the group file (/etc/group) Returns a list of gid_t which should be freed by calling program. Parameters: username: the name of the user ngroups: ptr to int which will be filled with the number of gids. group_list: ptr to an array of gid_t. Returns: 0 on success. -1 on realloc failure -2 on getgrent failure 1 on failure ******************************************************************************/ int get_gidlist( const char * username, int * ngroups, gid_t ** group_list ) { struct group * group_info = NULL; gid_t * groups = NULL; gid_t * newgroups = NULL; int i = 0; /* rewind the file pointer to the beginning of the /etc/group file */ setgrent(); lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): looping through group file\n"); *ngroups = 0; while ( ( group_info = getgrent() ) ) { char ** pgr_mem = group_info->gr_mem; char * gr_mem = NULL; lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): group %s\n", group_info->gr_name); while ( (gr_mem = *pgr_mem) ) { lcmaps_log_debug(4, "\tlcmaps_get_gidlist(): \tgroup member %s\n", gr_mem); if (strncmp(username, gr_mem, strlen(username))==0) { lcmaps_log_debug(2, "\tlcmaps_get_gidlist(): \t\tfound group %s for %s\n", group_info->gr_name, username); (*ngroups)++; newgroups = (gid_t *) realloc(groups, ((*ngroups) * sizeof(gid_t))); if (newgroups == NULL) { lcmaps_log(1, "lcmaps_get_gidlist(): cannot realloc\n"); free(groups); return -1; } groups=newgroups; groups[(*ngroups)-1] = group_info->gr_gid; } ++pgr_mem; } } if (errno==ENOMEM) { lcmaps_log(1, "lcmaps_get_gidlist(): Cannot read the group file, %s\n", strerror(errno)); free(groups); groups=NULL; /* Close the group file */ endgrent(); return -2; } *group_list=groups; lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): %d groups found for %s\n", *ngroups, username); for (i = 0; i < *ngroups; i++) { lcmaps_log_debug(4,"\tlcmaps_get_gidlist(): group nr %d ==> gid_t %d\n", i+1, groups[i]); } /* Close the group file */ endgrent(); return 0; }