void scan_passwd (void) { int i = 1; struct passwd *p; #ifdef _REENTRANT char buf[1024]; struct passwd pbuf; #endif #ifdef _REENTRANT #if GETHOSTBYNAME_R_ARGS == 6 while (getpwent_r (&pbuf, buf, sizeof (buf), &p) == 0 && p != NULL) #else while ((p = getpwent_r (&pbuf, buf, sizeof (buf))) != NULL) #endif #else while ((p = getpwent ()) != NULL) #endif { printf ("%s:%s:%d:%d:%s:%s:%s\n", p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell); i++; } }
int getpwentries(HDF *hdf) { int ret = 0; NEOERR *err = NULL; struct passwd pw, *pwp; char buf[BUFLEN]; setpwent(); while (1) { if (getpwent_r(&pw, buf, BUFLEN, &pwp)) break; err = hdf_set_valuef(hdf, "system.passwd.%s.uid=%d", pwp->pw_name, pwp->pw_uid); err = hdf_set_valuef(hdf, "system.passwd.%s.gid=%d", pwp->pw_name, pwp->pw_gid); err = hdf_set_valuef(hdf, "system.passwd.%s.gecos=%s", pwp->pw_name, pwp->pw_gecos); err = hdf_set_valuef(hdf, "system.passwd.%s.dir=%s", pwp->pw_name, pwp->pw_dir); err = hdf_set_valuef(hdf, "system.passwd.%s.shell=%s", pwp->pw_name, pwp->pw_shell); if (err != STATUS_OK) { nerr_log_error(err); ret -1; } } endpwent(); return ret; }
/* Give preference to /etc/passwd than HOME */ const gchar * g_get_home_dir (void) { if (home_dir == NULL){ pthread_mutex_lock (&home_lock); if (home_dir == NULL){ #ifdef HAVE_GETPWENT_R struct passwd pwbuf, *track; char buf [4096]; uid_t uid; uid = getuid (); setpwent (); while (getpwent_r (&pwbuf, buf, sizeof (buf), &track) == 0){ if (pwbuf.pw_uid == uid){ home_dir = g_strdup (pwbuf.pw_dir); break; } } endpwent (); #endif if (home_dir == NULL) home_dir = g_getenv ("HOME"); pthread_mutex_unlock (&home_lock); } } return home_dir; }
struct passwd * getpwent(void) { nss_XbyY_buf_t *b = get_pwbuf(); return (b == NULL ? NULL : getpwent_r(b->result, b->buffer, b->buflen)); }
struct passwd *getpwent(void) { static char line_buff[PWD_BUFFER_SIZE]; static struct passwd pwd; if (getpwent_r(&pwd, line_buff, sizeof(line_buff), NULL) != -1) { return &pwd; } return NULL; }
int getpwuid_r(uid_t uid, struct passwd *res, char *buf, size_t buflen, struct passwd **res_sig) { while (!getpwent_r(res,buf,buflen,res_sig)) if (uid==res->pw_uid) goto ok; *res_sig=0; ok: endpwent(); return *res_sig?0:-1; }
struct passwd *getpwent(void) { int ret; static char line_buff[PWD_BUFFER_SIZE]; static struct passwd pwd; struct passwd *result; if ((ret=getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) == 0) { return &pwd; } __set_errno(ret); return NULL; }
static void username_tab_completion(char *ud, char *with_shash_flg) { struct passwd *entry; int userlen; ud++; /* ~user/... to user/... */ userlen = strlen(ud); if (with_shash_flg) { /* "~/..." or "~user/..." */ char *sav_ud = ud - 1; char *home = NULL; char *temp; if (*ud == '/') { /* "~/..." */ home = home_pwd_buf; } else { /* "~user/..." */ temp = strchr(ud, '/'); *temp = 0; /* ~user\0 */ entry = getpwnam(ud); *temp = '/'; /* restore ~user/... */ ud = temp; if (entry) home = entry->pw_dir; } if (home) { if ((userlen + strlen(home) + 1) < MAX_LINELEN) { char temp2[MAX_LINELEN]; /* argument size */ /* /home/user/... */ sprintf(temp2, "%s%s", home, ud); strcpy(sav_ud, temp2); } } } else { /* "~[^/]*" */ /* Using _r function to avoid pulling in static buffers */ char line_buff[256]; struct passwd pwd; struct passwd *result; setpwent(); while (!getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) { /* Null usernames should result in all users as possible completions. */ if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) { add_match(xasprintf("~%s/", pwd.pw_name)); } } endpwent(); } }
int main(int argc,char *argv[]) { #ifndef OLD struct passwd pw,*tmp; char buf[1000]; while (getpwent_r(&pw,buf,sizeof(buf),&tmp)==0) { printf("name %s\npassword %s\nuid %u\ngid %u\ngecos %s\ndir %s\nshell %s\n", pw.pw_name,pw.pw_passwd,pw.pw_uid,pw.pw_gid,pw.pw_gecos,pw.pw_dir, pw.pw_shell); } #else struct passwd *pw; while (pw=getpwent()) { printf("name %s\npassword %s\nuid %u\ngid %u\ngecos %s\ndir %s\nshell %s\n", pw->pw_name,pw->pw_passwd,pw->pw_uid,pw->pw_gid,pw->pw_gecos,pw->pw_dir, pw->pw_shell); } #endif return 0; }
struct passwd *getpwent(void) { pw_tls_t *p; struct passwd *ent; int err; PRINT(("%s()\n", __FUNCTION__)); p = get_pw_tls(); if (!p) { /* we are really bork */ __set_errno(ENOMEM); return NULL; } err = getpwent_r(&p->pwent, p->pwbuff, PWBUFFSZ, &ent); if (err < 0) { __set_errno(err); return NULL; } if (!ent) return NULL; PRINT(("getpwent(); returning entry for %s\n", ent->pw_name)); return ent; }
/* * get_group_members - identify the users in a given group name * IN group_name - a single group name * RET a zero terminated list of its UIDs or NULL on error * NOTE: User root has implicitly access to every group * NOTE: The caller must xfree non-NULL return values */ extern uid_t *get_group_members(char *group_name) { char grp_buffer[PW_BUF_SIZE]; struct group grp, *grp_result = NULL; struct passwd *pwd_result = NULL; uid_t *group_uids = NULL, my_uid; gid_t my_gid; int i, j, uid_cnt; #ifdef HAVE_AIX FILE *fp = NULL; #elif defined (__APPLE__) || defined (__CYGWIN__) #else char pw_buffer[PW_BUF_SIZE]; struct passwd pw; #endif group_uids = _get_group_cache(group_name); if (group_uids) { /* We found in cache */ _log_group_members(group_name, group_uids); return group_uids; } /* We need to check for !grp_result, since it appears some * versions of this function do not return an error on failure. */ if (getgrnam_r(group_name, &grp, grp_buffer, PW_BUF_SIZE, &grp_result) || (grp_result == NULL)) { error("Could not find configured group %s", group_name); return NULL; } my_gid = grp_result->gr_gid; j = 0; uid_cnt = 0; #ifdef HAVE_AIX setgrent_r(&fp); while (!getgrent_r(&grp, grp_buffer, PW_BUF_SIZE, &fp)) { grp_result = &grp; #elif defined (__APPLE__) || defined (__CYGWIN__) setgrent(); while ((grp_result = getgrent()) != NULL) { #else setgrent(); while (getgrent_r(&grp, grp_buffer, PW_BUF_SIZE, &grp_result) == 0 && grp_result != NULL) { #endif if (grp_result->gr_gid == my_gid) { if (strcmp(grp_result->gr_name, group_name)) { debug("including members of group '%s' as it " "corresponds to the same gid as group" " '%s'",grp_result->gr_name,group_name); } for (i=0; grp_result->gr_mem[i]; i++) { if (uid_from_string(grp_result->gr_mem[i], &my_uid) < 0) { /* Group member without valid login */ continue; } if (my_uid == 0) continue; if (j >= uid_cnt) { uid_cnt += 100; xrealloc(group_uids, (sizeof(uid_t) * uid_cnt)); } group_uids[j++] = my_uid; } } } #ifdef HAVE_AIX endgrent_r(&fp); setpwent_r(&fp); while (!getpwent_r(&pw, pw_buffer, PW_BUF_SIZE, &fp)) { pwd_result = &pw; #else endgrent(); setpwent(); #if defined (__sun) while ((pwd_result = getpwent_r(&pw, pw_buffer, PW_BUF_SIZE)) != NULL) { #elif defined (__APPLE__) || defined (__CYGWIN__) while ((pwd_result = getpwent()) != NULL) { #else while (!getpwent_r(&pw, pw_buffer, PW_BUF_SIZE, &pwd_result)) { #endif #endif if (pwd_result->pw_gid != my_gid) continue; if (j >= uid_cnt) { uid_cnt += 100; xrealloc(group_uids, (sizeof(uid_t) * uid_cnt)); } group_uids[j++] = pwd_result->pw_uid; } #ifdef HAVE_AIX endpwent_r(&fp); #else endpwent(); #endif _put_group_cache(group_name, group_uids, uid_cnt); _log_group_members(group_name, group_uids); return group_uids; } /* Delete our group/uid cache */ extern void clear_group_cache(void) { pthread_mutex_lock(&group_cache_mutex); if (group_cache_list) { list_destroy(group_cache_list); group_cache_list = NULL; } pthread_mutex_unlock(&group_cache_mutex); } /* Get a record from our group/uid cache. * Return NULL if not found. */ static uid_t *_get_group_cache(char *group_name) { ListIterator iter; struct group_cache_rec *cache_rec; uid_t *group_uids = NULL; int sz; pthread_mutex_lock(&group_cache_mutex); if (!group_cache_list) { pthread_mutex_unlock(&group_cache_mutex); return NULL; } iter = list_iterator_create(group_cache_list); if (!iter) fatal("list_iterator_create: malloc failure"); while ((cache_rec = (struct group_cache_rec *) list_next(iter))) { if (strcmp(group_name, cache_rec->group_name)) continue; sz = sizeof(uid_t) * (cache_rec->uid_cnt + 1); group_uids = (uid_t *) xmalloc(sz); memcpy(group_uids, cache_rec->group_uids, sz); break; } list_iterator_destroy(iter); pthread_mutex_unlock(&group_cache_mutex); return group_uids; } /* Delete a record from the group/uid cache, used by list functions */ static void _cache_del_func(void *x) { struct group_cache_rec *cache_rec; cache_rec = (struct group_cache_rec *) x; xfree(cache_rec->group_name); xfree(cache_rec->group_uids); xfree(cache_rec); } /* Put a record on our group/uid cache */ static void _put_group_cache(char *group_name, void *group_uids, int uid_cnt) { struct group_cache_rec *cache_rec; int sz; pthread_mutex_lock(&group_cache_mutex); if (!group_cache_list) { group_cache_list = list_create(_cache_del_func); if (!group_cache_list) fatal("list_create: malloc failure:"); } sz = sizeof(uid_t) * (uid_cnt + 1); cache_rec = xmalloc(sizeof(struct group_cache_rec)); cache_rec->group_name = xstrdup(group_name); cache_rec->uid_cnt = uid_cnt; cache_rec->group_uids = (uid_t *) xmalloc(sz); if (uid_cnt > 0) memcpy(cache_rec->group_uids, group_uids, sz); list_append(group_cache_list, cache_rec); pthread_mutex_unlock(&group_cache_mutex); } static void _log_group_members(char *group_name, uid_t *group_uids) { #if _DEBUG int i; if ((group_uids == NULL) || (group_uids[0] == 0)) { info("Group %s has no users", group_name); return; } info("Group %s contains uids:", group_name); for (i=0; group_uids && group_uids[i]; i++) info(" %u", group_uids[i]); #endif }
bool Setup::checkClientUsers(const string& uname) { bool status = true; struct passwd *pwp = NULL; int i = 0; #ifdef _linux_ struct passwd pw; char buf[BUFLEN]; #else static Mutex mutex; ScopedMutex lock(&mutex); #endif setpwent(); while (1 && getuid() == 0) { #ifdef _linux_ i = getpwent_r(&pw, buf, BUFLEN, &pwp); #else pwp = getpwent(); #endif if (i) { break; } if (pwp == NULL) { return true; } if ((uname.empty() && pwp->pw_uid >= INETFS_MIN_UID && pwp->pw_uid <= INETFS_MAX_UID) || (uname.length() > 0 && uname == pwp->pw_name)) { string name = pwp->pw_name; int uid = pwp->pw_uid; int gid = pwp->pw_gid; string home = pwp->pw_dir; // .inetfs dir string local = home + string("/.inetfs"); ::mkdir(local.c_str(), 0700); ::chown(local.c_str(), uid, gid); string passwd = home + string("/.inetfs/passwd"); ::mkdir(passwd.c_str(), 0700); ::chown(passwd.c_str(), uid, gid); #ifdef UID_LINKS_ENABLED string links = home + string("/.inetfs/links"); ::mkdir(links.c_str(), 0700); ::chown(links.c_str(), uid, gid); local = home + string("/.inetfs/links"); if (!file_exists(local.c_str()) && !dir_exists(local.c_str())) { ::symlink(links.c_str(), local.c_str()); ::chown(local.c_str(), uid, gid); ::chmod(local.c_str(), 0700); } #endif } } endpwent(); return status; }
static unsigned int runtest_cmds(cap_channel_t *cappwd) { char bufs[1024], bufc[1024]; unsigned int result; struct passwd *pwds, *pwdc; struct passwd sts, stc; result = 0; setpwent(); cap_setpwent(cappwd); pwds = getpwent(); pwdc = cap_getpwent(cappwd); if (passwd_compare(pwds, pwdc)) { result |= GETPWENT0; pwds = getpwent(); pwdc = cap_getpwent(cappwd); if (passwd_compare(pwds, pwdc)) result |= GETPWENT1; } getpwent_r(&sts, bufs, sizeof(bufs), &pwds); cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) { result |= GETPWENT_R0; getpwent_r(&sts, bufs, sizeof(bufs), &pwds); cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) result |= GETPWENT_R1; } setpwent(); cap_setpwent(cappwd); getpwent_r(&sts, bufs, sizeof(bufs), &pwds); cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) result |= GETPWENT_R2; pwds = getpwent(); pwdc = cap_getpwent(cappwd); if (passwd_compare(pwds, pwdc)) result |= GETPWENT2; pwds = getpwnam("root"); pwdc = cap_getpwnam(cappwd, "root"); if (passwd_compare(pwds, pwdc)) { pwds = getpwnam("operator"); pwdc = cap_getpwnam(cappwd, "operator"); if (passwd_compare(pwds, pwdc)) result |= GETPWNAM; } getpwnam_r("root", &sts, bufs, sizeof(bufs), &pwds); cap_getpwnam_r(cappwd, "root", &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) { getpwnam_r("operator", &sts, bufs, sizeof(bufs), &pwds); cap_getpwnam_r(cappwd, "operator", &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) result |= GETPWNAM_R; } pwds = getpwuid(UID_ROOT); pwdc = cap_getpwuid(cappwd, UID_ROOT); if (passwd_compare(pwds, pwdc)) { pwds = getpwuid(UID_OPERATOR); pwdc = cap_getpwuid(cappwd, UID_OPERATOR); if (passwd_compare(pwds, pwdc)) result |= GETPWUID; } getpwuid_r(UID_ROOT, &sts, bufs, sizeof(bufs), &pwds); cap_getpwuid_r(cappwd, UID_ROOT, &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) { getpwuid_r(UID_OPERATOR, &sts, bufs, sizeof(bufs), &pwds); cap_getpwuid_r(cappwd, UID_OPERATOR, &stc, bufc, sizeof(bufc), &pwdc); if (passwd_compare(pwds, pwdc)) result |= GETPWUID_R; } return (result); }
/*....................................................................... * The _hd_scan_user_home_dirs() function calls a user-provided function * for each username known by the system, passing the function both * the name and the home directory of the user. * * Input: * home HomeDir * The resource object for reading home * directories. * prefix const char * Only information for usernames that * start with this prefix will be * returned. Note that the empty & string "", matches all usernames. * data void * Anonymous data to be passed to the * callback function. * callback_fn HOME_DIR_FN(*) The function to call for each user. * Output: * return int 0 - Successful completion. * 1 - An error occurred. A description * of the error can be obtained by * calling _hd_last_home_dir_error(). */ int _hd_scan_user_home_dirs(HomeDir *home, const char *prefix, void *data, HOME_DIR_FN(*callback_fn)) { int waserr = 0; /* True after errors */ int prefix_len; /* The length of prefix[] */ /* * Check the arguments. */ if(!home || !prefix || !callback_fn) { if(home) { _err_record_msg(home->err, "_hd_scan_user_home_dirs: Missing callback function", END_ERR_MSG); }; return 1; }; /* * Get the length of the username prefix. */ prefix_len = strlen(prefix); /* * There are no reentrant versions of getpwent() etc for scanning * the password file, so disable username completion when the * library is compiled to be reentrant. */ #if defined(PREFER_REENTRANT) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L #if defined __sun && defined __SVR4 if(0) #else if(1) #endif { struct passwd pwd_buffer; /* A returned password entry */ struct passwd *pwd; /* A pointer to pwd_buffer */ char buffer[512]; /* The buffer in which the string members of */ /* pwd_buffer are stored. */ /* * See if the prefix that is being completed is a complete username. */ if(!waserr && getpwnam_r(prefix, &pwd_buffer, buffer, sizeof(buffer), &pwd) == 0 && pwd != NULL) { waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, _err_get_msg(home->err), ERR_MSG_LEN); }; /* * See if the username of the current user minimally matches the prefix. */ if(!waserr && getpwuid_r(getuid(), &pwd_buffer, buffer, sizeof(buffer), &pwd) == 0 && pwd != NULL && strncmp(prefix, pwd->pw_name, prefix_len)==0) { waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, _err_get_msg(home->err), ERR_MSG_LEN); }; /* * Reentrancy not required? */ } else #endif { struct passwd pwd_buffer; /* A returned password entry */ struct passwd *pwd; /* The pointer to the latest password entry */ /* * Open the password file. */ setpwent(); /* * Read the contents of the password file, looking for usernames * that start with the specified prefix, and adding them to the * list of matches. */ #if defined __sun && defined __SVR4 while((pwd = getpwent_r(&pwd_buffer, home->buffer, home->buflen)) != NULL && !waserr) { #else while((pwd = getpwent()) != NULL && !waserr) { #endif if(strncmp(prefix, pwd->pw_name, prefix_len) == 0) { waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, _err_get_msg(home->err), ERR_MSG_LEN); }; }; /* * Close the password file. */ endpwent(); }; /* * Under ksh ~+ stands for the absolute pathname of the current working * directory. */ if(!waserr && strncmp(prefix, "+", prefix_len) == 0) { const char *pwd = hd_getpwd(home); if(pwd) { waserr = callback_fn(data, "+", pwd, _err_get_msg(home->err),ERR_MSG_LEN); } else { waserr = 1; _err_record_msg(home->err, "Can't determine current directory.", END_ERR_MSG); }; }; return waserr; } /*....................................................................... * Return the value of getenv("PWD") if this points to the current * directory, or the return value of getcwd() otherwise. The reason for * prefering PWD over getcwd() is that the former preserves the history * of symbolic links that have been traversed to reach the current * directory. This function is designed to provide the equivalent * expansion of the ksh ~+ directive, which normally returns its value * of PWD. * * Input: * home HomeDir * The resource object for reading home directories. * Output: * return const char * A pointer to either home->buffer, where the * pathname is recorded, the string returned by * getenv("PWD"), or NULL on error. */ static const char *hd_getpwd(HomeDir *home) { /* * Get the absolute path of the current working directory. */ char *cwd = getcwd(home->buffer, home->buflen); /* * Some shells set PWD with the path of the current working directory. * This will differ from cwd in that it won't have had symbolic links * expanded. */ const char *pwd = getenv("PWD"); /* * If PWD was set, and it points to the same directory as cwd, return * its value. Note that it won't be the same if the current shell or * the current program has changed directories, after inheriting PWD * from a parent shell. */ struct stat cwdstat, pwdstat; if(pwd && cwd && stat(cwd, &cwdstat)==0 && stat(pwd, &pwdstat)==0 && cwdstat.st_dev == pwdstat.st_dev && cwdstat.st_ino == pwdstat.st_ino) return pwd; /* * Also return pwd if getcwd() failed, since it represents the best * information that we have access to. */ if(!cwd) return pwd; /* * In the absence of a valid PWD, return cwd. */ return cwd; }
int deluser_main(int argc, char **argv) { /* User or group name */ char *name; /* Username (non-NULL only in "delgroup USER GROUP" case) */ char *member; /* Name of passwd or group file */ const char *pfile; /* Name of shadow or gshadow file */ const char *sfile; /* Are we deluser or delgroup? */ int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u')); if (geteuid() != 0) bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); name = argv[1]; member = NULL; switch (argc) { case 3: if (!ENABLE_FEATURE_DEL_USER_FROM_GROUP || do_deluser) break; /* It's "delgroup USER GROUP" */ member = name; name = argv[2]; /* Fallthrough */ case 2: if (do_deluser) { /* "deluser USER" */ xgetpwnam(name); /* bail out if USER is wrong */ pfile = bb_path_passwd_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_shadow_file; } else { struct group *gr; do_delgroup: /* "delgroup GROUP" or "delgroup USER GROUP" */ if (do_deluser < 0) { /* delgroup after deluser? */ gr = getgrnam(name); if (!gr) return EXIT_SUCCESS; } else { gr = xgetgrnam(name); /* bail out if GROUP is wrong */ } if (!member) { /* "delgroup GROUP" */ struct passwd *pw; struct passwd pwent; /* Check if the group is in use */ #define passwd_buf bb_common_bufsiz1 while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) { if (pwent.pw_gid == gr->gr_gid) bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name); } //endpwent(); } pfile = bb_path_group_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_gshadow_file; } /* Modify pfile, then sfile */ do { if (update_passwd(pfile, name, NULL, member) == -1) return EXIT_FAILURE; if (ENABLE_FEATURE_SHADOWPASSWDS) { pfile = sfile; sfile = NULL; } } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); if (ENABLE_DELGROUP && do_deluser > 0) { /* "deluser USER" also should try to delete * same-named group. IOW: do "delgroup USER" */ // On debian deluser is a perl script that calls userdel. // From man userdel: // If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will // delete the group with the same name as the user. do_deluser = -1; goto do_delgroup; } return EXIT_SUCCESS; } /* Reached only if number of command line args is wrong */ bb_show_usage(); }
/* * Determine the default path to the persistent storage file and create it if it doesn't exist. */ TSS_RESULT get_user_ps_path(char **file) { TSS_RESULT result; char *file_name = NULL, *home_dir = NULL; struct passwd *pwp; #if (defined (__linux) || defined (linux) || defined(__GLIBC__)) struct passwd pw; #endif struct stat stat_buf; char buf[PASSWD_BUFSIZE]; uid_t euid; int rc; if ((file_name = getenv("TSS_USER_PS_FILE"))) { *file = strdup(file_name); return (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY); } #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)) MUTEX_LOCK(user_ps_path); #endif euid = geteuid(); #if defined (SOLARIS) /* * Solaris keeps user PS in a local directory instead of * in the user's home directory, which may be shared * by multiple systems. * * The directory path on Solaris is /var/tpm/userps/[EUID]/ */ rc = snprintf(buf, sizeof (buf), "%s/%d", TSS_USER_PS_DIR, euid); #else setpwent(); while (1) { #if (defined (__linux) || defined (linux) || defined(__GLIBC__)) rc = getpwent_r(&pw, buf, PASSWD_BUFSIZE, &pwp); if (rc) { LogDebugFn("USER PS: Error getting path to home directory: getpwent_r: %s", strerror(rc)); endpwent(); return TSPERR(TSS_E_INTERNAL_ERROR); } #elif (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)) if ((pwp = getpwent()) == NULL) { LogDebugFn("USER PS: Error getting path to home directory: getpwent: %s", strerror(rc)); endpwent(); MUTEX_UNLOCK(user_ps_path); return TSPERR(TSS_E_INTERNAL_ERROR); } #endif if (euid == pwp->pw_uid) { home_dir = strdup(pwp->pw_dir); break; } } endpwent(); if (!home_dir) return TSPERR(TSS_E_OUTOFMEMORY); /* Tack on TSS_USER_PS_DIR and see if it exists */ rc = snprintf(buf, sizeof (buf), "%s/%s", home_dir, TSS_USER_PS_DIR); #endif /* SOLARIS */ if (rc == sizeof (buf)) { LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE); result = TSPERR(TSS_E_INTERNAL_ERROR); goto done; } errno = 0; if ((rc = stat(buf, &stat_buf)) == -1) { if (errno == ENOENT) { errno = 0; /* Create the user's ps directory if it is not there. */ if ((rc = mkdir(buf, 0700)) == -1) { LogDebugFn("USER PS: Error creating dir: %s: %s", buf, strerror(errno)); result = TSPERR(TSS_E_INTERNAL_ERROR); goto done; } } else { LogDebugFn("USER PS: Error stating dir: %s: %s", buf, strerror(errno)); result = TSPERR(TSS_E_INTERNAL_ERROR); goto done; } } /* Directory exists or has been created, return the path to the file */ #if defined (SOLARIS) rc = snprintf(buf, sizeof (buf), "%s/%d/%s", TSS_USER_PS_DIR, euid, TSS_USER_PS_FILE); #else rc = snprintf(buf, sizeof (buf), "%s/%s/%s", home_dir, TSS_USER_PS_DIR, TSS_USER_PS_FILE); #endif if (rc == sizeof (buf)) { LogDebugFn("USER PS: Path to file too long! (> %zd bytes)", sizeof (buf)); } else *file = strdup(buf); result = (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY); done: free(home_dir); return result; }
static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) { semanage_list_t *homedir_list = NULL; semanage_list_t *shells = NULL; fc_match_handle_t hand; char *rbuf = NULL; char *path = NULL; long rbuflen; uid_t temp, minuid = 500, maxuid = 60000; int minuid_set = 0; struct passwd pwstorage, *pwbuf; struct stat buf; int retval; path = semanage_findval(PATH_ETC_USERADD, "HOME", "="); if (path && *path) { if (semanage_list_push(&homedir_list, path)) goto fail; } free(path); path = semanage_findval(PATH_ETC_LIBUSER, "LU_HOMEDIRECTORY", "="); if (path && *path) { if (semanage_list_push(&homedir_list, path)) goto fail; } free(path); path = NULL; if (!homedir_list) { if (semanage_list_push(&homedir_list, PATH_DEFAULT_HOME)) { goto fail; } } if (!stat(PATH_EXPORT_HOME, &buf)) { if (S_ISDIR(buf.st_mode)) { if (semanage_list_push(&homedir_list, PATH_EXPORT_HOME)) { goto fail; } } } if (!(s->usepasswd)) return homedir_list; shells = get_shell_list(); assert(shells); path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MIN", NULL); if (path && *path) { temp = atoi(path); minuid = temp; minuid_set = 1; } free(path); path = NULL; path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL); if (path && *path) { temp = atoi(path); maxuid = temp; } free(path); path = NULL; path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "="); if (path && *path) { temp = atoi(path); if (!minuid_set || temp < minuid) { minuid = temp; minuid_set = 1; } } free(path); path = NULL; rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (rbuflen <= 0) goto fail; rbuf = malloc(rbuflen); if (rbuf == NULL) goto fail; setpwent(); while ((retval = getpwent_r(&pwstorage, rbuf, rbuflen, &pwbuf)) == 0) { if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid) continue; if (!semanage_list_find(shells, pwbuf->pw_shell)) continue; int len = strlen(pwbuf->pw_dir) -1; for(; len > 0 && pwbuf->pw_dir[len] == '/'; len--) { pwbuf->pw_dir[len] = '\0'; } if (strcmp(pwbuf->pw_dir, "/") == 0) continue; if (ignore(pwbuf->pw_dir)) continue; if (semanage_str_count(pwbuf->pw_dir, '/') <= 1) continue; if (!(path = strdup(pwbuf->pw_dir))) { break; } semanage_rtrim(path, '/'); if (!semanage_list_find(homedir_list, path)) { /* * Now check for an existing file context that matches * so we don't label a non-homedir as a homedir. */ hand.dir = path; hand.matched = 0; if (semanage_fcontext_iterate(s->h_semanage, fcontext_matches, &hand) == STATUS_ERR) goto fail; /* NOTE: old genhomedircon printed a warning on match */ if (hand.matched) { WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or greater than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid, maxuid); } else { if (semanage_list_push(&homedir_list, path)) goto fail; } } free(path); path = NULL; } if (retval && retval != ENOENT) { WARN(s->h_semanage, "Error while fetching users. " "Returning list so far."); } if (semanage_list_sort(&homedir_list)) goto fail; endpwent(); free(rbuf); semanage_list_destroy(&shells); return homedir_list; fail: endpwent(); free(rbuf); free(path); semanage_list_destroy(&homedir_list); semanage_list_destroy(&shells); return NULL; }
/* * get_group_members - identify the users in a given group name * IN group_name - a single group name * RET a zero terminated list of its UIDs or NULL on error * NOTE: User root has implicitly access to every group * NOTE: The caller must xfree non-NULL return values */ extern uid_t *get_group_members(char *group_name) { char *grp_buffer = NULL; struct group grp, *grp_result = NULL; struct passwd *pwd_result = NULL; uid_t *group_uids = NULL, my_uid; gid_t my_gid; int buflen = PW_BUF_SIZE, i, j, res, uid_cnt; #ifdef HAVE_AIX FILE *fp = NULL; #elif defined (__APPLE__) || defined (__CYGWIN__) #else char pw_buffer[PW_BUF_SIZE]; struct passwd pw; #endif group_uids = _get_group_cache(group_name); if (group_uids) { /* We found in cache */ _log_group_members(group_name, group_uids); return group_uids; } #if defined(_SC_GETGR_R_SIZE_MAX) i = sysconf(_SC_GETGR_R_SIZE_MAX); buflen = MAX(buflen, i); #endif grp_buffer = xmalloc(buflen); while (1) { slurm_seterrno(0); res = getgrnam_r(group_name, &grp, grp_buffer, buflen, &grp_result); /* We need to check for !grp_result, since it appears some * versions of this function do not return an error on * failure. */ if (res != 0 || !grp_result) { if (errno == ERANGE) { buflen *= 2; xrealloc(grp_buffer, buflen); continue; } error("%s: Could not find configured group %s", __func__, group_name); xfree(grp_buffer); return NULL; } break; } my_gid = grp_result->gr_gid; j = 0; uid_cnt = 0; /* Get the members from the getgrnam_r() call. */ for (i = 0; grp_result->gr_mem[i]; i++) { if (uid_from_string(grp_result->gr_mem[i], &my_uid) < 0) { continue; } if (my_uid == 0) continue; if (j + 1 >= uid_cnt) { uid_cnt += 100; xrealloc(group_uids, (sizeof(uid_t) * uid_cnt)); } group_uids[j++] = my_uid; } #ifdef HAVE_AIX setgrent_r(&fp); while (1) { slurm_seterrno(0); res = getgrent_r(&grp, grp_buffer, buflen, &fp); if (res != 0) { if (errno == ERANGE) { buflen *= 2; xrealloc(grp_buffer, buflen); continue; } break; } grp_result = &grp; #elif defined (__APPLE__) || defined (__CYGWIN__) setgrent(); while (1) { if ((grp_result = getgrent()) == NULL) break; #else setgrent(); while (1) { /* MH-CEA workaround to handle different group entries with * the same gid */ slurm_seterrno(0); res = getgrent_r(&grp, grp_buffer, buflen, &grp_result); if (res != 0 || grp_result == NULL) { /* FreeBSD returns 0 and sets the grp_result to NULL * unlike linux which returns ENOENT. */ if (errno == ERANGE) { buflen *= 2; xrealloc(grp_buffer, buflen); continue; } break; } #endif if (grp_result->gr_gid == my_gid) { if (strcmp(grp_result->gr_name, group_name)) { debug("including members of group '%s' as it " "corresponds to the same gid as group" " '%s'",grp_result->gr_name,group_name); } for (i=0; grp_result->gr_mem[i]; i++) { if (uid_from_string(grp_result->gr_mem[i], &my_uid) < 0) { /* Group member without valid login */ continue; } if (my_uid == 0) continue; if (j+1 >= uid_cnt) { uid_cnt += 100; xrealloc(group_uids, (sizeof(uid_t) * uid_cnt)); } group_uids[j++] = my_uid; } } } #ifdef HAVE_AIX endgrent_r(&fp); setpwent_r(&fp); while (!getpwent_r(&pw, pw_buffer, PW_BUF_SIZE, &fp)) { pwd_result = &pw; #else endgrent(); setpwent(); #if defined (__sun) while ((pwd_result = getpwent_r(&pw, pw_buffer, PW_BUF_SIZE)) != NULL) { #elif defined (__APPLE__) || defined (__CYGWIN__) while ((pwd_result = getpwent()) != NULL) { #else while (!getpwent_r(&pw, pw_buffer, PW_BUF_SIZE, &pwd_result)) { #endif #endif /* At eof FreeBSD returns 0 unlike Linux * which returns ENOENT. */ if (pwd_result == NULL) break; if (pwd_result->pw_gid != my_gid) continue; if (j+1 >= uid_cnt) { uid_cnt += 100; xrealloc(group_uids, (sizeof(uid_t) * uid_cnt)); } group_uids[j++] = pwd_result->pw_uid; } #ifdef HAVE_AIX endpwent_r(&fp); #else endpwent(); #endif xfree(grp_buffer); _put_group_cache(group_name, group_uids, j); _log_group_members(group_name, group_uids); return group_uids; } /* Delete our group/uid cache */ extern void clear_group_cache(void) { slurm_mutex_lock(&group_cache_mutex); FREE_NULL_LIST(group_cache_list); slurm_mutex_unlock(&group_cache_mutex); } /* Get a record from our group/uid cache. * Return NULL if not found. */ static uid_t *_get_group_cache(char *group_name) { ListIterator iter; struct group_cache_rec *cache_rec; uid_t *group_uids = NULL; int sz; slurm_mutex_lock(&group_cache_mutex); if (!group_cache_list) { slurm_mutex_unlock(&group_cache_mutex); return NULL; } iter = list_iterator_create(group_cache_list); while ((cache_rec = (struct group_cache_rec *) list_next(iter))) { if (strcmp(group_name, cache_rec->group_name)) continue; sz = sizeof(uid_t) * (cache_rec->uid_cnt + 1); group_uids = (uid_t *) xmalloc(sz); memcpy(group_uids, cache_rec->group_uids, sz); break; } list_iterator_destroy(iter); slurm_mutex_unlock(&group_cache_mutex); return group_uids; } /* Delete a record from the group/uid cache, used by list functions */ static void _cache_del_func(void *x) { struct group_cache_rec *cache_rec; cache_rec = (struct group_cache_rec *) x; xfree(cache_rec->group_name); xfree(cache_rec->group_uids); xfree(cache_rec); } /* Put a record on our group/uid cache */ static void _put_group_cache(char *group_name, void *group_uids, int uid_cnt) { struct group_cache_rec *cache_rec; int sz; slurm_mutex_lock(&group_cache_mutex); if (!group_cache_list) { group_cache_list = list_create(_cache_del_func); } sz = sizeof(uid_t) * (uid_cnt); cache_rec = xmalloc(sizeof(struct group_cache_rec)); cache_rec->group_name = xstrdup(group_name); cache_rec->uid_cnt = uid_cnt; cache_rec->group_uids = (uid_t *) xmalloc(sizeof(uid_t) + sz); if (uid_cnt > 0) memcpy(cache_rec->group_uids, group_uids, sz); list_append(group_cache_list, cache_rec); slurm_mutex_unlock(&group_cache_mutex); } static void _log_group_members(char *group_name, uid_t *group_uids) { #if _DEBUG int i; if ((group_uids == NULL) || (group_uids[0] == 0)) { info("Group %s has no users", group_name); return; } info("Group %s contains uids:", group_name); for (i=0; group_uids && group_uids[i]; i++) info(" %u", group_uids[i]); #endif }