public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libc/11134] New: getpwnam shows shadow passwords of NIS users
@ 2010-01-05  9:26 Christoph dot Pleger at cs dot tu-dortmund dot de
  2010-01-05  9:28 ` [Bug libc/11134] " Christoph dot Pleger at cs dot tu-dortmund dot de
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Christoph dot Pleger at cs dot tu-dortmund dot de @ 2010-01-05  9:26 UTC (permalink / raw)
  To: glibc-bugs

Hello,
I have several machines where almost all user accounts come by NIS. The NIS
server is running on a Solaris machine. As usual, the Solaris NIS server
exports the passwd data in the map "passwd" and the shadow data in the map
"passwd.adjunct.byname". These two maps are mangled together in some calls
of libc6, for example in getpwnam. This makes it possible for every user who
has an account on the NIS client machine to see the encrypted passwords of
all NIS users. This is a grave security bug.

Furthermore, getspnam returns a NULL pointer for all NIS users, even if
getspnam is called by root.

I wrote a patch nis_shadow.diff that solves these problems. It makes the 
following changes:

* In nis-pwd.c, do not mangle encrypted password from 
  passwd.adjunct.byname map  into the password field
  of passwd map, instead mangle an 'x' into the field

* In nis-spwd.c, look for key in passwd.adjunct.byname if shadow.byname
  does not exist and add the two missing fields (passwd.adjunct.byname
  has two fields less than shadow)

diff -Naurp glibc-2.7.original/nis/nss_nis/nis-pwd.c 
glibc-2.7/nis/nss_nis/nis-pwd.c
--- glibc-2.7.original/nis/nss_nis/nis-pwd.c	2006-05-02 00:31:15.000000000 
+0200
+++ glibc-2.7/nis/nss_nis/nis-pwd.c	2009-12-22 09:04:46.000000000 +0100
@@ -275,8 +275,8 @@ internal_nis_getpwent_r (struct passwd *
 	      yp_match (domain, "passwd.adjunct.byname", result, namelen,
 			&result2, &len2)) == YPERR_SUCCESS)
 	{
-	  /* We found a passwd.adjunct entry.  Merge encrypted
-	     password therein into original result.  */
+	  /* We found a passwd.adjunct entry.  Merge "x"
+	     into original result.  */
 	  char *encrypted = strchr (result2, ':');
 	  char *endp;
 	  size_t restlen;
@@ -304,7 +304,7 @@ internal_nis_getpwent_r (struct passwd *
 
 	  mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen),
 				     ":", 1),
-			    encrypted, endp - encrypted),
+			    "x", 1),
 		   p, restlen + 1);
 	  p = buffer;
 
@@ -408,8 +408,8 @@ _nss_nis_getpwnam_r (const char *name, s
       && yp_match (domain, "passwd.adjunct.byname", name, namelen,
 		   &result2, &len2) == YPERR_SUCCESS)
     {
-      /* We found a passwd.adjunct entry.  Merge encrypted password
-	 therein into original result.  */
+      /* We found a passwd.adjunct entry.  Merge "x"
+	 into original result.  */
       char *encrypted = strchr (result2, ':');
       char *endp;
 
@@ -436,7 +436,7 @@ _nss_nis_getpwnam_r (const char *name, s
 
       __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, name, namelen),
 				       ":", 1),
-			    encrypted, endp - encrypted),
+			    "x", 1),
 		 p, restlen + 1);
       p = buffer;
 
@@ -509,8 +509,8 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
 	  yp_match (domain, "passwd.adjunct.byname", result, namelen,
 		    &result2, &len2)) == YPERR_SUCCESS)
     {
-      /* We found a passwd.adjunct entry.  Merge encrypted password
-	 therein into original result.  */
+      /* We found a passwd.adjunct entry.  Merge "x"
+	 into original result.  */
       char *encrypted = strchr (result2, ':');
       char *endp;
       size_t restlen;
@@ -538,7 +538,7 @@ _nss_nis_getpwuid_r (uid_t uid, struct p
 
       __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
 				       ":", 1),
-			    encrypted, endp - encrypted),
+			    "x", 1),
 		 p, restlen + 1);
       p = buffer;
 
diff -Naurp glibc-2.7.original/nis/nss_nis/nis-spwd.c 
glibc-2.7/nis/nss_nis/nis-spwd.c
--- glibc-2.7.original/nis/nss_nis/nis-spwd.c	2006-04-29 03:09:49.000000000 
+0200
+++ glibc-2.7/nis/nss_nis/nis-spwd.c	2009-12-22 10:02:25.000000000 +0100
@@ -78,17 +78,42 @@ internal_nis_getspent_r (struct spwd *sp
     {
       char *result;
       char *outkey;
+      char *p;
       int len;
       int keylen;
       int yperr;
+      int adjunct_used = 0;
 
-      if (new_start)
+      if (new_start) {
         yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
 			  &len);
-      else
+        
+        if (yperr == YPERR_MAP) {
+	  if (result != NULL)
+	    free result;
+
+	  yperr = yp_first (domain, "passwd.adjunct.byname", &outkey, &keylen, 
&result,
+			    &len);
+
+	  adjunct_used = 1;
+	}
+      }
+          
+      else {
         yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey,
 			 &keylen, &result, &len);
 
+        if (yperr == YPERR_MAP) {
+	  if (result != NULL)
+	    free result;
+
+	  yperr = yp_next (domain, "passwd.adjunct.byname", oldkey, oldkeylen, 
&outkey,
+			   &keylen, &result, &len);
+	  
+	  adjunct_used = 1;
+	}
+      }
+
       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
         {
 	  enum nss_status retval = yperr2nss (yperr);
@@ -98,15 +123,32 @@ internal_nis_getspent_r (struct spwd *sp
           return retval;
         }
 
-      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
-        {
-          free (result);
-	  *errnop = ERANGE;
-          return NSS_STATUS_TRYAGAIN;
-        }
+      if (! adjunct_used)
+	{
+	  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  p = strncpy (buffer, result, len);
+	  buffer[len] = '\0';  
+	}
+      else
+	{
+	  if (__builtin_expect ((size_t) (len + 3) > buflen, 0))
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  p = strncpy (buffer, result, len);
+	  buffer[len] = '\0';  
+	  p = strcat (buffer, "::");
+	}
 
-      char *p = strncpy (buffer, result, len);
-      buffer[len] = '\0';
       while (isspace (*p))
         ++p;
       free (result);
@@ -149,6 +191,9 @@ enum nss_status
 _nss_nis_getspnam_r (const char *name, struct spwd *sp,
 		     char *buffer, size_t buflen, int *errnop)
 {
+  int adjunct_used = 0;
+  char *p;
+
   if (name == NULL)
     {
       *errnop = EINVAL;
@@ -164,6 +209,15 @@ _nss_nis_getspnam_r (const char *name, s
   int yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result,
 			&len);
 
+  if (yperr == YPERR_MAP) {
+    if (result != NULL)
+      free result;
+
+    yperr = yp_match (domain, "passwd.adjunct.byname", name, strlen (name), 
&result,
+		      &len);
+    adjunct_used = 1;
+  }
+
   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
     {
       enum nss_status retval = yperr2nss (yperr);
@@ -173,15 +227,32 @@ _nss_nis_getspnam_r (const char *name, s
       return retval;
     }
 
-  if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+  if (! adjunct_used)
     {
-      free (result);
-      *errnop = ERANGE;
-      return NSS_STATUS_TRYAGAIN;
+      if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      p = strncpy (buffer, result, len);
+      buffer[len] = '\0';  
     }
+  else
+    {
+      if (__builtin_expect ((size_t) (len + 3) > buflen, 0))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
 
-  char *p = strncpy (buffer, result, len);
-  buffer[len] = '\0';
+      p = strncpy (buffer, result, len);
+      buffer[len] = '\0';  
+      p = strcat (buffer, "::");
+    }
+  
   while (isspace (*p))
     ++p;
   free (result);


Regards
  Christoph

-- 
           Summary: getpwnam shows shadow passwords of NIS users
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: critical
          Priority: P1
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: Christoph dot Pleger at cs dot tu-dortmund dot de
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=11134

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


^ permalink raw reply	[flat|nested] 12+ messages in thread
[parent not found: <bug-11134-131@http.sourceware.org/bugzilla/>]

end of thread, other threads:[~2014-06-30 20:29 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-05  9:26 [Bug libc/11134] New: getpwnam shows shadow passwords of NIS users Christoph dot Pleger at cs dot tu-dortmund dot de
2010-01-05  9:28 ` [Bug libc/11134] " Christoph dot Pleger at cs dot tu-dortmund dot de
2010-01-06  7:59 ` Christoph dot Pleger at cs dot tu-dortmund dot de
2010-02-17 13:15 ` Christoph dot Pleger at cs dot tu-dortmund dot de
2010-02-17 13:18 ` Christoph dot Pleger at cs dot tu-dortmund dot de
2010-04-05 20:20 ` drepper at redhat dot com
2010-04-05 20:20 ` drepper at redhat dot com
2010-04-06 22:53 ` drepper at redhat dot com
2010-04-07 14:41 ` drepper at redhat dot com
     [not found] <bug-11134-131@http.sourceware.org/bugzilla/>
2014-02-16 19:35 ` jackie.rosen at hushmail dot com
2014-05-28 19:44 ` schwab at sourceware dot org
2014-06-30 20:29 ` fweimer at redhat dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).