This builds off of the recursion checking introduced by -depth to avoid a deadlock if/when we recurse into ourselves while looking up the user's UID to compare it to the configured value. diff -ur nss_ldap-265/ldap-nss.c nss_ldap-265-2/ldap-nss.c --- nss_ldap-265/ldap-nss.c 2010-08-19 17:16:51.000000000 -0400 +++ nss_ldap-265-2/ldap-nss.c 2010-08-19 17:25:09.000000000 -0400 @@ -34,6 +34,7 @@ #endif #include <assert.h> +#include <pwd.h> #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -4356,20 +4357,55 @@ int _nss_ldap_test_initgroups_ignoreuser (const char *user) { - char **p; + char **p, *buf; + size_t buflen; + struct passwd pwd, *passwd; - if (__config == NULL) - return 0; - - if (__config->ldc_initgroups_ignoreusers == NULL) - return 0; - - for (p = __config->ldc_initgroups_ignoreusers; *p != NULL; p++) + if (__config != NULL) { - if (strcmp (*p, user) == 0) - return 1; + if (__config->ldc_initgroups_ignoreusers != NULL) + for (p = __config->ldc_initgroups_ignoreusers; *p != NULL; p++) + { + if (strcmp (*p, user) == 0) + return 1; + } + if (__config->ldc_initgroups_minimum_uid >= 0) + { + memset (&pwd, 0, sizeof(pwd)); + buflen = 0x100; + buf = malloc(buflen); + if (buf != NULL) + { + passwd = NULL; + while ((getpwnam_r(user, &pwd, buf, buflen, &passwd) != 0) && + (passwd != &pwd)) + { + switch (errno) + { + case ERANGE: + buflen *= 2; + free(buf); + if (buflen > 0x100000) + buf = NULL; + else + buf = malloc(buflen); + break; + case EINTR: + continue; + break; + default: + free(buf); + buf = NULL; + break; + } + if (buf == NULL) + break; + } + } + if ((passwd == &pwd) && (passwd->pw_uid < 1000)) + return 1; + } } - return 0; } diff -ur nss_ldap-265/ldap-nss.h nss_ldap-265-2/ldap-nss.h --- nss_ldap-265/ldap-nss.h 2010-08-19 17:16:51.000000000 -0400 +++ nss_ldap-265-2/ldap-nss.h 2010-08-19 17:18:47.000000000 -0400 @@ -400,6 +400,7 @@ time_t ldc_mtime; char **ldc_initgroups_ignoreusers; + int ldc_initgroups_minimum_uid; /* disable the do-res_init()-on-resolv.conf-changes hack */ unsigned int ldc_resolv_conf_res_init_hack; diff -ur nss_ldap-265/ldap-pwd.c nss_ldap-265-2/ldap-pwd.c --- nss_ldap-265/ldap-pwd.c 2010-08-19 17:16:51.000000000 -0400 +++ nss_ldap-265-2/ldap-pwd.c 2010-08-19 16:40:43.000000000 -0400 @@ -49,6 +49,7 @@ #include "ldap-nss.h" #include "ldap-pwd.h" #include "util.h" +#include "depth.h" #ifdef HAVE_PORT_AFTER_H #include <port_after.h> @@ -242,6 +243,10 @@ struct passwd * result, char *buffer, size_t buflen, int *errnop) { +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif LOOKUP_NAME (name, result, buffer, buflen, errnop, _nss_ldap_filt_getpwnam, LM_PASSWD, _nss_ldap_parse_pw, LDAP_NSS_BUFLEN_DEFAULT); } @@ -261,6 +266,10 @@ struct passwd *result, char *buffer, size_t buflen, int *errnop) { +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif LOOKUP_NUMBER (uid, result, buffer, buflen, errnop, _nss_ldap_filt_getpwuid, LM_PASSWD, _nss_ldap_parse_pw, LDAP_NSS_BUFLEN_DEFAULT); } diff -ur nss_ldap-265/nss_ldap.5 nss_ldap-265-2/nss_ldap.5 --- nss_ldap-265/nss_ldap.5 2010-08-19 17:16:51.000000000 -0400 +++ nss_ldap-265-2/nss_ldap.5 2010-08-19 17:19:23.000000000 -0400 @@ -445,6 +445,14 @@ to return NSS_STATUS_NOTFOUND if called with a listed users as its argument. .TP +.B nss_initgroups_minimum_uid <uid> +This option directs the +.B nss_ldap +implementation of +.BR initgroups(3) +to return NSS_STATUS_NOTFOUND if called with a user whose UID is +below the value given as the argument. +.TP .B nss_getgrent_skipmembers <yes|no> Specifies whether or not to populate the members list in the group structure for group lookups. If very large groups diff -ur nss_ldap-265/util.c nss_ldap-265-2/util.c --- nss_ldap-265/util.c 2010-08-19 17:16:51.000000000 -0400 +++ nss_ldap-265-2/util.c 2010-08-19 17:18:33.000000000 -0400 @@ -669,6 +669,7 @@ result->ldc_reconnect_maxsleeptime = LDAP_NSS_MAXSLEEPTIME; result->ldc_reconnect_maxconntries = LDAP_NSS_MAXCONNTRIES; result->ldc_initgroups_ignoreusers = NULL; + result->ldc_initgroups_minimum_uid = -1; for (i = 0; i <= LM_NONE; i++) { @@ -1180,6 +1181,10 @@ break; } } + else if (!strcasecmp (k, NSS_LDAP_KEY_INITGROUPS_MINIMUM_UID)) + { + result->ldc_initgroups_minimum_uid = atoi(v); + } else if (!strcasecmp (k, NSS_LDAP_KEY_GETGRENT_SKIPMEMBERS)) { if (!strcasecmp (v, "on") || !strcasecmp (v, "yes") diff -ur nss_ldap-265/util.h nss_ldap-265-2/util.h --- nss_ldap-265/util.h 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265-2/util.h 2010-08-19 17:19:46.000000000 -0400 @@ -92,6 +92,7 @@ #define NSS_LDAP_KEY_PAGESIZE "pagesize" #define NSS_LDAP_KEY_INITGROUPS "nss_initgroups" #define NSS_LDAP_KEY_INITGROUPS_IGNOREUSERS "nss_initgroups_ignoreusers" +#define NSS_LDAP_KEY_INITGROUPS_MINIMUM_UID "nss_initgroups_minimum_uid" #define NSS_LDAP_KEY_GETGRENT_SKIPMEMBERS "nss_getgrent_skipmembers" /* more reconnect policy fine-tuning */