r4087 - in glibc-package/branches/glibc-branch-etch/debian: . patches patches/any
Author: aurel32
Date: 2010-01-16 15:26:47 +0000 (Sat, 16 Jan 2010)
New Revision: 4087
Added:
glibc-package/branches/glibc-branch-etch/debian/patches/any/submitted-nis-shadow.diff
Modified:
glibc-package/branches/glibc-branch-etch/debian/changelog
glibc-package/branches/glibc-branch-etch/debian/patches/series
Log:
* Fix NIS shadow entries leakage to non-priviledge users when nscd is
in use.
Fixes: CVE-2010-0015.
Modified: glibc-package/branches/glibc-branch-etch/debian/changelog
===================================================================
--- glibc-package/branches/glibc-branch-etch/debian/changelog 2010-01-16 14:54:09 UTC (rev 4086)
+++ glibc-package/branches/glibc-branch-etch/debian/changelog 2010-01-16 15:26:47 UTC (rev 4087)
@@ -1,3 +1,11 @@
+glibc (2.3.6.ds1-13etch10) stable; urgency=low
+
+ * Fix NIS shadow entries leakage to non-priviledge users when nscd is
+ in use.
+ Fixes: CVE-2010-0015.
+
+ -- Aurelien Jarno <aurel32@debian.org> Sat, 16 Jan 2010 16:26:38 +0100
+
glibc (2.3.6.ds1-13etch9) stable; urgency=low
* Backport from unstable: patches/localedata/cy_EL_euro.diff,
Added: glibc-package/branches/glibc-branch-etch/debian/patches/any/submitted-nis-shadow.diff
===================================================================
--- glibc-package/branches/glibc-branch-etch/debian/patches/any/submitted-nis-shadow.diff (rev 0)
+++ glibc-package/branches/glibc-branch-etch/debian/patches/any/submitted-nis-shadow.diff 2010-01-16 15:26:47 UTC (rev 4087)
@@ -0,0 +1,339 @@
+2010-01-06 Christoph Pleger <Christoph.Pleger@cs.tu-dortmund.de>
+ Aurelien Jarno <aurelien@aurel32.net>
+
+ * nis/nss_nis/nis-pwd.c (internal_nis_getpwent_r): When adjunct
+ style secret password is returned, mangle 'x' instead of the
+ encrypted password.
+ (_nss_nis_getpwnam_r): Likewise.
+ (_nss_nis_getpwuid_r): Likewise.
+ * nis/nss_nis/nis-spwd.c (internal_nis_getspent_r): When shadow.byname
+ does not exist, look in passwd.adjunct.byname and adapt the result.
+ (_nss_nis_getspnam_r): Likewise.
+
+
+--- a/nis/nss_nis/nis-pwd.c
++++ b/nis/nss_nis/nis-pwd.c
+@@ -82,9 +82,8 @@
+ do
+ {
+ enum nss_status retval;
+- char *result, *outkey, *result2, *p;
+- int len, keylen, len2;
+- size_t namelen;
++ char *result, *outkey, *p;
++ int len, keylen;
+
+ if (new_start)
+ retval = yperr2nss (yp_first (domain, "passwd.byname",
+@@ -105,44 +104,33 @@
+ recognized by a password starting with "##". */
+ p = strchr (result, ':');
+ if (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)
++ && p[1] == '#' && p[2] == '#')
+ {
+- /* We found a passwd.adjunct entry. Merge encrypted
+- password therein into original result. */
+- char *encrypted = strchr (result2, ':');
+- char *endp;
+- size_t restlen;
++ size_t namelen, restlen;
+
+- if (encrypted == NULL
+- || (endp = strchr (++encrypted, ':')) == NULL
+- || (p = strchr (p + 1, ':')) == NULL)
++ namelen = p - result;
++ if ((p = strchr (p + 1, ':')) == NULL)
+ {
+ /* Invalid format of the entry. This never should happen
+ unless the data from which the NIS table is generated is
+ wrong. We simply ignore it. */
+- free (result2);
+ goto non_adjunct;
+ }
+
++ /* We found an adjunct style secret password. Replace
++ it by 'x' into the result. */
+ restlen = len - (p - result);
+- if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++ if ((size_t) (namelen + restlen + 3) > buflen)
+ {
+- free (result2);
+ free (result);
+ *errnop = ERANGE;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+- __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
+- ":", 1),
+- encrypted, endp - encrypted),
++ __mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
++ ":x", 2),
+ p, restlen + 1);
+ p = buffer;
+-
+- free (result2);
+ }
+ else
+ {
+@@ -201,8 +189,8 @@
+ {
+ struct parser_data *data = (void *) buffer;
+ enum nss_status retval;
+- char *domain, *result, *result2, *p;
+- int len, len2, parse_res;
++ char *domain, *result, *p;
++ int len, parse_res;
+ size_t namelen;
+
+ if (name == NULL)
+@@ -230,43 +218,32 @@
+ by a password starting with "##". */
+ p = strchr (result, ':');
+ if (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)
++ && p[1] == '#' && p[2] == '#')
+ {
+- /* We found a passwd.adjunct entry. Merge encrypted password
+- therein into original result. */
+- char *encrypted = strchr (result2, ':');
+- char *endp;
+ size_t restlen;
+-
+- if (encrypted == NULL
+- || (endp = strchr (++encrypted, ':')) == NULL
+- || (p = strchr (p + 1, ':')) == NULL)
++
++ if ((p = strchr (p + 1, ':')) == NULL)
+ {
+ /* Invalid format of the entry. This never should happen
+ unless the data from which the NIS table is generated is
+ wrong. We simply ignore it. */
+- free (result2);
+ goto non_adjunct;
+ }
+
++ /* We found an adjunct style secret password. Replace
++ it by 'x' into the result. */
+ restlen = len - (p - result);
+- if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++ if ((size_t) (namelen + restlen + 3) > buflen)
+ {
+- free (result2);
+ free (result);
+ *errnop = ERANGE;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+- __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, name, namelen),
+- ":", 1),
+- encrypted, endp - encrypted),
++ __mempcpy (__mempcpy (__mempcpy (buffer, name, namelen),
++ ":x", 2),
+ p, restlen + 1);
+ p = buffer;
+-
+- free (result2);
+ }
+ else
+ {
+@@ -304,10 +281,9 @@
+ {
+ struct parser_data *data = (void *) buffer;
+ enum nss_status retval;
+- char *domain, *result, *p, *result2;
+- int len, nlen, parse_res, len2;
++ char *domain, *result, *p;
++ int len, nlen, parse_res;
+ char buf[32];
+- size_t namelen;
+
+ if (yp_get_default_domain (&domain))
+ return NSS_STATUS_UNAVAIL;
+@@ -328,44 +304,32 @@
+ by a password starting with "##". */
+ p = strchr (result, ':');
+ if (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)
++ && p[1] == '#' && p[2] == '#')
+ {
+- /* We found a passwd.adjunct entry. Merge encrypted password
+- therein into original result. */
+- char *encrypted = strchr (result2, ':');
+- char *endp;
+- size_t restlen;
++ size_t namelen, restlen;
+
+- if (encrypted == NULL
+- || (endp = strchr (++encrypted, ':')) == NULL
+- || (p = strchr (p + 1, ':')) == NULL)
++ namelen = p - result;
++ if ((p = strchr (p + 1, ':')) == NULL)
+ {
+ /* Invalid format of the entry. This never should happen
+ unless the data from which the NIS table is generated is
+ wrong. We simply ignore it. */
+- free (result2);
+ goto non_adjunct;
+ }
+-
++ /* We found an adjunct style secret password. Replace
++ it by 'x' into the result. */
+ restlen = len - (p - result);
+- if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen)
++ if ((size_t) (namelen + restlen + 3) > buflen)
+ {
+- free (result2);
+ free (result);
+ *errnop = ERANGE;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+- __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
+- ":", 1),
+- encrypted, endp - encrypted),
++ __mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
++ ":x", 2),
+ p, restlen + 1);
+ p = buffer;
+-
+- free (result2);
+ }
+ else
+ {
+--- a/nis/nss_nis/nis-spwd.c
++++ b/nis/nss_nis/nis-spwd.c
+@@ -78,25 +78,51 @@
+ /* Get the next entry until we found a correct one. */
+ do
+ {
+- enum nss_status retval;
+ char *p;
++ int yperr;
++ int adjunct_used = 0;
+
+ if (new_start)
+- retval = yperr2nss (yp_first (domain, "shadow.byname",
+- &outkey, &keylen, &result, &len));
++ {
++ yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
++ &len);
++
++ if (yperr == YPERR_MAP)
++ {
++ if (result != NULL)
++ free(result);
++
++ yperr = yp_first (domain, "shadow.byname", &outkey, &keylen,
++ &result, &len);
++ adjunct_used = 1;
++ }
++ }
+ else
+- retval = yperr2nss ( yp_next (domain, "shadow.byname",
+- oldkey, oldkeylen,
+- &outkey, &keylen, &result, &len));
++ {
++ yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey,
++ &keylen, &result, &len);
+
+- if (retval != NSS_STATUS_SUCCESS)
++ if (yperr == YPERR_MAP)
++ {
++ if (result != NULL)
++ free(result);
++
++ yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen,
++ &outkey, &keylen, &result, &len);
++ adjunct_used = 1;
++ }
++ }
++
++ if (yperr != YPERR_SUCCESS)
+ {
++ enum nss_status retval = yperr2nss (yperr);
++
+ if (retval == NSS_STATUS_TRYAGAIN)
+ *errnop = errno;
+ return retval;
+ }
+
+- if ((size_t) (len + 1) > buflen)
++ if ((size_t) (len + (adjunct_used ? 3 : 1)) > buflen)
+ {
+ free (result);
+ *errnop = ERANGE;
+@@ -105,6 +131,9 @@
+
+ p = strncpy (buffer, result, len);
+ buffer[len] = '\0';
++ if (adjunct_used)
++ p = strcat (buffer, "::");
++
+ while (isspace (*p))
+ ++p;
+ free (result);
+@@ -147,9 +176,9 @@
+ char *buffer, size_t buflen, int *errnop)
+ {
+ struct parser_data *data = (void *) buffer;
+- enum nss_status retval;
+ char *domain, *result, *p;
+- int len, parse_res;
++ int len, parse_res, yperr;
++ int adjunct_used = 0;
+
+ if (name == NULL)
+ {
+@@ -160,17 +189,29 @@
+ if (yp_get_default_domain (&domain))
+ return NSS_STATUS_UNAVAIL;
+
+- retval = yperr2nss (yp_match (domain, "shadow.byname", name,
+- strlen (name), &result, &len));
++ yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result,
++ &len);
+
+- if (retval != NSS_STATUS_SUCCESS)
++ 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);
++
+ if (retval == NSS_STATUS_TRYAGAIN)
+ *errnop = errno;
+ return retval;
+ }
+
+- if ((size_t) (len + 1) > buflen)
++ if ((size_t) (len + (adjunct_used ? 3 : 1)) > buflen)
+ {
+ free (result);
+ *errnop = ERANGE;
+@@ -179,6 +220,9 @@
+
+ p = strncpy (buffer, result, len);
+ buffer[len] = '\0';
++ if (adjunct_used)
++ p = strcat (buffer, "::");
++
+ while (isspace (*p))
+ ++p;
+ free (result);
Modified: glibc-package/branches/glibc-branch-etch/debian/patches/series
===================================================================
--- glibc-package/branches/glibc-branch-etch/debian/patches/series 2010-01-16 14:54:09 UTC (rev 4086)
+++ glibc-package/branches/glibc-branch-etch/debian/patches/series 2010-01-16 15:26:47 UTC (rev 4087)
@@ -201,3 +201,4 @@
any/cvs-vfprintf-stack-smashing.diff
any/cvs-getnetgrent_r-memory-leak.diff
any/cvs-sunrpc_rpc_thread.diff -p0
+any/submitted-nis-shadow.diff -p1
Reply to: