summaryrefslogtreecommitdiff
path: root/modules/pammodutil/modutil_getpwuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pammodutil/modutil_getpwuid.c')
-rw-r--r--modules/pammodutil/modutil_getpwuid.c79
1 files changed, 72 insertions, 7 deletions
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 <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 */
}