The attached patch seems to solve the problems. It works with nscd as well as
without nscd. Authentication works fine now.
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)
Maybe some people can have a look over my patch to see if I missed anything.
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);