diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | nis/libnsl.h | 3 | ||||
-rw-r--r-- | nis/nss | 11 | ||||
-rw-r--r-- | nis/nss-default.c | 5 | ||||
-rw-r--r-- | nis/nss_nis/nis-pwd.c | 51 | ||||
-rw-r--r-- | nis/nss_nis/nis-spwd.c | 79 |
7 files changed, 132 insertions, 49 deletions
@@ -1,3 +1,25 @@ +2010-04-07 Ulrich Drepper <drepper@redhat.com> + + [BZ #11134] + * nis/libnsl.h (NSS_FLAG_ADJUNCT_AS_SHADOW): Define. + * nis/nss: Document new ADJUNCT_AS_SHADOW variable. + * nis/nss-default.c: Handle ADJUNCT_AS_SHADOW variable. + * nis/nss_nis/nis-pwd.c (internal_nis_endpwent): Minor cleanups. + (internal_nis_getpwent_r): Don't fill in password from adjunct table + if NSS_FLAG_ADJUNCT_AS_SHADOW is set. + (_nss_nis_getpwnam_r): Likewise. + (_nss_nis_getpwuid_r): Likewise. + * nis/nss_nis/nis-spwd.c (ent_adjunct_used): Nee global variable. + (_nss_nis_setspent): Also reset ent_adjunct_used. + (internal_nis_getspent_r): If new_start is set and shadow.byname table + does not exist and NSS_FLAG_ADJUNCT_AS_SHADOW is set, try to get + passwd.adjunct.byname table. If new_start is not set get next entry + from the initially used table. Synthesize shadow.byname table if + necessary by adding two empty fields. + (_nss_nis_getspnam_r): If shadow.byname table does not exist and + NSS_FLAG_ADJUNCT_AS_SHADOW is set, try to get passwd.adjunct.byname + table and synthesize shadow.byname table. + 2010-04-06 H.J. Lu <hongjiu.lu@intel.com> * Makerules (libc-abis): Add $(..) to libc-abis. @@ -1,5 +1,5 @@ -GNU C Library NEWS -- history of user-visible changes. 2009-12-8 -Copyright (C) 1992-2008, 2009 Free Software Foundation, Inc. +GNU C Library NEWS -- history of user-visible changes. 2010-4-7 +Copyright (C) 1992-2009, 2010 Free Software Foundation, Inc. See the end for copying conditions. Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/> @@ -9,6 +9,12 @@ Version 2.12 * New Linux interface: recvmmsg +* New NIS mode selector ADJUNCT_AS_SHADOW. The passwd.adjunct.byname table + will not be used to fill in password fields in the passwd.byname replies. + Instead it is used to synthesize the shadow.byname table, should it be + missing. This is a useful mode in some installations involving Solaris. + Implemented by Ulrich Drepper. + Version 2.11 diff --git a/nis/libnsl.h b/nis/libnsl.h index c6ceb32..dc15930 100644 --- a/nis/libnsl.h +++ b/nis/libnsl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2005, 2006, 2010 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -21,6 +21,7 @@ #define NSS_FLAG_NETID_AUTHORITATIVE 1 #define NSS_FLAG_SERVICES_AUTHORITATIVE 2 #define NSS_FLAG_SETENT_BATCH_READ 4 +#define NSS_FLAG_ADJUNCT_AS_SHADOW 8 /* Get current set of default flags. */ @@ -1,7 +1,7 @@ # /etc/default/nss # This file can theoretically contain a bunch of customization variables # for Name Service Switch in the GNU C library. For now there are only -# three variables: +# four variables: # # NETID_AUTHORITATIVE # If set to TRUE, the initgroups() function will accept the information @@ -26,3 +26,12 @@ # might result into a network communication with the server to get # the next entry. #SETENT_BATCH_READ=TRUE +# +# ADJUNCT_AS_SHADOW +# If set to TRUE, the passwd routines in the NIS NSS module will not +# use the passwd.adjunct.byname tables to fill in the password data +# in the passwd structure. This is a security problem if the NIS +# server cannot be trusted to send the passwd.adjuct table only to +# privileged clients. Instead the passwd.adjunct.byname table is +# used to synthesize the shadow.byname table if it does not exist. +#ADJUNCT_AS_SHADOW=TRUE diff --git a/nis/nss-default.c b/nis/nss-default.c index 046ddfe..d7a3293 100644 --- a/nis/nss-default.c +++ b/nis/nss-default.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 2001, 2004, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 1996,2001,2004,2006,2007,2010 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -47,7 +47,8 @@ static const struct #define STRNLEN(s) s, sizeof (s) - 1 { STRNLEN ("NETID_AUTHORITATIVE"), NSS_FLAG_NETID_AUTHORITATIVE }, { STRNLEN ("SERVICES_AUTHORITATIVE"), NSS_FLAG_SERVICES_AUTHORITATIVE }, - { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ } + { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ }, + { STRNLEN ("ADJUNCT_AS_SHADOW"), NSS_FLAG_ADJUNCT_AS_SHADOW }, }; #define nvars (sizeof (vars) / sizeof (vars[0])) diff --git a/nis/nss_nis/nis-pwd.c b/nis/nss_nis/nis-pwd.c index fdc7dc9..89de350 100644 --- a/nis/nss_nis/nis-pwd.c +++ b/nis/nss_nis/nis-pwd.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1996-1998,2001-2003,2006,2009 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998,2001-2003,2006,2009,2010 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -39,7 +40,7 @@ /* Protect global state against multiple changers */ __libc_lock_define_initialized (static, lock) -static bool_t new_start = 1; +static bool new_start = true; static char *oldkey; static int oldkeylen; static intern_t intern; @@ -108,13 +109,10 @@ _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval, static void internal_nis_endpwent (void) { - new_start = 1; - if (oldkey != NULL) - { - free (oldkey); - oldkey = NULL; - oldkeylen = 0; - } + new_start = true; + free (oldkey); + oldkey = NULL; + oldkeylen = 0; struct response_t *curr = intern.start; @@ -264,18 +262,21 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, } /* Check for adjunct style secret passwords. They can be - recognized by a password starting with "##". */ + recognized by a password starting with "##". We do not use + it if the passwd.adjunct.byname table is supposed to be used + as a shadow.byname replacement. */ char *p = strchr (result, ':'); size_t namelen; char *result2; int len2; - if (p != NULL /* This better should be true in all cases. */ + if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0 + && p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && (namelen = p - result, yp_match (domain, "passwd.adjunct.byname", result, namelen, &result2, &len2)) == YPERR_SUCCESS) { - /* We found a passwd.adjunct entry. Merge encrypted + /* We found a passwd.adjunct.byname entry. Merge encrypted password therein into original result. */ char *encrypted = strchr (result2, ':'); char *endp; @@ -325,7 +326,7 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, } while (isspace (*p)) - ++p; + ++p; if (!batch_read) free (result); @@ -346,7 +347,7 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, free (oldkey); oldkey = outkey; oldkeylen = keylen; - new_start = 0; + new_start = false; } } while (parse_res < 1); @@ -399,16 +400,19 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, } /* Check for adjunct style secret passwords. They can be recognized - by a password starting with "##". */ + by a password starting with "##". We do not use it if the + passwd.adjunct.byname table is supposed to be used as a shadow.byname + replacement. */ char *result2; int len2; char *p = strchr (result, ':'); - if (p != NULL /* This better should be true in all cases. */ + if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0 + && p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && yp_match (domain, "passwd.adjunct.byname", name, namelen, &result2, &len2) == YPERR_SUCCESS) { - /* We found a passwd.adjunct entry. Merge encrypted password + /* We found a passwd.adjunct.byname entry. Merge encrypted password therein into original result. */ char *encrypted = strchr (result2, ':'); char *endp; @@ -465,7 +469,7 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) - return NSS_STATUS_TRYAGAIN; + return NSS_STATUS_TRYAGAIN; else return NSS_STATUS_NOTFOUND; } @@ -498,18 +502,21 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, } /* Check for adjunct style secret passwords. They can be recognized - by a password starting with "##". */ + by a password starting with "##". We do not use it if the + passwd.adjunct.byname table is supposed to be used as a shadow.byname + replacement. */ char *result2; int len2; size_t namelen; char *p = strchr (result, ':'); - if (p != NULL /* This better should be true in all cases. */ + if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0 + && p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && (namelen = p - result, yp_match (domain, "passwd.adjunct.byname", result, namelen, &result2, &len2)) == YPERR_SUCCESS) { - /* We found a passwd.adjunct entry. Merge encrypted password + /* We found a passwd.adjunct.byname entry. Merge encrypted password therein into original result. */ char *encrypted = strchr (result2, ':'); char *endp; @@ -567,7 +574,7 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) - return NSS_STATUS_TRYAGAIN; + return NSS_STATUS_TRYAGAIN; else return NSS_STATUS_NOTFOUND; } diff --git a/nis/nss_nis/nis-spwd.c b/nis/nss_nis/nis-spwd.c index 0fc4e17..3cf913b 100644 --- a/nis/nss_nis/nis-spwd.c +++ b/nis/nss_nis/nis-spwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998,2001-2003,2006,2010 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -31,6 +31,7 @@ #include <rpcsvc/ypclnt.h> #include "nss-nis.h" +#include <libnsl.h> /* Get the declaration of the parser function. */ #define ENTNAME spent @@ -41,7 +42,8 @@ /* Protect global state against multiple changers */ __libc_lock_define_initialized (static, lock) -static bool_t new_start = 1; +static bool new_start = true; +static bool ent_adjunct_used; static char *oldkey; static int oldkeylen; @@ -50,7 +52,8 @@ _nss_nis_setspent (int stayopen) { __libc_lock_lock (lock); - new_start = 1; + new_start = true; + ent_adjunct_used = false; free (oldkey); oldkey = NULL; oldkeylen = 0; @@ -83,32 +86,50 @@ internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen, int yperr; if (new_start) - yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result, - &len); + { + yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result, + &len); + if (__builtin_expect (yperr == YPERR_MAP, 0) + && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW)) + { + free (result); + yperr = yp_first (domain, "passwd.adjunct.byname", &outkey, + &keylen, &result, &len); + ent_adjunct_used = true; + } + } else - yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey, - &keylen, &result, &len); + yperr = yp_next (domain, (ent_adjunct_used + ? "passwd.adjunct.byname" : "shadow.byname"), + oldkey, oldkeylen, &outkey, &keylen, &result, &len); if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) - { + { enum nss_status retval = yperr2nss (yperr); if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; - return retval; - } + return retval; + } - if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) - { - free (result); + if (__builtin_expect ((size_t) (len + (ent_adjunct_used ? 3 : 1)) + > buflen, 0)) + { + free (result); *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } + return NSS_STATUS_TRYAGAIN; + } char *p = strncpy (buffer, result, len); - buffer[len] = '\0'; + if (ent_adjunct_used) + /* This is an ugly trick. The format of passwd.adjunct.byname almost + matches the shadow.byname format except that the last two fields + are missing. Synthesize them by marking them empty. */ + strcpy (&buffer[len], "::"); + else + buffer[len] = '\0'; while (isspace (*p)) - ++p; + ++p; free (result); parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen, @@ -123,7 +144,7 @@ internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen, free (oldkey); oldkey = outkey; oldkeylen = keylen; - new_start = 0; + new_start = false; } while (!parse_res); @@ -154,15 +175,25 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp, *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } + const size_t name_len = strlen (name); char *domain; if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; + bool adjunct_used = false; char *result; int len; - int yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result, + int yperr = yp_match (domain, "shadow.byname", name, name_len, &result, &len); + if (__builtin_expect (yperr == YPERR_MAP, 0) + && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW)) + { + free (result); + yperr = yp_match (domain, "passwd.adjunct.byname", name, name_len, + &result, &len); + adjunct_used = true; + } if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { @@ -173,7 +204,7 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp, return retval; } - if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) + if (__builtin_expect ((size_t) (len + (adjunct_used ? 3 : 1)) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -181,7 +212,13 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp, } char *p = strncpy (buffer, result, len); - buffer[len] = '\0'; + if (__builtin_expect (adjunct_used, false)) + /* This is an ugly trick. The format of passwd.adjunct.byname almost + matches the shadow.byname format except that the last two fields + are missing. Synthesize them by marking them empty. */ + strcpy (&buffer[len], "::"); + else + buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); |