| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- /* Test that nsswitch.conf reloading actually works.
- Copyright (C) 2020-2026 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 <sys/types.h>
- #include <errno.h>
- #include <pwd.h>
- #include <support/support.h>
- #include <support/check.h>
- #include "nss_test.h"
- /* Size of buffers used by *_r functions. */
- #define TESTBUFLEN 4096
- static struct passwd pwd_table_1[] = {
- PWD (100),
- PWD (30),
- PWD (200),
- PWD (60),
- PWD (20000),
- PWD_LAST ()
- };
- static const char *hostaddr_5[] =
- {
- "ABCd", "ABCD", "ABC4", NULL
- };
- static const char *hostaddr_15[] =
- {
- "4321", "4322", NULL
- };
- static const char *hostaddr_25[] =
- {
- "WXYZ", NULL
- };
- static struct hostent host_table_1[] = {
- HOST (5),
- HOST (15),
- HOST (25),
- HOST_LAST ()
- };
- void
- _nss_test1_init_hook(test_tables *t)
- {
- t->pwd_table = pwd_table_1;
- t->host_table = host_table_1;
- }
- /* The first of these must not appear in pwd_table_1. */
- static struct passwd pwd_table_2[] = {
- PWD (5),
- PWD_N(200, "name30"),
- PWD (16),
- PWD_LAST ()
- };
- static const char *hostaddr_6[] =
- {
- "mnop", NULL
- };
- static const char *hostaddr_16[] =
- {
- "7890", "7891", NULL
- };
- static const char *hostaddr_26[] =
- {
- "qwer", "qweR", NULL
- };
- static struct hostent host_table_2[] = {
- HOST (6),
- HOST (16),
- HOST (26),
- HOST_LAST ()
- };
- void
- _nss_test2_init_hook(test_tables *t)
- {
- t->pwd_table = pwd_table_2;
- t->host_table = host_table_2;
- }
- static void
- must_be_tests (struct passwd *pt, struct hostent *ht)
- {
- int i;
- struct hostent *h;
- struct passwd *p;
- for (i = 0; !PWD_ISLAST (&pt[i]); ++i)
- {
- p = getpwuid (pt[i].pw_uid);
- TEST_VERIFY (p != NULL);
- if (p != NULL)
- {
- TEST_COMPARE_STRING (p->pw_name, pt[i].pw_name);
- }
- }
- setpwent ();
- for (i = 0; !PWD_ISLAST (&pt[i]); ++i)
- {
- p = getpwent ();
- TEST_VERIFY (p != NULL);
- if (p != NULL)
- {
- TEST_COMPARE_STRING (p->pw_name, pt[i].pw_name);
- TEST_COMPARE (p->pw_uid, pt[i].pw_uid);
- }
- }
- endpwent ();
- for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
- {
- h = gethostbyname (ht[i].h_name);
- TEST_VERIFY (h != NULL);
- if (h != NULL)
- {
- TEST_COMPARE_STRING (h->h_name, ht[i].h_name);
- TEST_COMPARE (h->h_addrtype, AF_INET);
- TEST_VERIFY (h->h_addr_list[0] != NULL);
- if (h->h_addr_list[0] != NULL)
- TEST_COMPARE_BLOB (h->h_addr_list[0], h->h_length,
- ht[i].h_addr_list[0], ht[i].h_length);
- }
- }
- for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
- {
- struct hostent r, *rp;
- char buf[TESTBUFLEN];
- int herrno, res;
- res = gethostbyname2_r (ht[i].h_name, AF_INET,
- &r, buf, TESTBUFLEN, &rp, &herrno);
- TEST_COMPARE (res, 0);
- if (res == 0)
- {
- TEST_COMPARE_STRING (r.h_name, ht[i].h_name);
- TEST_COMPARE (r.h_addrtype, AF_INET);
- TEST_VERIFY (r.h_addr_list[0] != NULL);
- if (r.h_addr_list[0] != NULL)
- TEST_COMPARE_BLOB (r.h_addr_list[0], r.h_length,
- ht[i].h_addr_list[0], ht[i].h_length);
- }
- }
- for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
- {
- h = gethostbyaddr (ht[i].h_addr, 4, AF_INET);
- TEST_VERIFY (h != NULL);
- if (h != NULL)
- {
- TEST_COMPARE_STRING (h->h_name, ht[i].h_name);
- TEST_VERIFY (h->h_addr_list[0] != NULL);
- if (h->h_addr_list[0] != NULL)
- TEST_COMPARE_BLOB (h->h_addr_list[0], h->h_length,
- ht[i].h_addr_list[0], ht[i].h_length);
- }
- }
- /* getaddrinfo */
- for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
- {
- struct addrinfo *ap;
- struct addrinfo hint;
- int res, j;
- memset (&hint, 0, sizeof (hint));
- hint.ai_family = AF_INET;
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_protocol = 0;
- hint.ai_flags = 0;
- ap = NULL;
- res = getaddrinfo (ht[i].h_name, NULL, &hint, &ap);
- TEST_COMPARE (res, 0);
- TEST_VERIFY (ap != NULL);
- if (res == 0 && ap != NULL)
- {
- j = 0; /* which address in the list */
- while (ap)
- {
- TEST_COMPARE (ap->ai_family, AF_INET);
- struct sockaddr_in *in = (struct sockaddr_in *)ap->ai_addr;
- unsigned char *up = (unsigned char *)&in->sin_addr;
- TEST_COMPARE_BLOB (up, 4, ht[i].h_addr_list[j], 4);
- ap = ap->ai_next;
- ++j;
- }
- }
- }
- /* getnameinfo */
- for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
- {
- struct sockaddr_in addr;
- int res;
- char host_buf[NI_MAXHOST];
- memset (&addr, 0, sizeof (addr));
- addr.sin_family = AF_INET;
- addr.sin_port = 80;
- memcpy (& addr.sin_addr, ht[i].h_addr_list[0], 4);
- res = getnameinfo ((struct sockaddr *) &addr, sizeof(addr),
- host_buf, sizeof(host_buf),
- NULL, 0, NI_NOFQDN);
- TEST_COMPARE (res, 0);
- if (res == 0)
- TEST_VERIFY (strcmp (ht[i].h_name, host_buf) == 0);
- else
- printf ("error %s\n", gai_strerror (res));
- }
- }
- static void
- must_be_1 (void)
- {
- struct passwd *p;
- must_be_tests (pwd_table_1, host_table_1);
- p = getpwnam("name5");
- TEST_VERIFY (p == NULL);
- }
- static void
- must_be_2 (void)
- {
- struct passwd *p;
- must_be_tests (pwd_table_2, host_table_2);
- p = getpwnam("name100");
- TEST_VERIFY (p == NULL);
- }
- static void
- xrename (const char *a, const char *b)
- {
- int i = rename (a, b);
- if (i != 0)
- FAIL_EXIT1 ("rename(%s,%s) failed: %s\n", a, b, strerror(errno));
- }
- /* If the actions change while in the midst of doing a series of
- lookups, make sure they're consistent. */
- static void
- test_cross_switch_consistency (void)
- {
- int i;
- struct passwd *p;
- /* We start by initiating a set/get/end loop on conf1. */
- setpwent ();
- for (i = 0; !PWD_ISLAST (&pwd_table_1[i]); ++i)
- {
- p = getpwent ();
- TEST_VERIFY (p != NULL);
- if (p != NULL)
- {
- TEST_COMPARE_STRING (p->pw_name, pwd_table_1[i].pw_name);
- TEST_COMPARE (p->pw_uid, pwd_table_1[i].pw_uid);
- }
- /* After the first lookup, switch to conf2 and verify */
- if (i == 0)
- {
- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1");
- xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf");
- p = getpwnam (pwd_table_2[0].pw_name);
- TEST_COMPARE (p->pw_uid, pwd_table_2[0].pw_uid);
- }
- /* But the original loop should still be on conf1. */
- }
- endpwent ();
- /* Make sure the set/get/end loop sees conf2 now. */
- setpwent ();
- for (i = 0; !PWD_ISLAST (&pwd_table_2[i]); ++i)
- {
- p = getpwent ();
- TEST_VERIFY (p != NULL);
- if (p != NULL)
- {
- TEST_COMPARE_STRING (p->pw_name, pwd_table_2[i].pw_name);
- TEST_COMPARE (p->pw_uid, pwd_table_2[i].pw_uid);
- }
- }
- endpwent ();
- }
- static int
- do_test (void)
- {
- /* The test1 module was configured at program start. */
- must_be_1 ();
- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1");
- xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf");
- must_be_2 ();
- xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf2");
- xrename ("/etc/nsswitch.conf1", "/etc/nsswitch.conf");
- must_be_1 ();
- test_cross_switch_consistency ();
- return 0;
- }
- #include <support/test-driver.c>
|