aboutsummaryrefslogtreecommitdiff
path: root/nss
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2010-08-11 07:25:02 -0700
committerUlrich Drepper <drepper@redhat.com>2010-08-11 07:25:02 -0700
commitc3e2f19bb995a0281f4cc56ad81bd67a5404dde6 (patch)
tree5bdbd8e1cb8119cd07cb48c60ef4f383c6b2d875 /nss
parentf15ce4d8dc139523fe0c273580b604b2453acba6 (diff)
downloadglibc-c3e2f19bb995a0281f4cc56ad81bd67a5404dde6.tar
glibc-c3e2f19bb995a0281f4cc56ad81bd67a5404dde6.tar.gz
glibc-c3e2f19bb995a0281f4cc56ad81bd67a5404dde6.tar.bz2
glibc-c3e2f19bb995a0281f4cc56ad81bd67a5404dde6.zip
Add self-contained test for NSS.
While at it fix interaction between __nss_configure_lookup and nscd. Otherwise the test fails if nscd is runnung.
Diffstat (limited to 'nss')
-rw-r--r--nss/Makefile16
-rw-r--r--nss/getXXbyYY_r.c7
-rw-r--r--nss/nss_files/files-parse.c6
-rw-r--r--nss/nss_test1.c154
-rw-r--r--nss/nsswitch.c6
-rw-r--r--nss/nsswitch.h16
-rw-r--r--nss/tst-nss-test1.c72
7 files changed, 268 insertions, 9 deletions
diff --git a/nss/Makefile b/nss/Makefile
index 670e6b2f16..04165b7604 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -1,4 +1,5 @@
-# Copyright (C) 1996-1998,2000-2002,2007,2009 Free Software Foundation, Inc.
+# Copyright (C) 1996-1998,2000-2002,2007,2009,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
@@ -39,7 +40,7 @@ databases = proto service hosts network grp pwd rpc ethers \
others := getent
install-bin := getent
-tests = test-netdb
+tests = test-netdb tst-nss-test1
xtests = bug-erange
include ../Makeconfig
@@ -84,3 +85,14 @@ endif
# a statically-linked program that hasn't already loaded it.
$(services:%=$(objpfx)libnss_%.so): $(common-objpfx)libc.so \
$(common-objpfx)libc_nonshared.a
+
+
+distribute += nss_test1.c
+
+CFLAGS-nss_test1.c = -DNOT_IN_libc=1
+$(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(common-objpfx)libc.so \
+ $(common-objpfx)libc_nonshared.a
+ $(build-module)
+$(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so
+ $(make-link)
+$(objpfx)tst-nss-test1.out: $(objpfx)/libnss_test1.so$(libnss_test1.so-version)
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index 16dadd70ef..0dbb0030e9 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2004, 2006, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2004,2006,2007,2009,2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -87,6 +87,8 @@
# define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
# define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
# define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
+# define CONCAT2(arg1, arg2) CONCAT2_2 (arg1, arg2)
+# define CONCAT2_2(arg1, arg2) arg1##arg2
#endif
#define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
@@ -186,7 +188,8 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
NOT_USENSCD_NAME = 0;
- if (!NOT_USENSCD_NAME)
+ if (!NOT_USENSCD_NAME
+ && !__nss_database_custom[CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)])
{
nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
H_ERRNO_VAR);
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
index 3603762f8e..66604bf94e 100644
--- a/nss/nss_files/files-parse.c
+++ b/nss/nss_files/files-parse.c
@@ -1,5 +1,5 @@
/* Common code for file-based database parsers in nss_files module.
- Copyright (C) 1996-2000, 2003, 2004, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1996-2000,2003,2004,2009,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
@@ -29,7 +29,7 @@
DATABASE -- string of the database file's name ("hosts", "passwd").
ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store
- things pointed to by the resultant `struct STRUCTURE'.
+ things pointed to by the resultant `struct STRUCTURE'.
NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
@@ -229,7 +229,7 @@ strtou32 (const char *nptr, char **endptr, int base)
char **list = parse_list (&line, buf_start, buf_end, '\0', errnop); \
if (list) \
result->TRAILING_LIST_MEMBER = list; \
- else \
+ else \
return -1; /* -1 indicates we ran out of space. */ \
}
diff --git a/nss/nss_test1.c b/nss/nss_test1.c
new file mode 100644
index 0000000000..3beb488fcf
--- /dev/null
+++ b/nss/nss_test1.c
@@ -0,0 +1,154 @@
+#include <errno.h>
+#include <nss.h>
+#include <pthread.h>
+#include <string.h>
+
+
+#define COPY_IF_ROOM(s) \
+ ({ size_t len_ = strlen (s) + 1; \
+ char *start_ = cp; \
+ buflen - (cp - buffer) < len_ \
+ ? NULL \
+ : (cp = mempcpy (cp, s, len_), start_); })
+
+
+/* Password handling. */
+#include <pwd.h>
+
+static struct passwd pwd_data[] =
+ {
+#define PWD(u) \
+ { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \
+ .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
+ .pw_shell = (char *) "*" }
+ PWD (100),
+ PWD (30),
+ PWD (200),
+ PWD (60),
+ PWD (20000)
+ };
+#define npwd_data (sizeof (pwd_data) / sizeof (pwd_data[0]))
+
+static size_t pwd_iter;
+#define CURPWD pwd_data[pwd_iter]
+
+static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+enum nss_status
+_nss_test1_setpwent (int stayopen)
+{
+ pwd_iter = 0;
+ return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_test1_endpwent (void)
+{
+ return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_test1_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
+ int *errnop)
+{
+ char *cp = buffer;
+ int res = NSS_STATUS_SUCCESS;
+
+ pthread_mutex_lock (&pwd_lock);
+
+ if (pwd_iter >= npwd_data)
+ res = NSS_STATUS_NOTFOUND;
+ else
+ {
+ result->pw_name = COPY_IF_ROOM (CURPWD.pw_name);
+ result->pw_passwd = COPY_IF_ROOM (CURPWD.pw_passwd);
+ result->pw_uid = CURPWD.pw_uid;
+ result->pw_gid = CURPWD.pw_gid;
+ result->pw_gecos = COPY_IF_ROOM (CURPWD.pw_gecos);
+ result->pw_dir = COPY_IF_ROOM (CURPWD.pw_dir);
+ result->pw_shell = COPY_IF_ROOM (CURPWD.pw_shell);
+
+ if (result->pw_name == NULL || result->pw_passwd == NULL
+ || result->pw_gecos == NULL || result->pw_dir == NULL
+ || result->pw_shell == NULL)
+ {
+ *errnop = ERANGE;
+ res = NSS_STATUS_TRYAGAIN;
+ }
+
+ ++pwd_iter;
+ }
+
+ pthread_mutex_unlock (&pwd_lock);
+
+ return res;
+}
+
+
+enum nss_status
+_nss_test1_getpwuid_r (uid_t uid, struct passwd *result, char *buffer,
+ size_t buflen, int *errnop)
+{
+ for (size_t idx = 0; idx < npwd_data; ++idx)
+ if (pwd_data[idx].pw_uid == uid)
+ {
+ char *cp = buffer;
+ int res = NSS_STATUS_SUCCESS;
+
+ result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name);
+ result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd);
+ result->pw_uid = pwd_data[idx].pw_uid;
+ result->pw_gid = pwd_data[idx].pw_gid;
+ result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos);
+ result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir);
+ result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell);
+
+ if (result->pw_name == NULL || result->pw_passwd == NULL
+ || result->pw_gecos == NULL || result->pw_dir == NULL
+ || result->pw_shell == NULL)
+ {
+ *errnop = ERANGE;
+ res = NSS_STATUS_TRYAGAIN;
+ }
+
+ return res;
+ }
+
+ return NSS_STATUS_NOTFOUND;
+}
+
+
+enum nss_status
+_nss_test1_getpwnam_r (const char *name, struct passwd *result, char *buffer,
+ size_t buflen, int *errnop)
+{
+ for (size_t idx = 0; idx < npwd_data; ++idx)
+ if (strcmp (pwd_data[idx].pw_name, name) == 0)
+ {
+ char *cp = buffer;
+ int res = NSS_STATUS_SUCCESS;
+
+ result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name);
+ result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd);
+ result->pw_uid = pwd_data[idx].pw_uid;
+ result->pw_gid = pwd_data[idx].pw_gid;
+ result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos);
+ result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir);
+ result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell);
+
+ if (result->pw_name == NULL || result->pw_passwd == NULL
+ || result->pw_gecos == NULL || result->pw_dir == NULL
+ || result->pw_shell == NULL)
+ {
+ *errnop = ERANGE;
+ res = NSS_STATUS_TRYAGAIN;
+ }
+
+ return res;
+ }
+
+ return NSS_STATUS_NOTFOUND;
+}
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index da94ca9838..92e6f5f91f 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1999, 2001-2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1996-1999,2001-2007,2009,2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -71,6 +71,9 @@ static const struct
};
#define ndatabases (sizeof (databases) / sizeof (databases[0]))
+/* Flags whether custom rules for database is set. */
+bool __nss_database_custom[NSS_DBSIDX_max];
+
__libc_lock_define_initialized (static, lock)
@@ -265,6 +268,7 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
/* Install new rules. */
*databases[cnt].dbp = new_db;
+ __nss_database_custom[cnt] = true;
__libc_lock_unlock (lock);
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index b80edef651..ae5657e889 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007
+/* Copyright (C) 1996-1999,2001,2002,2003,2004,2007,2010
Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -28,6 +28,7 @@
#include <resolv.h>
#include <search.h>
#include <dlfcn.h>
+#include <stdbool.h>
/* Actions performed after lookup finished. */
typedef enum
@@ -96,6 +97,19 @@ typedef struct name_database
} name_database;
+/* Indices into DATABASES in nsswitch.c and __NSS_DATABASE_CUSTOM. */
+enum
+ {
+#define DEFINE_DATABASE(arg) NSS_DBSIDX_##arg,
+#include "databases.def"
+#undef DEFINE_DATABASE
+ NSS_DBSIDX_max
+ };
+
+/* Flags whether custom rules for database is set. */
+extern bool __nss_database_custom[NSS_DBSIDX_max];
+
+
/* Interface functions for NSS. */
/* Get the data structure representing the specified database.
diff --git a/nss/tst-nss-test1.c b/nss/tst-nss-test1.c
new file mode 100644
index 0000000000..4e443d4539
--- /dev/null
+++ b/nss/tst-nss-test1.c
@@ -0,0 +1,72 @@
+#include <nss.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ int retval = 0;
+
+ __nss_configure_lookup ("passwd", "test1");
+
+ static const unsigned int pwdids[] = { 100, 30, 200, 60, 20000 };
+#define npwdids (sizeof (pwdids) / sizeof (pwdids[0]))
+ setpwent ();
+
+ const unsigned int *np = pwdids;
+ for (struct passwd *p = getpwent (); p != NULL; ++np, p = getpwent ())
+ if (p->pw_uid != *np || strncmp (p->pw_name, "name", 4) != 0
+ || atol (p->pw_name + 4) != *np)
+ {
+ printf ("passwd entry %ju wrong (%s, %u)\n",
+ np - pwdids, p->pw_name, p->pw_uid);
+ retval = 1;
+ break;
+ }
+
+ endpwent ();
+
+ for (int i = npwdids - 1; i >= 0; --i)
+ {
+ char buf[30];
+ snprintf (buf, sizeof (buf), "name%u", pwdids[i]);
+
+ struct passwd *p = getpwnam (buf);
+ if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0)
+ {
+ printf ("passwd entry \"%s\" wrong\n", buf);
+ retval = 1;
+ }
+
+ p = getpwuid (pwdids[i]);
+ if (p == NULL || p->pw_uid != pwdids[i] || strcmp (buf, p->pw_name) != 0)
+ {
+ printf ("passwd entry %u wrong\n", pwdids[i]);
+ retval = 1;
+ }
+
+ snprintf (buf, sizeof (buf), "name%u", pwdids[i] + 1);
+
+ p = getpwnam (buf);
+ if (p != NULL)
+ {
+ printf ("passwd entry \"%s\" wrong\n", buf);
+ retval = 1;
+ }
+
+ p = getpwuid (pwdids[i] + 1);
+ if (p != NULL)
+ {
+ printf ("passwd entry %u wrong\n", pwdids[i] + 1);
+ retval = 1;
+ }
+ }
+
+ return retval;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"