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 <aure...@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.ple...@cs.tu-dortmund.de> + Aurelien Jarno <aurel...@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 -- To UNSUBSCRIBE, email to debian-glibc-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org