]> granicus.if.org Git - linux-pam/blobdiff - modules/pammodutil/modutil_getpwuid.c
Relevant BUGIDs:
[linux-pam] / modules / pammodutil / modutil_getpwuid.c
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 */
 }