aboutsummaryrefslogtreecommitdiff
path: root/nis
diff options
context:
space:
mode:
Diffstat (limited to 'nis')
-rw-r--r--nis/libnsl.h3
-rw-r--r--nis/nss11
-rw-r--r--nis/nss-default.c5
-rw-r--r--nis/nss_nis/nis-pwd.c51
-rw-r--r--nis/nss_nis/nis-spwd.c79
5 files changed, 102 insertions, 47 deletions
diff --git a/nis/libnsl.h b/nis/libnsl.h
index c6ceb321d7..dc15930716 100644
--- a/nis/libnsl.h
+++ b/nis/libnsl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2005, 2006, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,6 +21,7 @@
#define NSS_FLAG_NETID_AUTHORITATIVE 1
#define NSS_FLAG_SERVICES_AUTHORITATIVE 2
#define NSS_FLAG_SETENT_BATCH_READ 4
+#define NSS_FLAG_ADJUNCT_AS_SHADOW 8
/* Get current set of default flags. */
diff --git a/nis/nss b/nis/nss
index aab40ab3f0..0ac6774a1f 100644
--- a/nis/nss
+++ b/nis/nss
@@ -1,7 +1,7 @@
# /etc/default/nss
# This file can theoretically contain a bunch of customization variables
# for Name Service Switch in the GNU C library. For now there are only
-# three variables:
+# four variables:
#
# NETID_AUTHORITATIVE
# If set to TRUE, the initgroups() function will accept the information
@@ -26,3 +26,12 @@
# might result into a network communication with the server to get
# the next entry.
#SETENT_BATCH_READ=TRUE
+#
+# ADJUNCT_AS_SHADOW
+# If set to TRUE, the passwd routines in the NIS NSS module will not
+# use the passwd.adjunct.byname tables to fill in the password data
+# in the passwd structure. This is a security problem if the NIS
+# server cannot be trusted to send the passwd.adjuct table only to
+# privileged clients. Instead the passwd.adjunct.byname table is
+# used to synthesize the shadow.byname table if it does not exist.
+#ADJUNCT_AS_SHADOW=TRUE
diff --git a/nis/nss-default.c b/nis/nss-default.c
index 046ddfee8d..d7a3293a49 100644
--- a/nis/nss-default.c
+++ b/nis/nss-default.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 1996,2001,2004,2006,2007,2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -47,7 +47,8 @@ static const struct
#define STRNLEN(s) s, sizeof (s) - 1
{ STRNLEN ("NETID_AUTHORITATIVE"), NSS_FLAG_NETID_AUTHORITATIVE },
{ STRNLEN ("SERVICES_AUTHORITATIVE"), NSS_FLAG_SERVICES_AUTHORITATIVE },
- { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ }
+ { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ },
+ { STRNLEN ("ADJUNCT_AS_SHADOW"), NSS_FLAG_ADJUNCT_AS_SHADOW },
};
#define nvars (sizeof (vars) / sizeof (vars[0]))
diff --git a/nis/nss_nis/nis-pwd.c b/nis/nss_nis/nis-pwd.c
index fdc7dc9e1e..89de350c4d 100644
--- a/nis/nss_nis/nis-pwd.c
+++ b/nis/nss_nis/nis-pwd.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1996-1998,2001-2003,2006,2009 Free Software Foundation, Inc.
+/* Copyright (C) 1996-1998,2001-2003,2006,2009,2010
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
@@ -39,7 +40,7 @@
/* Protect global state against multiple changers */
__libc_lock_define_initialized (static, lock)
-static bool_t new_start = 1;
+static bool new_start = true;
static char *oldkey;
static int oldkeylen;
static intern_t intern;
@@ -108,13 +109,10 @@ _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
static void
internal_nis_endpwent (void)
{
- new_start = 1;
- if (oldkey != NULL)
- {
- free (oldkey);
- oldkey = NULL;
- oldkeylen = 0;
- }
+ new_start = true;
+ free (oldkey);
+ oldkey = NULL;
+ oldkeylen = 0;
struct response_t *curr = intern.start;
@@ -264,18 +262,21 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
}
/* Check for adjunct style secret passwords. They can be
- recognized by a password starting with "##". */
+ recognized by a password starting with "##". We do not use
+ it if the passwd.adjunct.byname table is supposed to be used
+ as a shadow.byname replacement. */
char *p = strchr (result, ':');
size_t namelen;
char *result2;
int len2;
- if (p != NULL /* This better should be true in all cases. */
+ if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+ && 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)
{
- /* We found a passwd.adjunct entry. Merge encrypted
+ /* We found a passwd.adjunct.byname entry. Merge encrypted
password therein into original result. */
char *encrypted = strchr (result2, ':');
char *endp;
@@ -325,7 +326,7 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
}
while (isspace (*p))
- ++p;
+ ++p;
if (!batch_read)
free (result);
@@ -346,7 +347,7 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
- new_start = 0;
+ new_start = false;
}
}
while (parse_res < 1);
@@ -399,16 +400,19 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
}
/* Check for adjunct style secret passwords. They can be recognized
- by a password starting with "##". */
+ by a password starting with "##". We do not use it if the
+ passwd.adjunct.byname table is supposed to be used as a shadow.byname
+ replacement. */
char *result2;
int len2;
char *p = strchr (result, ':');
- if (p != NULL /* This better should be true in all cases. */
+ if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+ && 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)
{
- /* We found a passwd.adjunct entry. Merge encrypted password
+ /* We found a passwd.adjunct.byname entry. Merge encrypted password
therein into original result. */
char *encrypted = strchr (result2, ':');
char *endp;
@@ -465,7 +469,7 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
if (__builtin_expect (parse_res < 1, 0))
{
if (parse_res == -1)
- return NSS_STATUS_TRYAGAIN;
+ return NSS_STATUS_TRYAGAIN;
else
return NSS_STATUS_NOTFOUND;
}
@@ -498,18 +502,21 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
}
/* Check for adjunct style secret passwords. They can be recognized
- by a password starting with "##". */
+ by a password starting with "##". We do not use it if the
+ passwd.adjunct.byname table is supposed to be used as a shadow.byname
+ replacement. */
char *result2;
int len2;
size_t namelen;
char *p = strchr (result, ':');
- if (p != NULL /* This better should be true in all cases. */
+ if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+ && 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)
{
- /* We found a passwd.adjunct entry. Merge encrypted password
+ /* We found a passwd.adjunct.byname entry. Merge encrypted password
therein into original result. */
char *encrypted = strchr (result2, ':');
char *endp;
@@ -567,7 +574,7 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
if (__builtin_expect (parse_res < 1, 0))
{
if (parse_res == -1)
- return NSS_STATUS_TRYAGAIN;
+ return NSS_STATUS_TRYAGAIN;
else
return NSS_STATUS_NOTFOUND;
}
diff --git a/nis/nss_nis/nis-spwd.c b/nis/nss_nis/nis-spwd.c
index 0fc4e17c42..3cf913b4cd 100644
--- a/nis/nss_nis/nis-spwd.c
+++ b/nis/nss_nis/nis-spwd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1996-1998,2001-2003,2006,2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
@@ -31,6 +31,7 @@
#include <rpcsvc/ypclnt.h>
#include "nss-nis.h"
+#include <libnsl.h>
/* Get the declaration of the parser function. */
#define ENTNAME spent
@@ -41,7 +42,8 @@
/* Protect global state against multiple changers */
__libc_lock_define_initialized (static, lock)
-static bool_t new_start = 1;
+static bool new_start = true;
+static bool ent_adjunct_used;
static char *oldkey;
static int oldkeylen;
@@ -50,7 +52,8 @@ _nss_nis_setspent (int stayopen)
{
__libc_lock_lock (lock);
- new_start = 1;
+ new_start = true;
+ ent_adjunct_used = false;
free (oldkey);
oldkey = NULL;
oldkeylen = 0;
@@ -83,32 +86,50 @@ internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
int yperr;
if (new_start)
- yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
- &len);
+ {
+ yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
+ &len);
+ if (__builtin_expect (yperr == YPERR_MAP, 0)
+ && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW))
+ {
+ free (result);
+ yperr = yp_first (domain, "passwd.adjunct.byname", &outkey,
+ &keylen, &result, &len);
+ ent_adjunct_used = true;
+ }
+ }
else
- yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey,
- &keylen, &result, &len);
+ yperr = yp_next (domain, (ent_adjunct_used
+ ? "passwd.adjunct.byname" : "shadow.byname"),
+ oldkey, oldkeylen, &outkey, &keylen, &result, &len);
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
- {
+ {
enum nss_status retval = yperr2nss (yperr);
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
- return retval;
- }
+ return retval;
+ }
- if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
- {
- free (result);
+ if (__builtin_expect ((size_t) (len + (ent_adjunct_used ? 3 : 1))
+ > buflen, 0))
+ {
+ free (result);
*errnop = ERANGE;
- return NSS_STATUS_TRYAGAIN;
- }
+ return NSS_STATUS_TRYAGAIN;
+ }
char *p = strncpy (buffer, result, len);
- buffer[len] = '\0';
+ if (ent_adjunct_used)
+ /* This is an ugly trick. The format of passwd.adjunct.byname almost
+ matches the shadow.byname format except that the last two fields
+ are missing. Synthesize them by marking them empty. */
+ strcpy (&buffer[len], "::");
+ else
+ buffer[len] = '\0';
while (isspace (*p))
- ++p;
+ ++p;
free (result);
parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen,
@@ -123,7 +144,7 @@ internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
- new_start = 0;
+ new_start = false;
}
while (!parse_res);
@@ -154,15 +175,25 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp,
*errnop = EINVAL;
return NSS_STATUS_UNAVAIL;
}
+ const size_t name_len = strlen (name);
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
+ bool adjunct_used = false;
char *result;
int len;
- int yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result,
+ int yperr = yp_match (domain, "shadow.byname", name, name_len, &result,
&len);
+ if (__builtin_expect (yperr == YPERR_MAP, 0)
+ && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW))
+ {
+ free (result);
+ yperr = yp_match (domain, "passwd.adjunct.byname", name, name_len,
+ &result, &len);
+ adjunct_used = true;
+ }
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
@@ -173,7 +204,7 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp,
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;
@@ -181,7 +212,13 @@ _nss_nis_getspnam_r (const char *name, struct spwd *sp,
}
char *p = strncpy (buffer, result, len);
- buffer[len] = '\0';
+ if (__builtin_expect (adjunct_used, false))
+ /* This is an ugly trick. The format of passwd.adjunct.byname almost
+ matches the shadow.byname format except that the last two fields
+ are missing. Synthesize them by marking them empty. */
+ strcpy (&buffer[len], "::");
+ else
+ buffer[len] = '\0';
while (isspace (*p))
++p;
free (result);