about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--NEWS10
-rw-r--r--nis/libnsl.h3
-rw-r--r--nis/nss11
-rw-r--r--nis/nss-default.c5
-rw-r--r--nis/nss_nis/nis-pwd.c51
-rw-r--r--nis/nss_nis/nis-spwd.c79
7 files changed, 132 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index e46656b1b4..d59224b46d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index e1fb6a5766..c19f3ae712 100644
--- a/NEWS
+++ b/NEWS
@@ -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 c6ceb321d7..dc15930716 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.  */
diff --git a/nis/nss b/nis/nss
index aab40ab3f0..0ac6774a1f 100644
--- a/nis/nss
+++ b/nis/nss
@@ -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 046ddfee8d..d7a3293a49 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 fdc7dc9e1e..89de350c4d 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 0fc4e17c42..3cf913b4cd 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);