From 328d7328e5b4ea8d60164ce874bada2f4f58a201 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 24 Sep 2004 13:14:14 +0000 Subject: Relevant BUGIDs: Purpose of commit: Commit summary: --------------- bugfix: Add missing files --- modules/pammodutil/modutil_getgrgid.c | 145 ++++++++++++++++++++++++++++++++++ modules/pammodutil/modutil_getgrnam.c | 134 +++++++++++++++++++++++++++++++ modules/pammodutil/modutil_getspnam.c | 134 +++++++++++++++++++++++++++++++ modules/pammodutil/modutil_ingroup.c | 121 ++++++++++++++++++++++++++++ 4 files changed, 534 insertions(+) create mode 100644 modules/pammodutil/modutil_getgrgid.c create mode 100644 modules/pammodutil/modutil_getgrnam.c create mode 100644 modules/pammodutil/modutil_getspnam.c create mode 100644 modules/pammodutil/modutil_ingroup.c (limited to 'modules/pammodutil') diff --git a/modules/pammodutil/modutil_getgrgid.c b/modules/pammodutil/modutil_getgrgid.c new file mode 100644 index 00000000..dcac4f78 --- /dev/null +++ b/modules/pammodutil/modutil_getgrgid.c @@ -0,0 +1,145 @@ +/* + * $Id$ + * + * 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 +#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 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 passwd) + 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 */ + 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; + + } + + length <<= 1; + + } 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/modules/pammodutil/modutil_getgrnam.c b/modules/pammodutil/modutil_getgrnam.c new file mode 100644 index 00000000..7e2d43ff --- /dev/null +++ b/modules/pammodutil/modutil_getgrnam.c @@ -0,0 +1,134 @@ +/* + * $Id$ + * + * 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 +#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 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 passwd) + 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 */ + 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; + + } + + length <<= 1; + + } 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/modules/pammodutil/modutil_getspnam.c b/modules/pammodutil/modutil_getspnam.c new file mode 100644 index 00000000..325cfd33 --- /dev/null +++ b/modules/pammodutil/modutil_getspnam.c @@ -0,0 +1,134 @@ +/* + * $Id$ + * + * 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 +#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 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 */ + 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; + + } + + length <<= 1; + + } 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/modules/pammodutil/modutil_ingroup.c b/modules/pammodutil/modutil_ingroup.c new file mode 100644 index 00000000..5a3b5d8d --- /dev/null +++ b/modules/pammodutil/modutil_ingroup.c @@ -0,0 +1,121 @@ +/* + * $Id$ + * + * 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 +#include + +#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); +} -- cgit v1.2.3