forked from pool/glibc
Andreas Schwab
47a70fb50a
- nss-database-check-reload.patch: nsswitch: return result when nss database is locked (BZ #27343) - nss-load-chroot.patch: nss: Re-enable NSS module loading after chroot (bsc#1182323, BZ #27389) - x86-isa-level.patch: x86: Set minimum x86-64 level marker (bsc#1182522, BZ #27318) - nss-database-lookup.patch: nss: fix nss_database_lookup2's alternate handling (bsc#1182247, BZ #27416) - nss-revert-api.patch: remove - nscd-netgroupcache.patch: nscd: Fix double free in netgroupcache (CVE-2021-27645, bsc#1182733, BZ #27462) OBS-URL: https://build.opensuse.org/request/show/877767 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=585
840 lines
28 KiB
Diff
840 lines
28 KiB
Diff
From: DJ Delorie via Libc-alpha <libc-alpha@sourceware.org>
|
|
Subject: [PATCH v4] nss: fix nss_database_lookup2's alternate handling [BZ
|
|
#27416]
|
|
Date: Fri, 05 Mar 2021 20:29:31 -0500
|
|
|
|
__nss_database_lookup2's extra arguments were left unused in the
|
|
nsswitch reloading patch set; this broke compat (default config
|
|
ignored) and shadow files (secondary name ignored) which relies on
|
|
these fallbacks.
|
|
|
|
This patch adds in the previous behavior by correcting the
|
|
initialization of the database list to reflect the fallbacks. This
|
|
means that the nss_database_lookup2 interface no longer needs to be
|
|
passed the fallback info, so API and callers were adjusted.
|
|
|
|
Since all callers needed to be edited anyway, the calls were changed
|
|
from __nss_database_lookup2 to the faster __nss_database_get. This
|
|
was an intended optimization which was deferred during the initial
|
|
lookup changes to avoid touching so many files.
|
|
|
|
The test case verifies that compat targets work (passwd) and that the
|
|
default configuration works (group). Tested on x86-64.
|
|
---
|
|
nscd/aicache.c | 4 +-
|
|
nscd/initgrcache.c | 3 +-
|
|
nscd/netgroupcache.c | 2 +-
|
|
nss/Makefile | 1 +
|
|
nss/Versions | 2 +-
|
|
nss/XXX-lookup.c | 17 +---
|
|
nss/databases.def | 3 +
|
|
nss/grp-lookup.c | 1 -
|
|
nss/hosts-lookup.c | 1 -
|
|
nss/key-lookup.c | 1 -
|
|
nss/network-lookup.c | 1 -
|
|
nss/nss_compat/compat-grp.c | 2 +-
|
|
nss/nss_compat/compat-initgroups.c | 2 +-
|
|
nss/nss_compat/compat-pwd.c | 2 +-
|
|
nss/nss_compat/compat-spwd.c | 3 +-
|
|
nss/nss_database.c | 35 ++++++-
|
|
nss/nss_database.h | 5 +-
|
|
nss/nss_module.c | 20 ++--
|
|
nss/nss_test.h | 7 ++
|
|
nss/nss_test1.c | 93 +++++++++++++++++++
|
|
nss/nsswitch.c | 25 +----
|
|
nss/nsswitch.h | 7 +-
|
|
nss/pwd-lookup.c | 1 -
|
|
nss/sgrp-lookup.c | 2 -
|
|
nss/spwd-lookup.c | 2 -
|
|
nss/tst-nss-compat1.c | 81 ++++++++++++++++
|
|
nss/tst-nss-compat1.root/etc/group | 1 +
|
|
nss/tst-nss-compat1.root/etc/nsswitch.conf | 3 +
|
|
nss/tst-nss-compat1.root/etc/passwd | 3 +
|
|
nss/tst-nss-compat1.root/etc/shadow | 2 +
|
|
.../tst-nss-compat1.script | 1 +
|
|
sysdeps/posix/getaddrinfo.c | 4 +-
|
|
32 files changed, 256 insertions(+), 81 deletions(-)
|
|
create mode 100644 nss/tst-nss-compat1.c
|
|
create mode 100644 nss/tst-nss-compat1.root/etc/group
|
|
create mode 100644 nss/tst-nss-compat1.root/etc/nsswitch.conf
|
|
create mode 100644 nss/tst-nss-compat1.root/etc/passwd
|
|
create mode 100644 nss/tst-nss-compat1.root/etc/shadow
|
|
create mode 100644 nss/tst-nss-compat1.root/tst-nss-compat1.script
|
|
|
|
Index: glibc-2.33/nscd/aicache.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nscd/aicache.c
|
|
+++ glibc-2.33/nscd/aicache.c
|
|
@@ -77,9 +77,7 @@ addhstaiX (struct database_dyn *db, int
|
|
int rc4 = 0;
|
|
int herrno = 0;
|
|
|
|
- no_more = __nss_database_lookup2 ("hosts", NULL,
|
|
- "dns [!UNAVAIL=return] files",
|
|
- &nip);
|
|
+ no_more = (__nss_database_get (nss_database_hosts, &nip) == false);
|
|
|
|
/* Initialize configurations. */
|
|
struct resolv_context *ctx = __resolv_context_get ();
|
|
Index: glibc-2.33/nscd/initgrcache.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nscd/initgrcache.c
|
|
+++ glibc-2.33/nscd/initgrcache.c
|
|
@@ -82,8 +82,7 @@ addinitgroupsX (struct database_dyn *db,
|
|
int no_more;
|
|
|
|
if (group_database == NULL)
|
|
- no_more = __nss_database_lookup2 ("group", NULL, "files",
|
|
- &group_database);
|
|
+ no_more = (__nss_database_get (nss_database_group, &group_database) == false);
|
|
else
|
|
no_more = 0;
|
|
nip = group_database;
|
|
Index: glibc-2.33/nscd/netgroupcache.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nscd/netgroupcache.c
|
|
+++ glibc-2.33/nscd/netgroupcache.c
|
|
@@ -143,7 +143,7 @@ addgetnetgrentX (struct database_dyn *db
|
|
*tofreep = NULL;
|
|
|
|
if (netgroup_database == NULL
|
|
- && __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database))
|
|
+ && !__nss_database_get (nss_database_netgroup, &netgroup_database))
|
|
{
|
|
/* No such service. */
|
|
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
|
|
Index: glibc-2.33/nss/Makefile
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/Makefile
|
|
+++ glibc-2.33/nss/Makefile
|
|
@@ -63,6 +63,7 @@ tests = test-netdb test-digits-dots ts
|
|
xtests = bug-erange
|
|
|
|
tests-container = \
|
|
+ tst-nss-compat1 \
|
|
tst-nss-test3 \
|
|
tst-nss-files-hosts-long \
|
|
tst-nss-db-endpwent \
|
|
Index: glibc-2.33/nss/Versions
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/Versions
|
|
+++ glibc-2.33/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_lookup2; __nss_database_get;
|
|
__nss_files_fopen; __nss_readline; __nss_parse_line_result;
|
|
}
|
|
}
|
|
Index: glibc-2.33/nss/XXX-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/XXX-lookup.c
|
|
+++ glibc-2.33/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;
|
|
Index: glibc-2.33/nss/databases.def
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/databases.def
|
|
+++ glibc-2.33/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:
|
|
Index: glibc-2.33/nss/grp-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/grp-lookup.c
|
|
+++ glibc-2.33/nss/grp-lookup.c
|
|
@@ -19,6 +19,5 @@
|
|
#include <config.h>
|
|
|
|
#define DATABASE_NAME group
|
|
-#define DEFAULT_CONFIG "files"
|
|
|
|
#include "XXX-lookup.c"
|
|
Index: glibc-2.33/nss/hosts-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/hosts-lookup.c
|
|
+++ glibc-2.33/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"
|
|
Index: glibc-2.33/nss/key-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/key-lookup.c
|
|
+++ glibc-2.33/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"
|
|
Index: glibc-2.33/nss/network-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/network-lookup.c
|
|
+++ glibc-2.33/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"
|
|
Index: glibc-2.33/nss/nss_compat/compat-grp.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_compat/compat-grp.c
|
|
+++ glibc-2.33/nss/nss_compat/compat-grp.c
|
|
@@ -81,7 +81,7 @@ static bool in_blacklist (const char *,
|
|
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");
|
|
Index: glibc-2.33/nss/nss_compat/compat-initgroups.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_compat/compat-initgroups.c
|
|
+++ glibc-2.33/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");
|
|
Index: glibc-2.33/nss/nss_compat/compat-pwd.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_compat/compat-pwd.c
|
|
+++ glibc-2.33/nss/nss_compat/compat-pwd.c
|
|
@@ -91,7 +91,7 @@ static bool in_blacklist (const char *,
|
|
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");
|
|
Index: glibc-2.33/nss/nss_compat/compat-spwd.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_compat/compat-spwd.c
|
|
+++ glibc-2.33/nss/nss_compat/compat-spwd.c
|
|
@@ -88,8 +88,7 @@ static bool in_blacklist (const char *,
|
|
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");
|
|
Index: glibc-2.33/nss/nss_database.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_database.c
|
|
+++ glibc-2.33/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_
|
|
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"
|
|
@@ -325,14 +327,40 @@ nss_database_reload (struct nss_database
|
|
/* 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. */
|
|
+
|
|
+ /* was lookup2() in nss/nss_compat/compat-spwd.c */
|
|
+ if (staging->services[nss_database_shadow_compat] == NULL)
|
|
+ staging->services[nss_database_shadow_compat] =
|
|
+ staging->services[nss_database_passwd_compat];
|
|
+
|
|
+ /* was ALTERNATE_NAME in nss/spwd_lookup.c */
|
|
+ if (staging->services[nss_database_shadow] == NULL)
|
|
+ staging->services[nss_database_shadow] =
|
|
+ staging->services[nss_database_passwd];
|
|
+
|
|
+ /* was ALTERNATE_NAME in nss/sgrp_lookup.c */
|
|
+ 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)
|
|
{
|
|
@@ -442,6 +470,7 @@ __nss_database_get (enum nss_database db
|
|
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)
|
|
Index: glibc-2.33/nss/nss_database.h
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_database.h
|
|
+++ glibc-2.33/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
|
|
Index: glibc-2.33/nss/nss_module.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_module.c
|
|
+++ glibc-2.33/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_mo
|
|
#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,
|
|
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);
|
|
Index: glibc-2.33/nss/nss_test.h
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_test.h
|
|
+++ glibc-2.33/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_t
|
|
|
|
#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_t
|
|
{ .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, \
|
|
Index: glibc-2.33/nss/nss_test1.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nss_test1.c
|
|
+++ glibc-2.33/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;
|
|
@@ -322,6 +332,89 @@ NAME(getgrnam_r) (const char *name, stru
|
|
|
|
return NSS_STATUS_NOTFOUND;
|
|
}
|
|
+
|
|
+/* -------------------------------------------------- */
|
|
+/* 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. */
|
|
Index: glibc-2.33/nss/nsswitch.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nsswitch.c
|
|
+++ glibc-2.33/nss/nsswitch.c
|
|
@@ -63,37 +63,22 @@ static const char * database_names[] = {
|
|
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)
|
|
+__nss_database_lookup2 (const char *database, 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 (__nss_database_get (database_id, ni))
|
|
+ return 0;
|
|
|
|
- /* 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;
|
|
- }
|
|
+ /* Failure. */
|
|
+ return -1;
|
|
}
|
|
libc_hidden_def (__nss_database_lookup2)
|
|
|
|
Index: glibc-2.33/nss/nsswitch.h
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/nsswitch.h
|
|
+++ glibc-2.33/nss/nsswitch.h
|
|
@@ -88,13 +88,10 @@ extern bool __nss_database_custom[NSS_DB
|
|
|
|
/* 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
|
|
+/* Get the data structure representing the specified database. 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);
|
|
+ struct nss_action **ni);
|
|
libc_hidden_proto (__nss_database_lookup2)
|
|
|
|
/* Put first function with name FCT_NAME for SERVICE in FCTP. The
|
|
Index: glibc-2.33/nss/pwd-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/pwd-lookup.c
|
|
+++ glibc-2.33/nss/pwd-lookup.c
|
|
@@ -19,6 +19,5 @@
|
|
#include <config.h>
|
|
|
|
#define DATABASE_NAME passwd
|
|
-#define DEFAULT_CONFIG "files"
|
|
|
|
#include "XXX-lookup.c"
|
|
Index: glibc-2.33/nss/sgrp-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/sgrp-lookup.c
|
|
+++ glibc-2.33/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"
|
|
Index: glibc-2.33/nss/spwd-lookup.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/nss/spwd-lookup.c
|
|
+++ glibc-2.33/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"
|
|
Index: glibc-2.33/nss/tst-nss-compat1.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/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>
|
|
Index: glibc-2.33/nss/tst-nss-compat1.root/etc/group
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/nss/tst-nss-compat1.root/etc/group
|
|
@@ -0,0 +1 @@
|
|
+wilma:x:100:
|
|
Index: glibc-2.33/nss/tst-nss-compat1.root/etc/nsswitch.conf
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/nss/tst-nss-compat1.root/etc/nsswitch.conf
|
|
@@ -0,0 +1,3 @@
|
|
+passwd : compat
|
|
+passwd_compat : test1
|
|
+
|
|
Index: glibc-2.33/nss/tst-nss-compat1.root/etc/passwd
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/nss/tst-nss-compat1.root/etc/passwd
|
|
@@ -0,0 +1,3 @@
|
|
+name5:x:5:555:name5 for testing:/home/name5:/bin/nologin
|
|
++name100
|
|
++name30
|
|
Index: glibc-2.33/nss/tst-nss-compat1.root/etc/shadow
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/nss/tst-nss-compat1.root/etc/shadow
|
|
@@ -0,0 +1,2 @@
|
|
++name100
|
|
++name30
|
|
Index: glibc-2.33/nss/tst-nss-compat1.root/tst-nss-compat1.script
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.33/nss/tst-nss-compat1.root/tst-nss-compat1.script
|
|
@@ -0,0 +1 @@
|
|
+cp $B/nss/libnss_test1.so $L/libnss_test1.so.2
|
|
Index: glibc-2.33/sysdeps/posix/getaddrinfo.c
|
|
===================================================================
|
|
--- glibc-2.33.orig/sysdeps/posix/getaddrinfo.c
|
|
+++ glibc-2.33/sysdeps/posix/getaddrinfo.c
|
|
@@ -720,9 +720,7 @@ gaih_inet (const char *name, const struc
|
|
}
|
|
#endif
|
|
|
|
- no_more = __nss_database_lookup2 ("hosts", NULL,
|
|
- "dns [!UNAVAIL=return] files",
|
|
- &nip);
|
|
+ no_more = (__nss_database_get (nss_database_hosts, &nip) == false);
|
|
|
|
/* If we are looking for both IPv4 and IPv6 address we don't
|
|
want the lookup functions to automatically promote IPv4
|