aboutsummaryrefslogtreecommitdiff
path: root/Linux-PAM/modules/pammodutil
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 12:47:05 -0800
committerSteve Langasek <steve.langasek@ubuntu.com>2019-01-03 12:47:05 -0800
commit4c51da22e068907adb7857d50f5109a467c94d7c (patch)
treebecf5fbae5dfcbe8896355f59042dc8eaefa7f37 /Linux-PAM/modules/pammodutil
parentefd31890b5ed496a5a00c08a262da240e66a4ddc (diff)
parentab9e8ba11f464fc083fc65a0bc695d60ebc86f3e (diff)
downloadpam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.gz
pam-4c51da22e068907adb7857d50f5109a467c94d7c.tar.bz2
pam-4c51da22e068907adb7857d50f5109a467c94d7c.zip
New upstream version 0.79
Diffstat (limited to 'Linux-PAM/modules/pammodutil')
-rw-r--r--Linux-PAM/modules/pammodutil/Makefile6
-rw-r--r--Linux-PAM/modules/pammodutil/README2
-rw-r--r--Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h37
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_cleanup.c2
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getgrgid.c150
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getgrnam.c139
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getlogin.c72
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getpwnam.c71
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getpwuid.c90
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getspnam.c139
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_ingroup.c121
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_ioloop.c52
-rw-r--r--Linux-PAM/modules/pammodutil/pammodutil.h4
13 files changed, 861 insertions, 24 deletions
diff --git a/Linux-PAM/modules/pammodutil/Makefile b/Linux-PAM/modules/pammodutil/Makefile
index 03334326..bad1bf62 100644
--- a/Linux-PAM/modules/pammodutil/Makefile
+++ b/Linux-PAM/modules/pammodutil/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+# $Id: Makefile,v 1.4 2004/09/24 13:13:22 kukuk Exp $
#
#
@@ -18,7 +18,9 @@ CFLAGS += $(PIC) $(STATIC) $(MOREFLAGS) \
-DLIBPAM_VERSION_MINOR=$(MINOR_REL)
# all the object files we care about
-LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o
+LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.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/Linux-PAM/modules/pammodutil/README b/Linux-PAM/modules/pammodutil/README
index bd957247..ea44f310 100644
--- a/Linux-PAM/modules/pammodutil/README
+++ b/Linux-PAM/modules/pammodutil/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+$Id: README,v 1.1 2001/12/09 22:15:12 agmorgan Exp $
This is a libarary of routines for use by modules. The routines seem
to have a common use for modules, but are not part of libpam and never
diff --git a/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h b/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
index d36fcfa0..ec0c8964 100644
--- a/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
+++ b/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
@@ -2,7 +2,7 @@
#define _PAM_MODUTIL_H
/*
- * $Id: _pam_modutil.h,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: _pam_modutil.h,v 1.4 2004/09/24 13:13:22 kukuk Exp $
*
* This file is a list of handy libc wrappers that attempt to provide some
* thread-safe and other convenient functionality to modules in a form that
@@ -15,10 +15,12 @@
* On systems that simply can't support thread safe programming, these
* functions don't support it either - sorry.
*
- * Copyright (c) 2001 Andrew Morgan <morgan@kernel.org>
+ * Copyright (c) 2001-2002 Andrew Morgan <morgan@kernel.org>
*/
#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
#include <sys/types.h>
extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh,
@@ -27,7 +29,38 @@ 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);
+extern const char *_pammodutil_getlogin(pam_handle_t *pamh);
+
+extern int _pammodutil_read(int fd, char *buffer, int count);
+
+extern int _pammodutil_write(int fd, const char *buffer, int count);
+
#endif /* _PAM_MODUTIL_H */
diff --git a/Linux-PAM/modules/pammodutil/modutil_cleanup.c b/Linux-PAM/modules/pammodutil/modutil_cleanup.c
index 76662133..5477481f 100644
--- a/Linux-PAM/modules/pammodutil/modutil_cleanup.c
+++ b/Linux-PAM/modules/pammodutil/modutil_cleanup.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_cleanup.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_cleanup.c,v 1.1 2001/12/09 22:15:12 agmorgan Exp $
*
* This function provides a common pam_set_data() friendly version of free().
*/
diff --git a/Linux-PAM/modules/pammodutil/modutil_getgrgid.c b/Linux-PAM/modules/pammodutil/modutil_getgrgid.c
new file mode 100644
index 00000000..f97a9239
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getgrgid.c
@@ -0,0 +1,150 @@
+/*
+ * $Id: modutil_getgrgid.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getgrgid() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <grp.h>
+#include <pthread.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 group *_pammodutil_getgrgid(pam_handle_t *pamh, gid_t gid)
+{
+#ifdef HAVE_GETGRGID_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct group *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct group) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the user - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the grp structure */
+ errno = 0;
+ status = getgrgid_r(gid, buffer,
+ sizeof(struct group) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getgrgid") + 1 +
+ longlen((long)gid) + 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_getgrgid_%ld_%d",
+ (long) gid, 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;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("grp structure took %u bytes or so of memory",
+ length+sizeof(struct group)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETGRGID_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getgrgid(). So, we use the standard libc function.
+ */
+
+ return getgrgid(gid);
+
+#endif /* def HAVE_GETGRGID_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getgrnam.c b/Linux-PAM/modules/pammodutil/modutil_getgrnam.c
new file mode 100644
index 00000000..0727618c
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getgrnam.c
@@ -0,0 +1,139 @@
+/*
+ * $Id: modutil_getgrnam.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getgrnam() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <grp.h>
+#include <pthread.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 group *_pammodutil_getgrnam(pam_handle_t *pamh, const char *group)
+{
+#ifdef HAVE_GETGRNAM_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct group *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct group) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the group - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the grp structure */
+ errno = 0;
+ status = getgrnam_r(group, buffer,
+ sizeof(struct group) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getgrnam") + 1 +
+ strlen(group) + 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_getgrnam_%s_%d", group, 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;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("grp structure took %u bytes or so of memory",
+ length+sizeof(struct group)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETGRNAM_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getgrnam(). So, we use the standard libc function.
+ */
+
+ return getgrnam(group);
+
+#endif /* def HAVE_GETGRNAM_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getlogin.c b/Linux-PAM/modules/pammodutil/modutil_getlogin.c
new file mode 100644
index 00000000..0e4a48d8
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getlogin.c
@@ -0,0 +1,72 @@
+/*
+ * $Id: modutil_getlogin.c,v 1.4 2004/11/08 10:57:15 t8m Exp $
+ *
+ * A central point for invoking getlogin(). Hopefully, this is a
+ * little harder to spoof than all the other versions that are out
+ * there.
+ */
+
+#include "pammodutil.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <utmp.h>
+
+#define _PAMMODUTIL_GETLOGIN "_pammodutil_getlogin"
+
+const char *_pammodutil_getlogin(pam_handle_t *pamh)
+{
+ int status;
+ char *logname;
+ const char *curr_tty;
+ char *curr_user;
+ struct utmp *ut, line;
+
+ status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN,
+ (const void **) &logname);
+ if (status == PAM_SUCCESS) {
+ return logname;
+ }
+
+ status = pam_get_item(pamh, PAM_TTY, (const void **) &curr_tty);
+ if ((status != PAM_SUCCESS) || (curr_tty == NULL)) {
+ curr_tty = ttyname(0);
+ }
+
+ if ((curr_tty == NULL) || memcmp(curr_tty, "/dev/", 5)) {
+ return NULL;
+ }
+
+ curr_tty += 5; /* strlen("/dev/") */
+ logname = NULL;
+
+ setutent();
+ strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
+
+ if ((ut = getutline(&line)) == NULL) {
+ goto clean_up_and_go_home;
+ }
+
+ curr_user = calloc(sizeof(line.ut_user)+1, 1);
+ if (curr_user == NULL) {
+ goto clean_up_and_go_home;
+ }
+
+ strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
+ /* calloc already zeroed the memory */
+
+ status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
+ _pammodutil_cleanup);
+ if (status != PAM_SUCCESS) {
+ free(curr_user);
+ goto clean_up_and_go_home;
+ }
+
+ logname = curr_user;
+
+clean_up_and_go_home:
+
+ endutent();
+
+ return logname;
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getpwnam.c b/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
index e3a8f270..eb359544 100644
--- a/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
+++ b/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_getpwnam.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_getpwnam.c,v 1.4 2005/03/30 14:59:41 kukuk Exp $
*
* This function provides a thread safer version of getpwnam() for use
* with PAM modules that care about this sort of thing.
@@ -9,9 +9,33 @@
#include "pammodutil.h"
+#include <errno.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
@@ -38,12 +62,44 @@ struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
buffer = new_buffer;
/* make the re-entrant call to get the pwd structure */
+ errno = 0;
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;
@@ -55,9 +111,12 @@ struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
free(buffer);
return NULL;
- }
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
- length <<= 1;
+ length <<= 2;
} while (length < PWD_ABSURD_PWD_LENGTH);
diff --git a/Linux-PAM/modules/pammodutil/modutil_getpwuid.c b/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
index cd93ded4..8ba20d17 100644
--- a/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
+++ b/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_getpwuid.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_getpwuid.c,v 1.4 2005/03/30 14:59:41 kukuk Exp $
*
* This function provides a thread safer version of getpwuid() for use
* with PAM modules that care about this sort of thing.
@@ -9,12 +9,46 @@
#include "pammodutil.h"
+#include <errno.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;
@@ -38,12 +72,45 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
buffer = new_buffer;
/* make the re-entrant call to get the pwd structure */
+ errno = 0;
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;
@@ -55,9 +122,12 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
free(buffer);
return NULL;
- }
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
- length <<= 1;
+ length <<= 2;
} while (length < PWD_ABSURD_PWD_LENGTH);
@@ -67,14 +137,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 */
}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getspnam.c b/Linux-PAM/modules/pammodutil/modutil_getspnam.c
new file mode 100644
index 00000000..e966bb52
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getspnam.c
@@ -0,0 +1,139 @@
+/*
+ * $Id: modutil_getspnam.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getspnam() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <shadow.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 spwd *_pammodutil_getspnam(pam_handle_t *pamh, const char *user)
+{
+#ifdef HAVE_GETSPNAM_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct spwd *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct spwd) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the user - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the spwd structure */
+ errno = 0;
+ status = getspnam_r(user, buffer,
+ sizeof(struct spwd) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getspnam") + 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_getspnam_%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;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("spwd structure took %u bytes or so of memory",
+ length+sizeof(struct spwd)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETSPNAM_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getspnam(). So, we use the standard libc function.
+ */
+
+ return getspnam(user);
+
+#endif /* def HAVE_GETSPNAM_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_ingroup.c b/Linux-PAM/modules/pammodutil/modutil_ingroup.c
new file mode 100644
index 00000000..e1f88b81
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_ingroup.c
@@ -0,0 +1,121 @@
+/*
+ * $Id: modutil_ingroup.c,v 1.1 2004/09/24 13:14:14 kukuk Exp $
+ *
+ * This function provides common methods for checking if a user is in a
+ * specified group.
+ */
+
+#include "pammodutil.h"
+#include "include/security/_pam_modutil.h"
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef HAVE_GETGROUPLIST
+static int checkgrouplist(const char *user, gid_t primary, gid_t target)
+{
+ gid_t *grouplist = NULL;
+ int agroups, ngroups, i;
+ ngroups = agroups = 3;
+ do {
+ grouplist = malloc(sizeof(gid_t) * agroups);
+ if (grouplist == NULL) {
+ return 0;
+ }
+ ngroups = agroups;
+ i = getgrouplist(user, primary, grouplist, &ngroups);
+ if ((i < 0) || (ngroups < 1)) {
+ agroups *= 2;
+ free(grouplist);
+ } else {
+ for (i = 0; i < ngroups; i++) {
+ if (grouplist[i] == target) {
+ free(grouplist);
+ return 1;
+ }
+ }
+ free(grouplist);
+ }
+ } while (((i < 0) || (ngroups < 1)) && (agroups < 10000));
+ return 0;
+}
+#endif
+
+static int _pammodutil_user_in_group_common(pam_handle_t *pamh,
+ struct passwd *pwd,
+ struct group *grp)
+{
+ int i;
+
+ if (pwd == NULL) {
+ return 0;
+ }
+ if (grp == NULL) {
+ return 0;
+ }
+
+ if (pwd->pw_gid == grp->gr_gid) {
+ return 1;
+ }
+
+ for (i = 0; (grp->gr_mem != NULL) && (grp->gr_mem[i] != NULL); i++) {
+ if (strcmp(pwd->pw_name, grp->gr_mem[i]) == 0) {
+ return 1;
+ }
+ }
+
+#ifdef HAVE_GETGROUPLIST
+ if (checkgrouplist(pwd->pw_name, pwd->pw_gid, grp->gr_gid)) {
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+int _pammodutil_user_in_group_nam_nam(pam_handle_t *pamh,
+ const char *user, const char *group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwnam(pamh, user);
+ grp = _pammodutil_getgrnam(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_nam_gid(pam_handle_t *pamh,
+ const char *user, gid_t group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwnam(pamh, user);
+ grp = _pammodutil_getgrgid(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_uid_nam(pam_handle_t *pamh,
+ uid_t user, const char *group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwuid(pamh, user);
+ grp = _pammodutil_getgrnam(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_uid_gid(pam_handle_t *pamh,
+ uid_t user, gid_t group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwuid(pamh, user);
+ grp = _pammodutil_getgrgid(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_ioloop.c b/Linux-PAM/modules/pammodutil/modutil_ioloop.c
new file mode 100644
index 00000000..37ac76fc
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_ioloop.c
@@ -0,0 +1,52 @@
+/*
+ * $Id: modutil_ioloop.c,v 1.2 2004/09/24 09:18:22 kukuk Exp $
+ *
+ * These functions provides common methods for ensure a complete read or
+ * write occurs. It handles EINTR and partial read/write returns.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <security/pam_modules.h>
+#include "include/security/_pam_modutil.h"
+
+int _pammodutil_read(int fd, char *buffer, int count)
+{
+ int block, offset = 0;
+
+ while (count > 0) {
+ block = read(fd, &buffer[offset], count);
+
+ if (block < 0) {
+ if (errno == EINTR) continue;
+ return block;
+ }
+ if (block == 0) return offset;
+
+ offset += block;
+ count -= block;
+ }
+
+ return offset;
+}
+
+int _pammodutil_write(int fd, const char *buffer, int count)
+{
+ int block, offset = 0;
+
+ while (count > 0) {
+ block = write(fd, &buffer[offset], count);
+
+ if (block < 0) {
+ if (errno == EINTR) continue;
+ return block;
+ }
+ if (block == 0) return offset;
+
+ offset += block;
+ count -= block;
+ }
+
+ return offset;
+}
diff --git a/Linux-PAM/modules/pammodutil/pammodutil.h b/Linux-PAM/modules/pammodutil/pammodutil.h
index 78d7e517..2b80c852 100644
--- a/Linux-PAM/modules/pammodutil/pammodutil.h
+++ b/Linux-PAM/modules/pammodutil/pammodutil.h
@@ -2,7 +2,7 @@
#define PAMMODUTIL_H
/*
- * $Id: pammodutil.h,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: pammodutil.h,v 1.2 2005/03/30 10:42:54 t8m Exp $
*
* Copyright (c) 2001 Andrew Morgan <morgan@kernel.org>
*/
@@ -13,7 +13,7 @@
#include <security/_pam_modutil.h>
#define PWD_INITIAL_LENGTH 0x100
-#define PWD_ABSURD_PWD_LENGTH 0x1000
+#define PWD_ABSURD_PWD_LENGTH 0x8000
/* This is a simple cleanup, it just free()s the 'data' memory */
extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data,