about summary refs log tree commit diff
path: root/nss
diff options
context:
space:
mode:
Diffstat (limited to 'nss')
-rw-r--r--nss/Makefile1
-rw-r--r--nss/Versions2
-rw-r--r--nss/XXX-lookup.c17
-rw-r--r--nss/databases.def3
-rw-r--r--nss/grp-lookup.c1
-rw-r--r--nss/hosts-lookup.c1
-rw-r--r--nss/key-lookup.c1
-rw-r--r--nss/network-lookup.c1
-rw-r--r--nss/nss_compat/compat-grp.c2
-rw-r--r--nss/nss_compat/compat-initgroups.c2
-rw-r--r--nss/nss_compat/compat-pwd.c2
-rw-r--r--nss/nss_compat/compat-spwd.c3
-rw-r--r--nss/nss_database.c38
-rw-r--r--nss/nss_database.h5
-rw-r--r--nss/nss_module.c20
-rw-r--r--nss/nss_test.h7
-rw-r--r--nss/nss_test1.c93
-rw-r--r--nss/nsswitch.c40
-rw-r--r--nss/nsswitch.h9
-rw-r--r--nss/pwd-lookup.c1
-rw-r--r--nss/sgrp-lookup.c2
-rw-r--r--nss/spwd-lookup.c2
-rw-r--r--nss/tst-nss-compat1.c81
-rw-r--r--nss/tst-nss-compat1.root/etc/group1
-rw-r--r--nss/tst-nss-compat1.root/etc/nsswitch.conf3
-rw-r--r--nss/tst-nss-compat1.root/etc/passwd3
-rw-r--r--nss/tst-nss-compat1.root/etc/shadow2
-rw-r--r--nss/tst-nss-compat1.root/tst-nss-compat1.script1
28 files changed, 248 insertions, 96 deletions
diff --git a/nss/Makefile b/nss/Makefile
index 0906202db9..71fbe583bf 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -63,6 +63,7 @@ tests			= test-netdb test-digits-dots tst-nss-getpwent bug17079 \
 xtests			= bug-erange
 
 tests-container = \
+			  tst-nss-compat1 \
 			  tst-nss-test3 \
 			  tst-nss-files-hosts-long \
 			  tst-nss-db-endpwent \
diff --git a/nss/Versions b/nss/Versions
index 71703750bf..fdddea104c 100644
--- a/nss/Versions
+++ b/nss/Versions
@@ -17,7 +17,7 @@ libc {
 
     __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2;
     __nss_services_lookup2; __nss_next2; __nss_lookup;
-    __nss_hash; __nss_database_lookup2;
+    __nss_hash; __nss_database_get;
     __nss_files_fopen; __nss_readline; __nss_parse_line_result;
   }
 }
diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c
index 48fc7b92fc..f1c97f7c8e 100644
--- a/nss/XXX-lookup.c
+++ b/nss/XXX-lookup.c
@@ -37,27 +37,20 @@
 #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
 #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
 
+#define DATABASE_NAME_ID CONCAT2_1 (nss_database_, DATABASE_NAME)
+#define CONCAT2_1(Pre, Name) CONCAT2_2 (Pre, Name)
+#define CONCAT2_2(Pre, Name) Pre##Name
+
 #define DATABASE_NAME_SYMBOL CONCAT3_1 (__nss_, DATABASE_NAME, _database)
 #define DATABASE_NAME_STRING STRINGIFY1 (DATABASE_NAME)
 #define STRINGIFY1(Name) STRINGIFY2 (Name)
 #define STRINGIFY2(Name) #Name
 
-#ifdef ALTERNATE_NAME
-#define ALTERNATE_NAME_STRING STRINGIFY1 (ALTERNATE_NAME)
-#else
-#define ALTERNATE_NAME_STRING NULL
-#endif
-
-#ifndef DEFAULT_CONFIG
-#define DEFAULT_CONFIG NULL
-#endif
-
 int
 DB_LOOKUP_FCT (nss_action_list *ni, const char *fct_name, const char *fct2_name,
 	       void **fctp)
 {
-  if (__nss_database_lookup2 (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING,
-			      DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0)
+  if (! __nss_database_get (DATABASE_NAME_ID, &DATABASE_NAME_SYMBOL))
     return -1;
 
   *ni = DATABASE_NAME_SYMBOL;
diff --git a/nss/databases.def b/nss/databases.def
index df5fab4168..3dc95648a8 100644
--- a/nss/databases.def
+++ b/nss/databases.def
@@ -23,17 +23,20 @@
 DEFINE_DATABASE (aliases)
 DEFINE_DATABASE (ethers)
 DEFINE_DATABASE (group)
+DEFINE_DATABASE (group_compat)
 DEFINE_DATABASE (gshadow)
 DEFINE_DATABASE (hosts)
 DEFINE_DATABASE (initgroups)
 DEFINE_DATABASE (netgroup)
 DEFINE_DATABASE (networks)
 DEFINE_DATABASE (passwd)
+DEFINE_DATABASE (passwd_compat)
 DEFINE_DATABASE (protocols)
 DEFINE_DATABASE (publickey)
 DEFINE_DATABASE (rpc)
 DEFINE_DATABASE (services)
 DEFINE_DATABASE (shadow)
+DEFINE_DATABASE (shadow_compat)
 
 /*
    Local Variables:
diff --git a/nss/grp-lookup.c b/nss/grp-lookup.c
index 7099544be5..034fa2ab7f 100644
--- a/nss/grp-lookup.c
+++ b/nss/grp-lookup.c
@@ -19,6 +19,5 @@
 #include <config.h>
 
 #define DATABASE_NAME group
-#define DEFAULT_CONFIG "files"
 
 #include "XXX-lookup.c"
diff --git a/nss/hosts-lookup.c b/nss/hosts-lookup.c
index c96b60ed66..1acafd01cd 100644
--- a/nss/hosts-lookup.c
+++ b/nss/hosts-lookup.c
@@ -17,6 +17,5 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define DATABASE_NAME hosts
-#define DEFAULT_CONFIG "dns [!UNAVAIL=return] files"
 
 #include "XXX-lookup.c"
diff --git a/nss/key-lookup.c b/nss/key-lookup.c
index 60d803ded5..aa267d36f9 100644
--- a/nss/key-lookup.c
+++ b/nss/key-lookup.c
@@ -17,6 +17,5 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define DATABASE_NAME publickey
-#define DEFAULT_CONFIG "nis nisplus"
 
 #include "XXX-lookup.c"
diff --git a/nss/network-lookup.c b/nss/network-lookup.c
index 8c1eeb3c84..eed4dc3d0f 100644
--- a/nss/network-lookup.c
+++ b/nss/network-lookup.c
@@ -17,6 +17,5 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define DATABASE_NAME networks
-#define DEFAULT_CONFIG "dns [!UNAVAIL=return] files"
 
 #include "XXX-lookup.c"
diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c
index eb4c68d5d4..aaf35e75b4 100644
--- a/nss/nss_compat/compat-grp.c
+++ b/nss/nss_compat/compat-grp.c
@@ -81,7 +81,7 @@ static bool in_blacklist (const char *, int, ent_t *);
 static void
 init_nss_interface (void)
 {
-  if (__nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0)
+  if (__nss_database_get (nss_database_group_compat, &ni))
     {
       setgrent_impl = __nss_lookup_function (ni, "setgrent");
       getgrnam_r_impl = __nss_lookup_function (ni, "getgrnam_r");
diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c
index cfd36b64b8..c3b065c931 100644
--- a/nss/nss_compat/compat-initgroups.c
+++ b/nss/nss_compat/compat-initgroups.c
@@ -91,7 +91,7 @@ init_nss_interface (void)
 
   /* Retest.  */
   if (ni == NULL
-      && __nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0)
+      && __nss_database_get (nss_database_group_compat, &ni))
     {
       initgroups_dyn_impl = __nss_lookup_function (ni, "initgroups_dyn");
       getgrnam_r_impl = __nss_lookup_function (ni, "getgrnam_r");
diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c
index f536754559..64d708ff63 100644
--- a/nss/nss_compat/compat-pwd.c
+++ b/nss/nss_compat/compat-pwd.c
@@ -91,7 +91,7 @@ static bool in_blacklist (const char *, int, ent_t *);
 static void
 init_nss_interface (void)
 {
-  if (__nss_database_lookup2 ("passwd_compat", NULL, "nis", &ni) >= 0)
+  if (__nss_database_get (nss_database_passwd_compat, &ni))
     {
       setpwent_impl = __nss_lookup_function (ni, "setpwent");
       getpwnam_r_impl = __nss_lookup_function (ni, "getpwnam_r");
diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c
index 5c91f9572a..b548dfbee1 100644
--- a/nss/nss_compat/compat-spwd.c
+++ b/nss/nss_compat/compat-spwd.c
@@ -88,8 +88,7 @@ static bool in_blacklist (const char *, int, ent_t *);
 static void
 init_nss_interface (void)
 {
-  if (__nss_database_lookup2 ("shadow_compat", "passwd_compat",
-			      "nis", &ni) >= 0)
+  if (__nss_database_get (nss_database_shadow_compat, &ni))
     {
       setspent_impl = __nss_lookup_function (ni, "setspent");
       getspnam_r_impl = __nss_lookup_function (ni, "getspnam_r");
diff --git a/nss/nss_database.c b/nss/nss_database.c
index fb72d0cc03..1e11294406 100644
--- a/nss/nss_database.c
+++ b/nss/nss_database.c
@@ -93,13 +93,16 @@ enum nss_database_default
 static const char per_database_defaults[NSS_DATABASE_COUNT] =
   {
    [nss_database_group] = nss_database_default_compat,
+   [nss_database_group_compat] = nss_database_default_nis,
    [nss_database_gshadow] = nss_database_default_files,
    [nss_database_hosts] = nss_database_default_dns,
    [nss_database_initgroups] = nss_database_default_none,
    [nss_database_networks] = nss_database_default_dns,
    [nss_database_passwd] = nss_database_default_compat,
+   [nss_database_passwd_compat] = nss_database_default_nis,
    [nss_database_publickey] = nss_database_default_nis_nisplus,
    [nss_database_shadow] = nss_database_default_compat,
+   [nss_database_shadow_compat] = nss_database_default_nis,
   };
 
 struct nss_database_default_cache
@@ -166,13 +169,12 @@ nss_database_select_default (struct nss_database_default_cache *cache,
       assert (errno == ENOMEM);
       return false;
     }
-  else
-    return true;
+  return true;
 }
 
 /* database_name must be large enough for each individual name plus a
    null terminator.  */
-typedef char database_name[11];
+typedef char database_name[14];
 #define DEFINE_DATABASE(name) \
   _Static_assert (sizeof (#name) <= sizeof (database_name), #name);
 #include "databases.def"
@@ -323,14 +325,43 @@ nss_database_reload (struct nss_database_data *staging,
     /* No other threads have access to fp.  */
     __fsetlocking (fp, FSETLOCKING_BYCALLER);
 
+  /* We start with all of *staging pointing to NULL.  */
+
   bool ok = true;
   if (fp != NULL)
     ok = nss_database_reload_1 (staging, fp);
 
+  /* Now we have non-NULL entries where the user explictly listed the
+     service in nsswitch.conf.  */
+
   /* Apply defaults.  */
   if (ok)
     {
       struct nss_database_default_cache cache = { };
+
+      /* These three default to other services if the user listed the
+	 other service.  */
+
+      /* "shadow_compat" defaults to "passwd_compat" if only the
+	 latter is given.  */
+      if (staging->services[nss_database_shadow_compat] == NULL)
+	staging->services[nss_database_shadow_compat] =
+	  staging->services[nss_database_passwd_compat];
+
+      /* "shadow" defaults to "passwd" if only the latter is
+	 given.  */
+      if (staging->services[nss_database_shadow] == NULL)
+	staging->services[nss_database_shadow] =
+	  staging->services[nss_database_passwd];
+
+      /* "gshadow" defaults to "group" if only the latter is
+	 given.  */
+      if (staging->services[nss_database_gshadow] == NULL)
+	staging->services[nss_database_gshadow] =
+	  staging->services[nss_database_group];
+
+      /* For anything still unspecified, load the default configs.  */
+
       for (int i = 0; i < NSS_DATABASE_COUNT; ++i)
         if (staging->services[i] == NULL)
           {
@@ -440,6 +471,7 @@ __nss_database_get (enum nss_database db, nss_action_list *actions)
   struct nss_database_state *local = nss_database_state_get ();
   return nss_database_check_reload_and_get (local, actions, db);
 }
+libc_hidden_def (__nss_database_get)
 
 nss_action_list
 __nss_database_get_noreload (enum nss_database db)
diff --git a/nss/nss_database.h b/nss/nss_database.h
index 1f827e6def..d4b23b5295 100644
--- a/nss/nss_database.h
+++ b/nss/nss_database.h
@@ -52,12 +52,11 @@ enum nss_database
   NSS_DATABASE_COUNT
 };
 
-
 /* Looks up the action list for DB and stores it in *ACTIONS.  Returns
    true on success or false on failure.  Success can mean that
    *ACTIONS is NULL.  */
-bool __nss_database_get (enum nss_database db, nss_action_list *actions)
-  attribute_hidden;
+bool __nss_database_get (enum nss_database db, nss_action_list *actions);
+libc_hidden_proto (__nss_database_get)
 
 /* Like __nss_database_get, but does not reload /etc/nsswitch.conf
    from disk.  This assumes that there has been a previous successful
diff --git a/nss/nss_module.c b/nss/nss_module.c
index 6c5f341f3e..60c070c851 100644
--- a/nss/nss_module.c
+++ b/nss/nss_module.c
@@ -31,14 +31,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef LINK_OBSOLETE_NSL
-# define DEFAULT_CONFIG    "compat [NOTFOUND=return] files"
-# define DEFAULT_DEFCONFIG "nis [NOTFOUND=return] files"
-#else
-# define DEFAULT_CONFIG    "files"
-# define DEFAULT_DEFCONFIG "files"
-#endif
-
 /* Suffix after .so of NSS service modules.  This is a bit of magic,
    but we assume LIBNSS_FILES_SO looks like "libnss_files.so.2" and we
    want a pointer to the ".2" part.  We have no API to extract this
@@ -292,11 +284,11 @@ __nss_module_get_function (struct nss_module *module, const char *name)
 #if defined SHARED && defined USE_NSCD
 /* Load all libraries for the service.  */
 static void
-nss_load_all_libraries (const char *service, const char *def)
+nss_load_all_libraries (enum nss_database service)
 {
   nss_action_list ni = NULL;
 
-  if (__nss_database_lookup2 (service, NULL, def, &ni) == 0)
+  if (__nss_database_get (service, &ni))
     while (ni->module != NULL)
       {
         __nss_module_load (ni->module);
@@ -323,10 +315,10 @@ __nss_disable_nscd (void (*cb) (size_t, struct traced_file *))
   is_nscd = true;
 
   /* Find all the relevant modules so that the init functions are called.  */
-  nss_load_all_libraries ("passwd", DEFAULT_CONFIG);
-  nss_load_all_libraries ("group", DEFAULT_CONFIG);
-  nss_load_all_libraries ("hosts", "dns [!UNAVAIL=return] files");
-  nss_load_all_libraries ("services", NULL);
+  nss_load_all_libraries (nss_database_passwd);
+  nss_load_all_libraries (nss_database_group);
+  nss_load_all_libraries (nss_database_hosts);
+  nss_load_all_libraries (nss_database_services);
 
   /* Make sure NSCD purges its cache if nsswitch.conf changes.  */
   init_traced_file (&pwd_traced_file.file, _PATH_NSSWITCH_CONF, 0);
diff --git a/nss/nss_test.h b/nss/nss_test.h
index f8b81c27a7..db3d617585 100644
--- a/nss/nss_test.h
+++ b/nss/nss_test.h
@@ -33,11 +33,13 @@
 
 #include <pwd.h>
 #include <grp.h>
+#include <shadow.h>
 #include <netdb.h>
 
 typedef struct test_tables {
   struct passwd *pwd_table;
   struct group *grp_table;
+  struct spwd *spwd_table;
   struct hostent *host_table;
 } test_tables;
 
@@ -46,10 +48,12 @@ extern void _nss_test2_init_hook (test_tables *) __attribute__((weak));
 
 #define PWD_LAST()    { .pw_name = NULL, .pw_uid = 0 }
 #define GRP_LAST()    { .gr_name = NULL, .gr_gid = 0 }
+#define SPWD_LAST()    { .sp_namp = NULL, .sp_pwdp = NULL }
 #define HOST_LAST()    { .h_name = NULL, .h_aliases = NULL, .h_length = 0, .h_addr_list = NULL }
 
 #define PWD_ISLAST(p)    ((p)->pw_name == NULL && (p)->pw_uid == 0)
 #define GRP_ISLAST(g)    ((g)->gr_name == NULL && (g)->gr_gid == 0)
+#define SPWD_ISLAST(s)    ((s)->sp_namp == NULL && (s)->sp_pwdp == 0)
 #define HOST_ISLAST(h)    ((h)->h_name == NULL && (h)->h_length == 0)
 
 /* Macros to fill in the tables easily.  */
@@ -76,6 +80,9 @@ extern void _nss_test2_init_hook (test_tables *) __attribute__((weak));
     { .gr_name = (char *) n, .gr_passwd = (char *) "*", .gr_gid = u, \
       .gr_mem = (char **) m }
 
+#define SPWD(u) \
+    { .sp_namp = (char *) "name" #u, .sp_pwdp = (char *) "passwd" #u }
+
 #define HOST(u)								\
     { .h_name = (char *) "name" #u, .h_aliases = NULL, .h_addrtype = u,	\
       .h_length = 4,							\
diff --git a/nss/nss_test1.c b/nss/nss_test1.c
index f73c7a6cd8..f8d81831ee 100644
--- a/nss/nss_test1.c
+++ b/nss/nss_test1.c
@@ -66,6 +66,9 @@ static int npwd_data = default_npwd_data;
 static struct group *grp_data = NULL;
 static int ngrp_data = 0;
 
+static struct spwd *spwd_data = NULL;
+static int nspwd_data = 0;
+
 static struct hostent *host_data = NULL;
 static int nhost_data = 0;
 
@@ -102,6 +105,13 @@ init(void)
 	    ;
 	  ngrp_data = i;
 	}
+      if (t.spwd_table)
+	{
+	  spwd_data = t.spwd_table;
+	  for (i=0; ! SPWD_ISLAST(& spwd_data[i]); i++)
+	    ;
+	  nspwd_data = i;
+	}
       if (t.host_table)
 	{
 	  host_data = t.host_table;
@@ -324,6 +334,89 @@ NAME(getgrnam_r) (const char *name, struct group *result, char *buffer,
 }
 
 /* -------------------------------------------------- */
+/* Shadow password handling.  */
+
+static size_t spwd_iter;
+#define CURSPWD spwd_data[spwd_iter]
+
+static pthread_mutex_t spwd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+enum nss_status
+NAME(setspent) (int stayopen)
+{
+  init();
+  spwd_iter = 0;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+NAME(endspwent) (void)
+{
+  init();
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+copy_shadow (struct spwd *result, struct spwd *local,
+	    char *buffer, size_t buflen, int *errnop)
+{
+  struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
+
+  result->sp_namp = alloc_buffer_maybe_copy_string (&buf, local->sp_namp);
+  result->sp_pwdp = alloc_buffer_maybe_copy_string (&buf, local->sp_pwdp);
+  result->sp_lstchg = local->sp_lstchg;
+  result->sp_min = local->sp_min;
+  result->sp_max = local->sp_max;
+  result->sp_warn = local->sp_warn;
+  result->sp_inact = local->sp_inact;
+  result->sp_expire = local->sp_expire;
+  result->sp_flag = local->sp_flag;
+
+  if (alloc_buffer_has_failed (&buf))
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+NAME(getspent_r) (struct spwd *result, char *buffer, size_t buflen,
+		  int *errnop)
+{
+  int res = NSS_STATUS_SUCCESS;
+
+  init();
+  pthread_mutex_lock (&spwd_lock);
+
+  if (spwd_iter >= nspwd_data)
+    res = NSS_STATUS_NOTFOUND;
+  else
+    {
+      res = copy_shadow (result, &CURSPWD, buffer, buflen, errnop);
+      ++spwd_iter;
+    }
+
+  pthread_mutex_unlock (&spwd_lock);
+
+  return res;
+}
+
+enum nss_status
+NAME(getspnam_r) (const char *name, struct spwd *result, char *buffer,
+		  size_t buflen, int *errnop)
+{
+  init();
+  for (size_t idx = 0; idx < nspwd_data; ++idx)
+    if (strcmp (spwd_data[idx].sp_namp, name) == 0)
+      return copy_shadow (result, &spwd_data[idx], buffer, buflen, errnop);
+
+  return NSS_STATUS_NOTFOUND;
+}
+
+/* -------------------------------------------------- */
 /* Host handling.  */
 
 static size_t host_iter;
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 46f232d720..6b7d4c780b 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -51,53 +51,13 @@
 #undef DEFINE_DATABASE
 
 
-#undef DEFINE_DATABASE
-#define DEFINE_DATABASE(name)  #name,
-static const char * database_names[] = {
-#include "databases.def"
-  NULL
-};
-
 #ifdef USE_NSCD
 /* Flags whether custom rules for database is set.  */
 bool __nss_database_custom[NSS_DBSIDX_max];
 #endif
 
-
 /*__libc_lock_define_initialized (static, lock)*/
 
-/* -1 == database not found
-    0 == database entry pointer stored */
-int
-__nss_database_lookup2 (const char *database, const char *alternate_name,
-			const char *defconfig, nss_action_list *ni)
-{
-  int database_id;
-
-  for (database_id = 0; database_names[database_id]; database_id++)
-    if (strcmp (database_names[database_id], database) == 0)
-	break;
-
-  if (database_names[database_id] == NULL)
-    return -1;
-
-  /* If *NI is NULL, the database was not mentioned in nsswitch.conf.
-     If *NI is not NULL, but *NI->module is NULL, the database was in
-     nsswitch.conf but listed no actions.  We test for the former.  */
-  if (__nss_database_get (database_id, ni) && *ni != NULL)
-    {
-      /* Success.  */
-      return 0;
-    }
-  else
-    {
-      /* Failure.  */
-      return -1;
-    }
-}
-libc_hidden_def (__nss_database_lookup2)
-
-
 /* -1 == not found
     0 == function found
     1 == finished */
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index c483bbd891..ab782b605e 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -88,15 +88,6 @@ extern bool __nss_database_custom[NSS_DBSIDX_max] attribute_hidden;
 
 /* Interface functions for NSS.  */
 
-/* Get the data structure representing the specified database.
-   If there is no configuration for this database in the file,
-   parse a service list from DEFCONFIG and use that.  More
-   than one function can use the database.  */
-extern int __nss_database_lookup2 (const char *database,
-				   const char *alternative_name,
-				   const char *defconfig, struct nss_action **ni);
-libc_hidden_proto (__nss_database_lookup2)
-
 /* Put first function with name FCT_NAME for SERVICE in FCTP.  The
    position is remembered in NI.  The function returns a value < 0 if
    an error occurred or no such function exists.  */
diff --git a/nss/pwd-lookup.c b/nss/pwd-lookup.c
index 4f5c47422f..5ec8a8b485 100644
--- a/nss/pwd-lookup.c
+++ b/nss/pwd-lookup.c
@@ -19,6 +19,5 @@
 #include <config.h>
 
 #define DATABASE_NAME passwd
-#define DEFAULT_CONFIG "files"
 
 #include "XXX-lookup.c"
diff --git a/nss/sgrp-lookup.c b/nss/sgrp-lookup.c
index 6df4c49ff1..9a2becc202 100644
--- a/nss/sgrp-lookup.c
+++ b/nss/sgrp-lookup.c
@@ -17,7 +17,5 @@
    <https://www.gnu.org/licenses/>.  */
 
 #define DATABASE_NAME gshadow
-#define ALTERNATE_NAME group
-#define DEFAULT_CONFIG "files"
 
 #include "XXX-lookup.c"
diff --git a/nss/spwd-lookup.c b/nss/spwd-lookup.c
index e3c8c1df7b..e9e661af12 100644
--- a/nss/spwd-lookup.c
+++ b/nss/spwd-lookup.c
@@ -19,7 +19,5 @@
 #include <config.h>
 
 #define DATABASE_NAME shadow
-#define ALTERNATE_NAME passwd
-#define DEFAULT_CONFIG "files"
 
 #include "XXX-lookup.c"
diff --git a/nss/tst-nss-compat1.c b/nss/tst-nss-compat1.c
new file mode 100644
index 0000000000..670cffe538
--- /dev/null
+++ b/nss/tst-nss-compat1.c
@@ -0,0 +1,81 @@
+/* Test error checking for group entries.
+   Copyright (C) 2021 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <shadow.h>
+
+#include <support/support.h>
+#include <support/check.h>
+
+#include "nss_test.h"
+
+static struct passwd pwd_table[] = {
+    PWD (100),
+    PWD (30),
+    PWD_LAST ()
+  };
+
+static struct spwd spwd_table[] = {
+    SPWD (100),
+    SPWD (30),
+    SPWD_LAST ()
+  };
+
+void
+_nss_test1_init_hook(test_tables *t)
+{
+  t->pwd_table = pwd_table;
+  t->spwd_table = spwd_table;
+}
+
+static int
+do_test (void)
+{
+  struct passwd *p = NULL;
+  struct spwd *s = NULL;
+  struct group *g = NULL;
+
+  /* Test that compat-to-test works.  */
+  p = getpwuid (100);
+  if (p == NULL)
+    FAIL_EXIT1("getpwuid-compat-test1 p");
+  else if (strcmp (p->pw_name, "name100") != 0)
+    FAIL_EXIT1("getpwuid-compat-test1 name100");
+
+  /* Shadow compat should use passwd via the alternate name.  */
+  s = getspnam ("name30");
+  if (s == NULL)
+    FAIL_EXIT1("getspnam-compat-test1 s");
+  else if (strcmp (s->sp_namp, "name30") != 0)
+    FAIL_EXIT1("getpwuid-compat-test1 name30");
+
+  /* Test that internal defconfig works.  */
+  g = getgrgid (100);
+  if (g == NULL)
+    FAIL_EXIT1("getgrgid-compat-null");
+  if (strcmp (g->gr_name, "wilma") != 0)
+    FAIL_EXIT1("getgrgid-compat-name");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nss/tst-nss-compat1.root/etc/group b/nss/tst-nss-compat1.root/etc/group
new file mode 100644
index 0000000000..ee467c7950
--- /dev/null
+++ b/nss/tst-nss-compat1.root/etc/group
@@ -0,0 +1 @@
+wilma:x:100:
diff --git a/nss/tst-nss-compat1.root/etc/nsswitch.conf b/nss/tst-nss-compat1.root/etc/nsswitch.conf
new file mode 100644
index 0000000000..7fe69d5ffa
--- /dev/null
+++ b/nss/tst-nss-compat1.root/etc/nsswitch.conf
@@ -0,0 +1,3 @@
+passwd : compat
+passwd_compat : test1
+
diff --git a/nss/tst-nss-compat1.root/etc/passwd b/nss/tst-nss-compat1.root/etc/passwd
new file mode 100644
index 0000000000..84635587bd
--- /dev/null
+++ b/nss/tst-nss-compat1.root/etc/passwd
@@ -0,0 +1,3 @@
+name5:x:5:555:name5 for testing:/home/name5:/bin/nologin
++name100
++name30
diff --git a/nss/tst-nss-compat1.root/etc/shadow b/nss/tst-nss-compat1.root/etc/shadow
new file mode 100644
index 0000000000..cba3152172
--- /dev/null
+++ b/nss/tst-nss-compat1.root/etc/shadow
@@ -0,0 +1,2 @@
++name100
++name30
diff --git a/nss/tst-nss-compat1.root/tst-nss-compat1.script b/nss/tst-nss-compat1.root/tst-nss-compat1.script
new file mode 100644
index 0000000000..fe6e863f01
--- /dev/null
+++ b/nss/tst-nss-compat1.root/tst-nss-compat1.script
@@ -0,0 +1 @@
+cp $B/nss/libnss_test1.so $L/libnss_test1.so.2