]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Implement new mode for NIS passwd.adjunct.byname table.
authorUlrich Drepper <drepper@redhat.com>
Wed, 7 Apr 2010 14:37:39 +0000 (07:37 -0700)
committerUlrich Drepper <drepper@redhat.com>
Wed, 7 Apr 2010 14:37:39 +0000 (07:37 -0700)
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.

ChangeLog
NEWS
nis/libnsl.h
nis/nss
nis/nss-default.c
nis/nss_nis/nis-pwd.c
nis/nss_nis/nis-spwd.c

index e46656b1b403ac8ed568f19dc36be326848baec5..d59224b46dbb01fb22deba85652744b710361c81 100644 (file)
--- 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 e1fb6a5766ea42e35f85610c8c5c6d38b5844386..c19f3ae712f336e340b0aceb4890db9ebea3826a 100644 (file)
--- 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.
+
 \f
 Version 2.11
 
index c6ceb321d7e3acc4491b6b0dcd52331cd7991294..dc15930716b2ee79c72c6c5acb74ff8ffe2ee378 100644 (file)
@@ -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 aab40ab3f01a8e1cd4cc72d8b763c9151abe9e85..0ac6774a1ff29f012efaec9c4be1fcc3b83da7e8 100644 (file)
--- 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
 #  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
index 046ddfee8d6d50fa900be97d84ee1d23b6b5cfd5..d7a3293a49dc8f7f890faf17d98f3f610d661b56 100644 (file)
@@ -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]))
 
index fdc7dc9e1e17a203c673c47e617b50dd17f75885..89de350c4dab47d48d073a5a1f3d2231af9c9973 100644 (file)
@@ -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;
     }
index 0fc4e17c4234f7dc6901d6e86c78c7c1d56603a6..3cf913b4cd38ee3ca9dca592575806061eb822c4 100644 (file)
@@ -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);