]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs:
authorThorsten Kukuk <kukuk@thkukuk.de>
Fri, 24 Sep 2004 13:13:18 +0000 (13:13 +0000)
committerThorsten Kukuk <kukuk@thkukuk.de>
Fri, 24 Sep 2004 13:13:18 +0000 (13:13 +0000)
Purpose of commit:

Commit summary:
---------------

bugfix: 440107: Add various patches from Linux Distibutors to make
PAM modules reentrant.

28 files changed:
CHANGELOG
_pam_aconf.h.in
configure
configure.in
modules/pam_access/pam_access.c
modules/pam_group/pam_group.c
modules/pam_lastlog/pam_lastlog.c
modules/pam_limits/pam_limits.c
modules/pam_listfile/pam_listfile.c
modules/pam_mail/pam_mail.c
modules/pam_mkhomedir/pam_mkhomedir.c
modules/pam_rhosts/pam_rhosts_auth.c
modules/pam_securetty/pam_securetty.c
modules/pam_shells/pam_shells.c
modules/pam_succeed_if/pam_succeed_if.c
modules/pam_tally/Makefile
modules/pam_tally/pam_tally.c
modules/pam_unix/Makefile
modules/pam_unix/pam_unix_acct.c
modules/pam_unix/pam_unix_auth.c
modules/pam_unix/pam_unix_passwd.c
modules/pam_unix/support.c
modules/pam_unix/support.h
modules/pam_wheel/pam_wheel.c
modules/pammodutil/Makefile
modules/pammodutil/include/security/_pam_modutil.h
modules/pammodutil/modutil_getpwnam.c
modules/pammodutil/modutil_getpwuid.c

index 33e26f0eaf31620abd3b51a7d351f0bcfd38e208..377d80bc6b45d1737b99830d249a304bb75b6145 100644 (file)
--- 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
 
index 99294d63efb80abbf92dd02d123045359060c583..1b1cde9581580ca6d1ba15be47d15b45afc245ce 100644 (file)
 
 /* 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
index 663c25a0bb1fdd9b7d213335917ca12d55b392e8..555f16a78976dfb95881ed4f8ddae90889cefb93 100755 (executable)
--- 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
index 09a345fe61bc49f2f69977f7952816885ffb7afe..73734335cfda582ff802e47676ff356f3bcd7f2f 100644 (file)
@@ -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)
index 031b94ba2cf07cd13984c3bc1e656e99205043d5..42e03527fa2e5be7dd110bc5178a37809a4c82ae 100644 (file)
@@ -59,6 +59,7 @@
 
 #include <security/_pam_macros.h>
 #include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
 
 /* 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);
index 4b42506c62011bc8500e96b1168bb821908e6445..e07a932e8df3265f044111e17c93f8db1d1e9ba1 100644 (file)
@@ -57,6 +57,7 @@ typedef enum { AND, OR } operator;
 
 #include <security/pam_modules.h>
 #include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
 
 /* --- 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;
index 6e53c24429d5900c4cd65845d4f19ba6128ae543..e9eeac4ef1c95a9e0666663d6f48e1c7b8bbe500 100644 (file)
@@ -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;
index 536446bd11a40b6344374e3ea18c0f39520db731..4354d3e1239ac959c14602eae3773089da9b4b5a 100644 (file)
@@ -90,6 +90,7 @@ struct pam_limit_s {
 
 #include <security/pam_modules.h>
 #include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
 
 /* 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 '<domain> -' 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;
     }
index bc677be3677b3debc9bbaa37b7e1e06a375efa8c..0ce3e0b1a755abcb39890d15cf800f5262dbe261 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <security/pam_modules.h>
 #include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
 
 /* 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);
index 4888a1a5fe27737d9e496ec1b35f8f18c7078df1..6cd173b4c896f8f08c13e131e7d24a4ef138cec2 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <security/pam_modules.h>
 #include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
 
 /* 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);
index 11180444332c18f1b701c2d7379f29ce2a85d76e..6814056f007682792617a1d7a066cd057d9766a9 100644 (file)
@@ -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));
index 95a1aad3b01ea287dcc93193026dd063ee06910a..374318dcc777293475a3dd7505239c96f58f10a0 100644 (file)
@@ -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)) {
index 274b3b7439e05e4b78215dc37d8b1d765d94a25a..8abbcb9438210c31f1c644c6c3793d922ab91c87 100644 (file)
@@ -34,6 +34,7 @@
 #define PAM_SM_ACCOUNT
 
 #include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
 
 /* 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,
index c9e2ed6c9187fcdb752c9644471b9d45d498e4db..64359eac911e383bbbe7006047b80100f62e7bf3 100644 (file)
@@ -15,6 +15,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <syslog.h>
 #include <unistd.h>
@@ -30,6 +31,7 @@
 #define PAM_SM_ACCOUNT
 
 #include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
 
 /* 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 */
     }
index 82491b6ef48795ad72101d228918cf457f28d0be..23974afa412f452a637d9904627e271b35d47cb5 100644 (file)
@@ -37,6 +37,8 @@
  *
  */
 
+#define _GNU_SOURCE
+
 #include <sys/types.h>
 #include <errno.h>
 #include <fcntl.h>
index c39970ddf815ad0cc9407d3de7916307b3c1e1cf..718d3b3052e08c8309f128836fdd8194568d1465 100644 (file)
@@ -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
 
index 27fe0b37dcaa57102140a4c04f02e2002eda2cda..341f448ea4295c078690ec14380df77165612f6c 100644 (file)
@@ -49,6 +49,7 @@
 /* #define PAM_SM_PASSWORD */
 
 #include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
 
 /*---------------------------------------------------------------------*/
 
@@ -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;
     }
index 61c4beaad6d3b2f227df7c3b79e56500caa9beb1..3fe0e8ae0bb58c927db413345b217d5c8b825d86 100644 (file)
@@ -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
index 58ba93c1e5cde3df15c7287708ae630b6f2eb734..f87b13b145fae6ab5aa358815303dbb1c67bac05 100644 (file)
@@ -53,6 +53,7 @@
 #define PAM_SM_ACCOUNT
 
 #include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
 
 #ifndef LINUX_PAM
 #include <security/pam_appl.h>
@@ -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;
        }
index a0c1da815f1f6b29df9276ec7b802775ef366f81..39e0cde539dbb9d335fbffb603c1e5a023fd3ed9 100644 (file)
@@ -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;
index 4320171ca341354c92b6c3c6d05dba9112b6b3be..f11d2b206d493ba515b34eb885132d38fb410a8a 100644 (file)
@@ -73,6 +73,8 @@
 #include <security/pam_appl.h>
 #endif                         /* LINUX_PAM */
 
+#include <security/_pam_modutil.h>
+
 #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)) {
 
index 3b1feb96464d86f8f27c78f9cb4851aa8f41eeff..05c51fed10bab38cb440083641489a783a3f0c7b 100644 (file)
@@ -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);
index d9212c28f9bcb833984657b2b04fc53ac67b0c7c..7219cd99bd103c0d7760d1434eddb4af548dd2df 100644 (file)
@@ -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
index 9545231b63680b377ea64c6fcb2fea0c5f47260a..8cd8eb3135a33f9fad4cc378b5dddd832c7ba413 100644 (file)
@@ -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))) {
index c1f1b9a781d4b88c7b53fc51faaa12875a787f1a..c9cd0062ddd1eff544a2ba331cf89c5cdcadb123 100644 (file)
@@ -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
index 5b95e279af6ebf46bc052010c220e8c1d888f45d..c2ac24c2975c6d5a11cdbc763239651310073d82 100644 (file)
@@ -19,6 +19,8 @@
  */
 
 #include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
 #include <sys/types.h>
 
 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);
 
index 287dc0654f551f63d7b12e8d521c80ecd9f30344..891b0b58aaff9c5f57147da1aa47683ea68105fc 100644 (file)
@@ -9,9 +9,32 @@
 
 #include "pammodutil.h"
 
+#include <limits.h>
+#include <pthread.h>
 #include <pwd.h>
+#include <stdio.h>
 #include <stdlib.h>
 
+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;
index e200dd1e1350a4ac075886ab709e1e15c55e5881..f28ed4e43bc84e53532208b9345048c6cf306005 100644 (file)
@@ -9,12 +9,45 @@
 
 #include "pammodutil.h"
 
+#include <limits.h>
+#include <pthread.h>
 #include <pwd.h>
+#include <stdio.h>
 #include <stdlib.h>
 
+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 */
 }