From 31668ed6f0bf6d2b1c6d621cca42aee0daf23a65 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 24 Sep 2004 13:13:18 +0000 Subject: [PATCH] Relevant BUGIDs: Purpose of commit: Commit summary: --------------- bugfix: 440107: Add various patches from Linux Distibutors to make PAM modules reentrant. --- CHANGELOG | 3 + _pam_aconf.h.in | 4 + configure | 6 +- configure.in | 2 +- modules/pam_access/pam_access.c | 68 ++++++++-------- modules/pam_group/pam_group.c | 15 ++-- modules/pam_lastlog/pam_lastlog.c | 2 +- modules/pam_limits/pam_limits.c | 78 ++++-------------- modules/pam_listfile/pam_listfile.c | 48 ++--------- modules/pam_mail/pam_mail.c | 3 +- modules/pam_mkhomedir/pam_mkhomedir.c | 2 +- modules/pam_rhosts/pam_rhosts_auth.c | 2 +- modules/pam_securetty/pam_securetty.c | 3 +- modules/pam_shells/pam_shells.c | 4 +- modules/pam_succeed_if/pam_succeed_if.c | 2 + modules/pam_tally/Makefile | 10 ++- modules/pam_tally/pam_tally.c | 3 +- modules/pam_unix/Makefile | 7 +- modules/pam_unix/pam_unix_acct.c | 7 +- modules/pam_unix/pam_unix_auth.c | 2 +- modules/pam_unix/pam_unix_passwd.c | 11 ++- modules/pam_unix/support.c | 47 ++--------- modules/pam_unix/support.h | 3 +- modules/pam_wheel/pam_wheel.c | 12 +-- modules/pammodutil/Makefile | 3 +- .../include/security/_pam_modutil.h | 27 +++++++ modules/pammodutil/modutil_getpwnam.c | 60 +++++++++++++- modules/pammodutil/modutil_getpwuid.c | 79 +++++++++++++++++-- 28 files changed, 287 insertions(+), 226 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 33e26f0e..377d80bc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -111,9 +111,12 @@ BerliOS Bugs are marked with (BerliOS #XXXX). * Make.Rules.in: Add targets for installing man pages for modules (from Linux distributors - kukuk) * Add pam_xauth module (Bug 436440 - kukuk) +* Add pam_localuser module (Bug 436444 - kukuk) +* Add pam_succeed_if module (from Linux distributors - kukuk) * configure.in: Fix check for libcrypt (Bug 417704 - kukuk) * Add the "broken_shadow" argument to pam_unix, for ignoring errors reading shadow information (from Linux distributors - kukuk) +* Add patches to make PAM modules reentrant (Bug 440107 - kukuk) 0.77: Mon Sep 23 10:25:42 PDT 2002 diff --git a/_pam_aconf.h.in b/_pam_aconf.h.in index 99294d63..1b1cde95 100644 --- a/_pam_aconf.h.in +++ b/_pam_aconf.h.in @@ -61,7 +61,11 @@ /* Define if reentrant declarations of standard nss functions are available */ #undef HAVE_GETPWNAM_R +#undef HAVE_GETPWUID_R +#undef HAVE_GETSPNAM_R #undef HAVE_GETGRNAM_R +#undef HAVE_GETGRGID_R +#undef HAVE_GETGROUPLIST /* ugly hack to partially support old pam_strerror syntax */ #undef UGLY_HACK_FOR_PRIOR_BEHAVIOR_SUPPORT diff --git a/configure b/configure index 663c25a0..555f16a7 100755 --- a/configure +++ b/configure @@ -7337,7 +7337,11 @@ done -for ac_func in getpwnam_r getgrnam_r + + + + +for ac_func in getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getgrouplist do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 09a345fe..73734335 100644 --- a/configure.in +++ b/configure.in @@ -402,7 +402,7 @@ AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_CHECK_FUNCS(gethostname gettimeofday mkdir select strcspn strdup strerror strspn strstr strtol uname) -AC_CHECK_FUNCS(getpwnam_r getgrnam_r) +AC_CHECK_FUNCS(getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getgrouplist) dnl Checks for programs/utilities AC_CHECK_PROG(HAVE_SGML2TXT, sgml2txt, yes, no) diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index 031b94ba..42e03527 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -59,6 +59,7 @@ #include #include +#include /* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */ @@ -148,17 +149,18 @@ static int parse_args(struct login_info *loginfo, int argc, const char **argv) return 1; /* OK */ } -typedef int match_func (char *, struct login_info *); +typedef int match_func (pam_handle_t *, char *, struct login_info *); -static int list_match (char *, struct login_info *, - match_func *); -static int user_match (char *, struct login_info *); -static int from_match (char *, struct login_info *); -static int string_match (char *, char *); +static int list_match (pam_handle_t *, char *, struct login_info *, + match_func *); +static int user_match (pam_handle_t *, char *, struct login_info *); +static int from_match (pam_handle_t *, char *, struct login_info *); +static int string_match (pam_handle_t *, char *, char *); /* login_access - match username/group and host/tty with access control file */ -static int login_access(struct login_info *item) +static int +login_access (pam_handle_t *pamh, struct login_info *item) { FILE *fp; char line[BUFSIZ]; @@ -205,8 +207,8 @@ static int login_access(struct login_info *item) item->config_file, lineno); continue; } - match = (list_match(froms, item, from_match) - && list_match(users, item, user_match)); + match = (list_match(pamh, froms, item, from_match) + && list_match(pamh, users, item, user_match)); } (void) fclose(fp); } else if (errno != ENOENT) { @@ -218,7 +220,8 @@ static int login_access(struct login_info *item) /* list_match - match an item against a list of tokens with exceptions */ -static int list_match(char *list, struct login_info *item, match_func *match_fn) +static int list_match(pam_handle_t *pamh, + char *list, struct login_info *item, match_func *match_fn) { char *tok; int match = NO; @@ -233,7 +236,7 @@ static int list_match(char *list, struct login_info *item, match_func *match_fn) for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) { if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ break; - if ((match = (*match_fn) (tok, item))) /* YES */ + if ((match = (*match_fn) (pamh, tok, item))) /* YES */ break; } /* Process exceptions to matches. */ @@ -241,7 +244,7 @@ static int list_match(char *list, struct login_info *item, match_func *match_fn) if (match != NO) { while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT")) /* VOID */ ; - if (tok == 0 || list_match((char *) 0, item, match_fn) == NO) + if (tok == 0 || list_match(pamh, (char *) 0, item, match_fn) == NO) return (match); } return (NO); @@ -273,12 +276,10 @@ static int netgroup_match(char *group, char *machine, char *user) /* user_match - match a username against one token */ -static int user_match(char *tok, struct login_info *item) +static int user_match(pam_handle_t *pamh, char *tok, struct login_info *item) { char *string = item->user->pw_name; struct login_info fake_item; - struct group *group; - int i; char *at; /* @@ -293,24 +294,22 @@ static int user_match(char *tok, struct login_info *item) fake_item.from = myhostname(); if (fake_item.from == NULL) return NO; - return (user_match(tok, item) && from_match(at + 1, &fake_item)); - } else if (tok[0] == '@') { /* netgroup */ + return (user_match (pamh, tok, item) && from_match (pamh, at + 1, &fake_item)); + } else if (tok[0] == '@') /* netgroup */ return (netgroup_match(tok + 1, (char *) 0, string)); - } else if (string_match(tok, string)) { /* ALL or exact match */ - return (YES); - } else if ((group = getgrnam(tok))) { /* try group membership */ - if (item->user->pw_gid == group->gr_gid) - return (YES); - for (i = 0; group->gr_mem[i]; i++) - if (strcasecmp(string, group->gr_mem[i]) == 0) - return (YES); - } - return (NO); + else if (string_match (pamh, tok, string)) /* ALL or exact match */ + return YES; + else if (_pammodutil_user_in_group_nam_nam (pamh, item->user->pw_name, tok)) + /* try group membership */ + return YES; + + return NO; } /* from_match - match a host or tty against a list of tokens */ -static int from_match(char *tok, struct login_info *item) +static int +from_match (pam_handle_t *pamh, char *tok, struct login_info *item) { char *string = item->from; int tok_len; @@ -327,9 +326,9 @@ static int from_match(char *tok, struct login_info *item) if (tok[0] == '@') { /* netgroup */ return (netgroup_match(tok + 1, string, (char *) 0)); - } else if (string_match(tok, string)) { /* ALL or exact match */ - return (YES); - } else if (tok[0] == '.') { /* domain: match last fields */ + } else if (string_match (pamh, tok, string)) /* ALL or exact match */ + return YES; + else if (tok[0] == '.') { /* domain: match last fields */ if ((str_len = strlen(string)) > (tok_len = strlen(tok)) && strcasecmp(tok, string + str_len - tok_len) == 0) return (YES); @@ -373,7 +372,8 @@ static int from_match(char *tok, struct login_info *item) /* string_match - match a string against one token */ -static int string_match(char *tok, char *string) +static int +string_match (pam_handle_t *pamh, char *tok, char *string) { /* @@ -444,7 +444,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc } - if ((user_pw=getpwnam(user))==NULL) return (PAM_USER_UNKNOWN); + if ((user_pw=_pammodutil_getpwnam(pamh, user))==NULL) return (PAM_USER_UNKNOWN); /* * Bundle up the arguments to avoid unnecessary clumsiness later on. @@ -461,7 +461,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc return PAM_ABORT; } - if (login_access(&loginfo)) { + if (login_access(pamh, &loginfo)) { return (PAM_SUCCESS); } else { _log_err("access denied for user `%s' from `%s'",user,from); diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c index 4b42506c..e07a932e 100644 --- a/modules/pam_group/pam_group.c +++ b/modules/pam_group/pam_group.c @@ -57,6 +57,7 @@ typedef enum { AND, OR } operator; #include #include +#include /* --- static functions for checking whether the user should be let in --- */ @@ -526,7 +527,7 @@ static int find_member(const char *string, int *at) #define GROUP_BLK 10 #define blk_size(len) (((len-1 + GROUP_BLK)/GROUP_BLK)*GROUP_BLK) -static int mkgrplist(char *buf, gid_t **list, int len) +static int mkgrplist(pam_handle_t *pamh, char *buf, gid_t **list, int len) { int l,at=0; int blks; @@ -589,7 +590,7 @@ static int mkgrplist(char *buf, gid_t **list, int len) { const struct group *grp; - grp = getgrnam(buf+at); + grp = _pammodutil_getgrnam(pamh, buf+at); if (grp == NULL) { _log_err("bad group: %s", buf+at); } else { @@ -608,8 +609,8 @@ static int mkgrplist(char *buf, gid_t **list, int len) } -static int check_account(const char *service, const char *tty - , const char *user) +static int check_account(pam_handle_t *pamh, const char *service, + const char *tty, const char *user) { int from=0,to=0,fd=-1; char *buffer=NULL; @@ -708,7 +709,7 @@ static int check_account(const char *service, const char *tty if (good) { D(("adding %s to gid list", buffer)); - good = mkgrplist(buffer, &grps, no_grps); + good = mkgrplist(pamh, buffer, &grps, no_grps); if (good < 0) { no_grps = 0; } else { @@ -831,7 +832,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags /* We initialize the pwdb library and check the account */ retval = pwdb_start(); /* initialize */ if (retval == PWDB_SUCCESS) { - retval = check_account(service,tty,user); /* get groups */ + retval = check_account(pamh, service,tty,user); /* get groups */ (void) pwdb_end(); /* tidy up */ } else { D(("failed to initialize pwdb; %s", pwdb_strerror(retval))); @@ -840,7 +841,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags } #else /* WANT_PWDB */ - retval = check_account(service,tty,user); /* get groups */ + retval = check_account(pamh,service,tty,user); /* get groups */ #endif /* WANT_PWDB */ return retval; diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index 6e53c244..e9eeac4e 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -425,7 +425,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc /* what uid? */ - pwd = getpwnam(user); + pwd = _pammodutil_getpwnam (pamh, user); if (pwd == NULL) { D(("couldn't identify user %s", user)); return PAM_CRED_INSUFFICIENT; diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index 536446bd..4354d3e1 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -90,6 +90,7 @@ struct pam_limit_s { #include #include +#include /* logging */ static void _pam_log(int err, const char *format, ...) @@ -147,62 +148,10 @@ static int _pam_parse(int argc, const char **argv, struct pam_limit_s *pl) #define LIMIT_ERR 1 /* error setting a limit */ #define LOGIN_ERR 2 /* too many logins err */ -/* checks if a user is on a list of members of the GID 0 group */ -static int is_on_list(char * const *list, const char *member) -{ - while (*list) { - if (strcmp(*list, member) == 0) - return 1; - list++; - } - return 0; -} - -/* - * Checks if a user is a member of a group - return non-zero if - * the user is in the group. - */ -static int is_in_group(const char *user_name, const char *group_name) -{ - struct passwd *pwd; - struct group *grp, *pgrp; - char uname[LINE_LENGTH], gname[LINE_LENGTH]; - - if (!user_name || !strlen(user_name)) - return 0; - if (!group_name || !strlen(group_name)) - return 0; - memset(uname, 0, sizeof(uname)); - strncpy(uname, user_name, sizeof(uname)-1); - memset(gname, 0, sizeof(gname)); - strncpy(gname, group_name, sizeof(gname)-1); - - pwd = getpwnam(uname); - if (!pwd) - return 0; - - /* the info about this group */ - grp = getgrnam(gname); - if (!grp) - return 0; - - /* first check: is a member of the group_name group ? */ - if (is_on_list(grp->gr_mem, uname)) - return 1; - - /* next check: user primary group is group_name ? */ - pgrp = getgrgid(pwd->pw_gid); - if (!pgrp) - return 0; - if (!strcmp(pgrp->gr_name, gname)) - return 1; - - return 0; -} - /* Counts the number of user logins and check against the limit*/ -static int check_logins(const char *name, int limit, int ctrl, - struct pam_limit_s *pl) +static int +check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl, + struct pam_limit_s *pl) { struct utmp *ut; unsigned int count; @@ -254,7 +203,7 @@ static int check_logins(const char *name, int limit, int ctrl, continue; } if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP) - && !is_in_group(ut->UT_USER, name)) { + && !_pammodutil_user_in_group_nam_nam(pamh, ut->UT_USER, name)) { continue; } } @@ -444,7 +393,7 @@ static void process_limit(int source, const char *lim_type, return; } -static int parse_config_file(const char *uname, int ctrl, +static int parse_config_file(pam_handle_t *pamh, const char *uname, int ctrl, struct pam_limit_s *pl) { FILE *fil; @@ -519,7 +468,7 @@ static int parse_config_file(const char *uname, int ctrl, _pam_log(LOG_DEBUG, "checking if %s is in group %s", uname, domain + 1); } - if (is_in_group(uname, domain+1)) + if (_pammodutil_user_in_group_nam_nam(pamh, uname, domain+1)) process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl, pl); } else if (domain[0]=='%') { @@ -530,7 +479,7 @@ static int parse_config_file(const char *uname, int ctrl, if (strcmp(domain,"%") == 0) process_limit(LIMITS_DEF_ALL, ltype, item, value, ctrl, pl); - else if (is_in_group(uname, domain+1)) + else if (_pammodutil_user_in_group_nam_nam(pamh, uname, domain+1)) process_limit(LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl, pl); } else if (strcmp(domain, "*") == 0) @@ -543,7 +492,7 @@ static int parse_config_file(const char *uname, int ctrl, } fclose(fil); return PAM_IGNORE; - } else if (domain[0] == '@' && is_in_group(uname, domain+1)) { + } else if (domain[0] == '@' && _pammodutil_user_in_group_nam_nam(pamh, uname, domain+1)) { if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_DEBUG, "no limits for '%s' in group '%s'", uname, domain+1); @@ -559,7 +508,8 @@ static int parse_config_file(const char *uname, int ctrl, return PAM_SUCCESS; } -static int setup_limits(const char * uname, uid_t uid, int ctrl, +static int setup_limits(pam_handle_t *pamh, + const char *uname, uid_t uid, int ctrl, struct pam_limit_s *pl) { int i; @@ -599,7 +549,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl, if (uid == 0) { D(("skip login limit check for uid=0")); } else if (pl->login_limit > 0) { - if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) { + if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) { retval |= LOGIN_ERR; } } else if (pl->login_limit == 0) { @@ -644,7 +594,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, return PAM_IGNORE; } - retval = parse_config_file(pwd->pw_name, ctrl, &pl); + retval = parse_config_file(pamh, pwd->pw_name, ctrl, &pl); if (retval == PAM_IGNORE) { D(("the configuration file has an applicable ' -' entry")); return PAM_SUCCESS; @@ -657,7 +607,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, if (ctrl & PAM_DO_SETREUID) { setreuid(pwd->pw_uid, -1); } - retval = setup_limits(pwd->pw_name, pwd->pw_uid, ctrl, &pl); + retval = setup_limits(pamh, pwd->pw_name, pwd->pw_uid, ctrl, &pl); if (retval != LIMITED_OK) { return PAM_PERM_DENIED; } diff --git a/modules/pam_listfile/pam_listfile.c b/modules/pam_listfile/pam_listfile.c index bc677be3..0ce3e0b1 100644 --- a/modules/pam_listfile/pam_listfile.c +++ b/modules/pam_listfile/pam_listfile.c @@ -39,6 +39,7 @@ #include #include +#include /* some syslogging */ @@ -64,45 +65,6 @@ static int is_on_list(char * const *list, const char *member) return 0; } -/* Checks if a user is a member of a group */ -static int is_on_group(const char *user_name, const char *group_name) -{ - struct passwd *pwd; - struct group *grp, *pgrp; - char uname[BUFSIZ], gname[BUFSIZ]; - - if (!strlen(user_name)) - return 0; - if (!strlen(group_name)) - return 0; - bzero(uname, sizeof(uname)); - strncpy(uname, user_name, sizeof(uname)-1); - bzero(gname, sizeof(gname)); - strncpy(gname, group_name, sizeof(gname)-1); - - pwd = getpwnam(uname); - if (!pwd) - return 0; - - /* the info about this group */ - grp = getgrnam(gname); - if (!grp) - return 0; - - /* first check: is a member of the group_name group ? */ - if (is_on_list(grp->gr_mem, uname)) - return 1; - - /* next check: user primary group is group_name ? */ - pgrp = getgrgid(pwd->pw_gid); - if (!pgrp) - return 0; - if (!strcmp(pgrp->gr_name, gname)) - return 1; - - return 0; -} - /* --- authentication management functions (only) --- */ /* Extended Items that are not directly available via pam_get_item() */ @@ -257,7 +219,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar return PAM_IGNORE; } } else if(apply_type==APPLY_TYPE_GROUP) { - if(!is_on_group(user_name,apply_val)) { + if(!_pammodutil_user_in_group_nam_nam(pamh,user_name,apply_val)) { /* Not a member of apply= group */ #ifdef DEBUG _pam_log(LOG_DEBUG, @@ -295,13 +257,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar if(extitem) { switch(extitem) { case EI_GROUP: - userinfo = getpwnam(citemp); + userinfo = _pammodutil_getpwnam(pamh, citemp); if (userinfo == NULL) { _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getpwnam(%s) failed", citemp); return onerr; } - grpinfo = getgrgid(userinfo->pw_gid); + grpinfo = _pammodutil_getgrgid(pamh, userinfo->pw_gid); if (grpinfo == NULL) { _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getgrgid(%d) failed", (int)userinfo->pw_gid); @@ -322,7 +284,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar /* Assume that we have already gotten PAM_USER in pam_get_item() - a valid assumption since citem gets set to PAM_USER in the extitem switch */ - userinfo = getpwnam(citemp); + userinfo = _pammodutil_getpwnam(pamh, citemp); if (userinfo == NULL) { _pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getpwnam(%s) failed", citemp); diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index 4888a1a5..6cd173b4 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -46,6 +46,7 @@ #include #include +#include /* some syslogging */ @@ -184,7 +185,7 @@ static int get_folder(pam_handle_t *pamh, int ctrl, if (ctrl & PAM_NEW_MAIL_DIR) { path = *path_mail; if (*path == '~') { /* support for $HOME delivery */ - pwd = getpwnam(user); + pwd = _pammodutil_getpwnam(pamh, user); if (pwd == NULL) { _log_err(LOG_ERR, "user [%s] unknown", user); _pam_overwrite(*path_mail); diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index 11180444..6814056f 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -359,7 +359,7 @@ int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc } /* Get the password entry */ - pwd = getpwnam(user); + pwd = _pammodutil_getpwnam (pamh, user); if (pwd == NULL) { D(("couldn't identify user %s", user)); diff --git a/modules/pam_rhosts/pam_rhosts_auth.c b/modules/pam_rhosts/pam_rhosts_auth.c index 95a1aad3..374318dc 100644 --- a/modules/pam_rhosts/pam_rhosts_auth.c +++ b/modules/pam_rhosts/pam_rhosts_auth.c @@ -550,7 +550,7 @@ pam_iruserok(pam_handle_t *pamh, /* private group caveat */ if (opts->opt_private_group) { - struct group *grp = getgrgid(sbuf.st_gid); + struct group *grp = _pammodutil_getgrgid(pamh, sbuf.st_gid); if (NULL == grp || NULL == grp->gr_name || strcmp(luser,grp->gr_name)) { diff --git a/modules/pam_securetty/pam_securetty.c b/modules/pam_securetty/pam_securetty.c index 274b3b74..8abbcb94 100644 --- a/modules/pam_securetty/pam_securetty.c +++ b/modules/pam_securetty/pam_securetty.c @@ -34,6 +34,7 @@ #define PAM_SM_ACCOUNT #include +#include /* some syslogging */ @@ -97,7 +98,7 @@ static int securetty_perform_check(pam_handle_t *pamh, int flags, int ctrl, return (retval == PAM_CONV_AGAIN ? PAM_INCOMPLETE:PAM_SERVICE_ERR); } - user_pwd = getpwnam(username); + user_pwd = _pammodutil_getpwnam(pamh, username); if (user_pwd == NULL) { return PAM_IGNORE; } else if (user_pwd->pw_uid != 0) { /* If the user is not root, diff --git a/modules/pam_shells/pam_shells.c b/modules/pam_shells/pam_shells.c index c9e2ed6c..64359eac 100644 --- a/modules/pam_shells/pam_shells.c +++ b/modules/pam_shells/pam_shells.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #define PAM_SM_ACCOUNT #include +#include /* some syslogging */ @@ -71,7 +73,7 @@ static int perform_check(pam_handle_t *pamh, int flags) return PAM_SERVICE_ERR; } - pw = getpwnam(userName); + pw = _pammodutil_getpwnam(pamh, userName); if (!pw) { return PAM_AUTH_ERR; /* user doesn't exist */ } diff --git a/modules/pam_succeed_if/pam_succeed_if.c b/modules/pam_succeed_if/pam_succeed_if.c index 82491b6e..23974afa 100644 --- a/modules/pam_succeed_if/pam_succeed_if.c +++ b/modules/pam_succeed_if/pam_succeed_if.c @@ -37,6 +37,8 @@ * */ +#define _GNU_SOURCE + #include #include #include diff --git a/modules/pam_tally/Makefile b/modules/pam_tally/Makefile index c39970dd..718d3b30 100644 --- a/modules/pam_tally/Makefile +++ b/modules/pam_tally/Makefile @@ -44,6 +44,12 @@ endif APPLICATION = $(TITLE) APPMODE = 755 +LINK_PAMMODUTILS = -L../pammodutil -lpammodutil -L../../libpam -lpam +INCLUDE_PAMMODUTILS = -I../pammodutil/include + +LDFLAGS += $(LINK_PAMMODUTILS) +CFLAGS += $(INCLUDE_PAMMODUTILS) + ####################### don't edit below ####################### all: dirs $(LIBSHARED) $(LIBSTATIC) register $(APPLICATION) @@ -65,10 +71,10 @@ ifdef DYNAMIC $(LIBOBJD): $(LIBSRC) $(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) -L../../libpam -lpam $(NEED_LINK_LIB_C) + $(LD_D) -o $@ $(LIBOBJD) $(LDFLAGS) $(APPLICATION): $(APPOBJD) $(TITLE).c - $(CC) $(CFLAGS) -o $@ $(APPOBJD) $(LOADLIBES) + $(CC) $(CFLAGS) -o $@ $(APPOBJD) $(LDFLAGS) $(LOADLIBES) endif diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c index 27fe0b37..341f448e 100644 --- a/modules/pam_tally/pam_tally.c +++ b/modules/pam_tally/pam_tally.c @@ -49,6 +49,7 @@ /* #define PAM_SM_PASSWORD */ #include +#include /*---------------------------------------------------------------------*/ @@ -123,7 +124,7 @@ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp ) return PAM_AUTH_ERR; } - if ( ! ( pw = getpwnam( user ) ) ) { + if ( ! ( pw = _pammodutil_getpwnam( pamh, user ) ) ) { _pam_log(LOG_ERR,MODULE_NAME ": pam_get_uid; no such user %s",user); return PAM_USER_UNKNOWN; } diff --git a/modules/pam_unix/Makefile b/modules/pam_unix/Makefile index 61c4beaa..3fe0e8ae 100644 --- a/modules/pam_unix/Makefile +++ b/modules/pam_unix/Makefile @@ -39,12 +39,15 @@ CHKPWD=unix_chkpwd EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" +LINK_PAMMODUTILS = -L../pammodutil -lpammodutil +INCLUDE_PAMMODUTILS = -I../pammodutil/include + ######################################################################## CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS) \ - -I../pammodutil/include + $(INCLUDE_PAMMODUTILS) -LDLIBS = $(EXTRALS) -L../pammodutil -lpammodutil +LDLIBS = $(EXTRALS) $(LINK_PAMMODUTILS) ifdef USE_CRACKLIB CRACKLIB = -lcrack diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 58ba93c1..f87b13b1 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -53,6 +53,7 @@ #define PAM_SM_ACCOUNT #include +#include #ifndef LINUX_PAM #include @@ -89,7 +90,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, return PAM_USER_UNKNOWN; } - pwent = getpwnam(uname); + pwent = _pammodutil_getpwnam(pamh, uname); if (!pwent) { _log_err(LOG_ALERT, pamh ,"could not identify user (from getpwnam(%s))" @@ -113,7 +114,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, return PAM_CRED_INSUFFICIENT; } } - spent = getspnam( uname ); + spent = _pammodutil_getspnam (pamh, uname); if (save_uid == pwent->pw_uid) setreuid( save_uid, save_euid ); else { @@ -123,7 +124,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, } } else if (!strcmp( pwent->pw_passwd, "x" )) { - spent = getspnam(uname); + spent = _pammodutil_getspnam (pamh, uname); } else { return PAM_SUCCESS; } diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index a0c1da81..39e0cde5 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -149,7 +149,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags /* if this user does not have a password... */ - if (_unix_blankpasswd(ctrl, name)) { + if (_unix_blankpasswd(pamh, ctrl, name)) { D(("user '%s' has blank passwd", name)); name = NULL; retval = PAM_SUCCESS; diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 4320171c..f11d2b20 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -73,6 +73,8 @@ #include #endif /* LINUX_PAM */ +#include + #include "yppasswd.h" #include "md5.h" #include "support.h" @@ -242,7 +244,8 @@ static int check_old_password(const char *forwho, const char *newpass) return retval; } -static int save_old_password(const char *forwho, const char *oldpass, +static int save_old_password(pam_handle_t *pamh, + const char *forwho, const char *oldpass, int howmany) { static char buf[16384]; @@ -314,7 +317,7 @@ static int save_old_password(const char *forwho, const char *oldpass, fclose(opwfile); if (!found) { - pwd = getpwnam(forwho); + pwd = _pammodutil_getpwnam(pamh, forwho); if (pwd == NULL) { err = 1; } else { @@ -550,7 +553,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, return retval; } /* first, save old password */ - if (save_old_password(forwho, fromwhat, remember)) { + if (save_old_password(pamh, forwho, fromwhat, remember)) { return PAM_AUTHTOK_ERR; } @@ -762,7 +765,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, D(("prelim check")); - if (_unix_blankpasswd(ctrl, user)) { + if (_unix_blankpasswd(pamh, ctrl, user)) { return PAM_SUCCESS; } else if (off(UNIX__IAMROOT, ctrl)) { diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 3b1feb96..05c51fed 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -282,19 +282,13 @@ static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err) * - to avoid prompting for one in such cases (CG) */ -int _unix_blankpasswd(unsigned int ctrl, const char *name) +int +_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name) { struct passwd *pwd = NULL; struct spwd *spwdent = NULL; char *salt = NULL; int retval; -#if HAVE_GETPWNAM_R - char *buf = NULL; - int bufsize = 0; - struct passwd pwd_buf; - - pwd = &pwd_buf; -#endif D(("called")); @@ -310,23 +304,7 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name) /* UNIX passwords area */ /* Get password file entry... */ -#if HAVE_GETPWNAM_R - bufsize = 1024; - buf = malloc(bufsize); - - if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) { - pwd = NULL; - } - while (retval == ERANGE) { - bufsize += 1024; - buf = realloc(buf, bufsize); - if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) { - pwd = NULL; - } - } -#else - pwd = getpwnam(name); -#endif + pwd = _pammodutil_getpwnam (pamh, name); if (pwd != NULL) { if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) @@ -344,15 +322,11 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name) setreuid( 0, -1 ); if(setreuid( -1, pwd->pw_uid ) == -1) /* Will fail elsewhere. */ -#if HAVE_GETPWNAM_R - if (buf) - free(buf); -#endif return 0; } } - spwdent = getspnam( name ); + spwdent = _pammodutil_getspnam (pamh, name); if (save_uid == pwd->pw_uid) setreuid( save_uid, save_euid ); else { @@ -365,7 +339,7 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name) * ...and shadow password file entry for this user, * if shadowing is enabled */ - spwdent = getspnam(name); + spwdent = _pammodutil_getspnam(pamh, name); } if (spwdent) salt = x_strdup(spwdent->sp_pwdp); @@ -387,11 +361,6 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name) if (salt) _pam_delete(salt); -#if HAVE_GETPWNAM_R - if (buf) - free(buf); -#endif - return retval; } @@ -503,7 +472,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name D(("locating user's record")); /* UNIX passwords area */ - pwd = getpwnam(name); /* Get password file entry... */ + pwd = _pammodutil_getpwnam (pamh, name); /* Get password file entry... */ if (pwd != NULL) { if (strcmp( pwd->pw_passwd, "*NP*" ) == 0) @@ -524,7 +493,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name } } - spwdent = getspnam( name ); + spwdent = _pammodutil_getspnam (pamh, name); if (save_uid == pwd->pw_uid) setreuid( save_uid, save_euid ); else { @@ -537,7 +506,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name * ...and shadow password file entry for this user, * if shadowing is enabled */ - spwdent = getspnam(name); + spwdent = _pammodutil_getspnam (pamh, name); } if (spwdent) salt = x_strdup(spwdent->sp_pwdp); diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index d9212c28..7219cd99 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -133,7 +133,8 @@ extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl ,int type, const char *text); extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc, const char **argv); -extern int _unix_blankpasswd(unsigned int ctrl, const char *name); +extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl, + const char *name); extern int _unix_verify_password(pam_handle_t * pamh, const char *name ,const char *p, unsigned int ctrl); extern int _unix_read_password(pam_handle_t * pamh diff --git a/modules/pam_wheel/pam_wheel.c b/modules/pam_wheel/pam_wheel.c index 9545231b..8cd8eb31 100644 --- a/modules/pam_wheel/pam_wheel.c +++ b/modules/pam_wheel/pam_wheel.c @@ -125,7 +125,7 @@ static int perform_check(pam_handle_t *pamh, int flags, int ctrl, } /* su to a uid 0 account ? */ - pwd = getpwnam(username); + pwd = _pammodutil_getpwnam (pamh, username); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_NOTICE,"unknown user %s",username); @@ -134,7 +134,7 @@ static int perform_check(pam_handle_t *pamh, int flags, int ctrl, } if (ctrl & PAM_USE_UID_ARG) { - tpwd = getpwuid(getuid()); + tpwd = _pammodutil_getpwuid (pamh, getuid()); if (!tpwd) { if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_NOTICE, "who is running me ?!"); @@ -145,7 +145,7 @@ static int perform_check(pam_handle_t *pamh, int flags, int ctrl, } else { fromsu = _pammodutil_getlogin(pamh); if (fromsu) { - tpwd = getpwnam(fromsu); + tpwd = _pammodutil_getpwnam (pamh, fromsu); } if (!fromsu || !tpwd) { if (ctrl & PAM_DEBUG_ARG) { @@ -160,11 +160,11 @@ static int perform_check(pam_handle_t *pamh, int flags, int ctrl, */ if (!use_group[0]) { - if ((grp = getgrnam("wheel")) == NULL) { - grp = getgrgid(0); + if ((grp = _pammodutil_getgrnam (pamh, "wheel")) == NULL) { + grp = _pammodutil_getgrgid (pamh, 0); } } else { - grp = getgrnam(use_group); + grp = _pammodutil_getgrnam (pamh, use_group); } if (!grp || (!grp->gr_mem && (tpwd->pw_gid != grp->gr_gid))) { diff --git a/modules/pammodutil/Makefile b/modules/pammodutil/Makefile index c1f1b9a7..c9cd0062 100644 --- a/modules/pammodutil/Makefile +++ b/modules/pammodutil/Makefile @@ -19,7 +19,8 @@ CFLAGS += $(PIC) $(STATIC) $(MOREFLAGS) \ # all the object files we care about LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o \ - modutil_getlogin.o modutil_ioloop.o + modutil_getspnam.o modutil_getgrnam.o modutil_getgrgid.o \ + modutil_ingroup.o modutil_getlogin.o modutil_ioloop.o # static library name LIBSTATIC = $(LIBNAME).a diff --git a/modules/pammodutil/include/security/_pam_modutil.h b/modules/pammodutil/include/security/_pam_modutil.h index 5b95e279..c2ac24c2 100644 --- a/modules/pammodutil/include/security/_pam_modutil.h +++ b/modules/pammodutil/include/security/_pam_modutil.h @@ -19,6 +19,8 @@ */ #include +#include +#include #include extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, @@ -27,6 +29,31 @@ extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, extern struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid); +extern struct group *_pammodutil_getgrnam(pam_handle_t *pamh, + const char *group); + +extern struct group *_pammodutil_getgrgid(pam_handle_t *pamh, + gid_t gid); + +extern struct spwd *_pammodutil_getspnam(pam_handle_t *pamh, + const char *user); + +extern int _pammodutil_user_in_group_nam_nam(pam_handle_t *pamh, + const char *user, + const char *group); + +extern int _pammodutil_user_in_group_nam_gid(pam_handle_t *pamh, + const char *user, + gid_t group); + +extern int _pammodutil_user_in_group_uid_nam(pam_handle_t *pamh, + uid_t user, + const char *group); + +extern int _pammodutil_user_in_group_uid_gid(pam_handle_t *pamh, + uid_t user, + gid_t group); + extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data, int error_status); diff --git a/modules/pammodutil/modutil_getpwnam.c b/modules/pammodutil/modutil_getpwnam.c index 287dc065..891b0b58 100644 --- a/modules/pammodutil/modutil_getpwnam.c +++ b/modules/pammodutil/modutil_getpwnam.c @@ -9,9 +9,32 @@ #include "pammodutil.h" +#include +#include #include +#include #include +static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER; +static void _pammodutil_lock(void) +{ + pthread_mutex_lock(&_pammodutil_mutex); +} +static void _pammodutil_unlock(void) +{ + pthread_mutex_unlock(&_pammodutil_mutex); +} + +static int intlen(int number) +{ + int len = 2; + while (number != 0) { + number /= 10; + len++; + } + return len; +} + struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user) { #ifdef HAVE_GETPWNAM_R @@ -41,9 +64,40 @@ struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user) status = getpwnam_r(user, buffer, sizeof(struct passwd) + (char *) buffer, length, &result); - if (!status && result) { - status = pam_set_data(pamh, "_pammodutil_getpwnam", result, - _pammodutil_cleanup); + if (!status && (result == buffer)) { + char *data_name; + const void *ignore; + int i; + + data_name = malloc(strlen("_pammodutil_getpwnam") + 1 + + strlen(user) + 1 + intlen(INT_MAX) + 1); + if ((pamh != NULL) && (data_name == NULL)) { + D(("was unable to register the data item [%s]", + pam_strerror(pamh, status))); + free(buffer); + return NULL; + } + + if (pamh != NULL) { + for (i = 0; i < INT_MAX; i++) { + sprintf(data_name, "_pammodutil_getpwnam_%s_%d", user, i); + _pammodutil_lock(); + status = PAM_NO_MODULE_DATA; + if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) { + status = pam_set_data(pamh, data_name, + result, _pammodutil_cleanup); + } + _pammodutil_unlock(); + if (status == PAM_SUCCESS) { + break; + } + } + } else { + status = PAM_SUCCESS; + } + + free(data_name); + if (status == PAM_SUCCESS) { D(("success")); return result; diff --git a/modules/pammodutil/modutil_getpwuid.c b/modules/pammodutil/modutil_getpwuid.c index e200dd1e..f28ed4e4 100644 --- a/modules/pammodutil/modutil_getpwuid.c +++ b/modules/pammodutil/modutil_getpwuid.c @@ -9,12 +9,45 @@ #include "pammodutil.h" +#include +#include #include +#include #include +static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER; +static void _pammodutil_lock(void) +{ + pthread_mutex_lock(&_pammodutil_mutex); +} +static void _pammodutil_unlock(void) +{ + pthread_mutex_unlock(&_pammodutil_mutex); +} + +static int intlen(int number) +{ + int len = 2; + while (number != 0) { + number /= 10; + len++; + } + return len; +} + +static int longlen(long number) +{ + int len = 2; + while (number != 0) { + number /= 10; + len++; + } + return len; +} + struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid) { -#ifdef HAVE_GETPWNAM_R +#ifdef HAVE_GETPWUID_R void *buffer=NULL; size_t length = PWD_INITIAL_LENGTH; @@ -41,9 +74,41 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid) status = getpwuid_r(uid, buffer, sizeof(struct passwd) + (char *) buffer, length, &result); - if (!status && result) { - status = pam_set_data(pamh, "_pammodutil_getpwuid", result, - _pammodutil_cleanup); + if (!status && (result == buffer)) { + char *data_name; + const void *ignore; + int i; + + data_name = malloc(strlen("_pammodutil_getpwuid") + 1 + + longlen((long) uid) + 1 + intlen(INT_MAX) + 1); + if ((pamh != NULL) && (data_name == NULL)) { + D(("was unable to register the data item [%s]", + pam_strerror(pamh, status))); + free(buffer); + return NULL; + } + + if (pamh != NULL) { + for (i = 0; i < INT_MAX; i++) { + sprintf(data_name, "_pammodutil_getpwuid_%ld_%d", + (long) uid, i); + _pammodutil_lock(); + status = PAM_NO_MODULE_DATA; + if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) { + status = pam_set_data(pamh, data_name, + result, _pammodutil_cleanup); + } + _pammodutil_unlock(); + if (status == PAM_SUCCESS) { + break; + } + } + } else { + status = PAM_SUCCESS; + } + + free(data_name); + if (status == PAM_SUCCESS) { D(("success")); return result; @@ -67,14 +132,14 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid) free(buffer); return NULL; -#else /* ie. ifndef HAVE_GETPWNAM_R */ +#else /* ie. ifndef HAVE_GETPWUID_R */ /* * Sorry, there does not appear to be a reentrant version of - * getpwnam(). So, we use the standard libc function. + * getpwuid(). So, we use the standard libc function. */ return getpwuid(uid); -#endif /* def HAVE_GETPWNAM_R */ +#endif /* def HAVE_GETPWUID_R */ } -- 2.40.0