2010-01-06 Christoph Pleger Aurelien Jarno * 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. Updated on 2010-03-03 from: https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/526530 Index: eglibc-2.11.1/nis/nss_nis/nis-pwd.c =================================================================== --- eglibc-2.11.1.orig/nis/nss_nis/nis-pwd.c 2009-06-24 09:26:34.000000000 -0700 +++ eglibc-2.11.1/nis/nss_nis/nis-pwd.c 2010-03-03 10:43:59.072419321 -0800 @@ -263,66 +263,15 @@ } } - /* Check for adjunct style secret passwords. They can be - recognized by a password starting with "##". */ - char *p = strchr (result, ':'); - size_t namelen; - char *result2; - int len2; - 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) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { - /* 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) - { - /* 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; - } - - restlen = len - (p - result); - if (__builtin_expect ((size_t) (namelen + (endp - encrypted) - + restlen + 2) > buflen, 0)) - { - free (result2); - free (result); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen), - ":", 1), - encrypted, endp - encrypted), - p, restlen + 1); - p = buffer; - - free (result2); + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; } - else - { - non_adjunct: - if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) - { - free (result); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - p = buffer; - *((char *) mempcpy (buffer, result, len)) = '\0'; - } + char *p = buffer; + *((char *) mempcpy (buffer, result, len)) = '\0'; while (isspace (*p)) ++p; @@ -398,63 +347,15 @@ return retval; } - /* Check for adjunct style secret passwords. They can be recognized - by a password starting with "##". */ - char *result2; - int len2; - char *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) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { - /* We found a passwd.adjunct entry. Merge encrypted password - therein into original result. */ - char *encrypted = strchr (result2, ':'); - char *endp; - - if (encrypted == NULL - || (endp = strchr (++encrypted, ':')) == NULL - || (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; - } - - size_t restlen = len - (p - result); - if (__builtin_expect ((size_t) (namelen + (endp - encrypted) - + restlen + 2) > buflen, 0)) - { - free (result2); - free (result); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, name, namelen), - ":", 1), - encrypted, endp - encrypted), - p, restlen + 1); - p = buffer; - - free (result2); + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; } - else - { - non_adjunct: - 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'; - } + char *p = strncpy (buffer, result, len); + buffer[len] = '\0'; while (isspace (*p)) ++p; @@ -497,66 +398,15 @@ return retval; } - /* Check for adjunct style secret passwords. They can be recognized - by a password starting with "##". */ - char *result2; - int len2; - size_t namelen; - char *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) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { - /* 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) - { - /* 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; - } - - restlen = len - (p - result); - if (__builtin_expect ((size_t) (namelen + (endp - encrypted) - + restlen + 2) > buflen, 0)) - { - free (result2); - free (result); - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen), - ":", 1), - encrypted, endp - encrypted), - p, restlen + 1); - p = buffer; - - free (result2); + free (result); + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; } - else - { - non_adjunct: - 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'; - } + char *p = strncpy (buffer, result, len); + buffer[len] = '\0'; while (isspace (*p)) ++p; Index: eglibc-2.11.1/nis/nss_nis/nis-spwd.c =================================================================== --- eglibc-2.11.1.orig/nis/nss_nis/nis-spwd.c 2006-08-16 18:18:26.000000000 -0700 +++ eglibc-2.11.1/nis/nss_nis/nis-spwd.c 2010-03-03 10:42:26.653668531 -0800 @@ -81,13 +81,38 @@ int len; int keylen; int yperr; + int adjunct_used = 0; if (new_start) - yperr = 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, "passwd.adjunct.byname", &outkey, &keylen, + &result, &len); + adjunct_used = 1; + } + } else - yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey, - &keylen, &result, &len); + { + 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)) { @@ -98,7 +123,7 @@ 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; @@ -107,6 +132,9 @@ char *p = strncpy (buffer, result, len); buffer[len] = '\0'; + if (adjunct_used) + p = strcat (buffer, "::"); + while (isspace (*p)) ++p; free (result); @@ -149,6 +177,8 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp, char *buffer, size_t buflen, int *errnop) { + int adjunct_used = 0; + if (name == NULL) { *errnop = EINVAL; @@ -164,6 +194,16 @@ 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,7 +213,7 @@ 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; @@ -182,6 +222,9 @@ char *p = strncpy (buffer, result, len); buffer[len] = '\0'; + if (adjunct_used) + p = strcat (buffer, "::"); + while (isspace (*p)) ++p; free (result);