tst-reload1.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* Test that nsswitch.conf reloading actually works.
  2. Copyright (C) 2020-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <nss.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <sys/types.h>
  20. #include <errno.h>
  21. #include <pwd.h>
  22. #include <support/support.h>
  23. #include <support/check.h>
  24. #include "nss_test.h"
  25. /* Size of buffers used by *_r functions. */
  26. #define TESTBUFLEN 4096
  27. static struct passwd pwd_table_1[] = {
  28. PWD (100),
  29. PWD (30),
  30. PWD (200),
  31. PWD (60),
  32. PWD (20000),
  33. PWD_LAST ()
  34. };
  35. static const char *hostaddr_5[] =
  36. {
  37. "ABCd", "ABCD", "ABC4", NULL
  38. };
  39. static const char *hostaddr_15[] =
  40. {
  41. "4321", "4322", NULL
  42. };
  43. static const char *hostaddr_25[] =
  44. {
  45. "WXYZ", NULL
  46. };
  47. static struct hostent host_table_1[] = {
  48. HOST (5),
  49. HOST (15),
  50. HOST (25),
  51. HOST_LAST ()
  52. };
  53. void
  54. _nss_test1_init_hook(test_tables *t)
  55. {
  56. t->pwd_table = pwd_table_1;
  57. t->host_table = host_table_1;
  58. }
  59. /* The first of these must not appear in pwd_table_1. */
  60. static struct passwd pwd_table_2[] = {
  61. PWD (5),
  62. PWD_N(200, "name30"),
  63. PWD (16),
  64. PWD_LAST ()
  65. };
  66. static const char *hostaddr_6[] =
  67. {
  68. "mnop", NULL
  69. };
  70. static const char *hostaddr_16[] =
  71. {
  72. "7890", "7891", NULL
  73. };
  74. static const char *hostaddr_26[] =
  75. {
  76. "qwer", "qweR", NULL
  77. };
  78. static struct hostent host_table_2[] = {
  79. HOST (6),
  80. HOST (16),
  81. HOST (26),
  82. HOST_LAST ()
  83. };
  84. void
  85. _nss_test2_init_hook(test_tables *t)
  86. {
  87. t->pwd_table = pwd_table_2;
  88. t->host_table = host_table_2;
  89. }
  90. static void
  91. must_be_tests (struct passwd *pt, struct hostent *ht)
  92. {
  93. int i;
  94. struct hostent *h;
  95. struct passwd *p;
  96. for (i = 0; !PWD_ISLAST (&pt[i]); ++i)
  97. {
  98. p = getpwuid (pt[i].pw_uid);
  99. TEST_VERIFY (p != NULL);
  100. if (p != NULL)
  101. {
  102. TEST_COMPARE_STRING (p->pw_name, pt[i].pw_name);
  103. }
  104. }
  105. setpwent ();
  106. for (i = 0; !PWD_ISLAST (&pt[i]); ++i)
  107. {
  108. p = getpwent ();
  109. TEST_VERIFY (p != NULL);
  110. if (p != NULL)
  111. {
  112. TEST_COMPARE_STRING (p->pw_name, pt[i].pw_name);
  113. TEST_COMPARE (p->pw_uid, pt[i].pw_uid);
  114. }
  115. }
  116. endpwent ();
  117. for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
  118. {
  119. h = gethostbyname (ht[i].h_name);
  120. TEST_VERIFY (h != NULL);
  121. if (h != NULL)
  122. {
  123. TEST_COMPARE_STRING (h->h_name, ht[i].h_name);
  124. TEST_COMPARE (h->h_addrtype, AF_INET);
  125. TEST_VERIFY (h->h_addr_list[0] != NULL);
  126. if (h->h_addr_list[0] != NULL)
  127. TEST_COMPARE_BLOB (h->h_addr_list[0], h->h_length,
  128. ht[i].h_addr_list[0], ht[i].h_length);
  129. }
  130. }
  131. for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
  132. {
  133. struct hostent r, *rp;
  134. char buf[TESTBUFLEN];
  135. int herrno, res;
  136. res = gethostbyname2_r (ht[i].h_name, AF_INET,
  137. &r, buf, TESTBUFLEN, &rp, &herrno);
  138. TEST_COMPARE (res, 0);
  139. if (res == 0)
  140. {
  141. TEST_COMPARE_STRING (r.h_name, ht[i].h_name);
  142. TEST_COMPARE (r.h_addrtype, AF_INET);
  143. TEST_VERIFY (r.h_addr_list[0] != NULL);
  144. if (r.h_addr_list[0] != NULL)
  145. TEST_COMPARE_BLOB (r.h_addr_list[0], r.h_length,
  146. ht[i].h_addr_list[0], ht[i].h_length);
  147. }
  148. }
  149. for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
  150. {
  151. h = gethostbyaddr (ht[i].h_addr, 4, AF_INET);
  152. TEST_VERIFY (h != NULL);
  153. if (h != NULL)
  154. {
  155. TEST_COMPARE_STRING (h->h_name, ht[i].h_name);
  156. TEST_VERIFY (h->h_addr_list[0] != NULL);
  157. if (h->h_addr_list[0] != NULL)
  158. TEST_COMPARE_BLOB (h->h_addr_list[0], h->h_length,
  159. ht[i].h_addr_list[0], ht[i].h_length);
  160. }
  161. }
  162. /* getaddrinfo */
  163. for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
  164. {
  165. struct addrinfo *ap;
  166. struct addrinfo hint;
  167. int res, j;
  168. memset (&hint, 0, sizeof (hint));
  169. hint.ai_family = AF_INET;
  170. hint.ai_socktype = SOCK_STREAM;
  171. hint.ai_protocol = 0;
  172. hint.ai_flags = 0;
  173. ap = NULL;
  174. res = getaddrinfo (ht[i].h_name, NULL, &hint, &ap);
  175. TEST_COMPARE (res, 0);
  176. TEST_VERIFY (ap != NULL);
  177. if (res == 0 && ap != NULL)
  178. {
  179. j = 0; /* which address in the list */
  180. while (ap)
  181. {
  182. TEST_COMPARE (ap->ai_family, AF_INET);
  183. struct sockaddr_in *in = (struct sockaddr_in *)ap->ai_addr;
  184. unsigned char *up = (unsigned char *)&in->sin_addr;
  185. TEST_COMPARE_BLOB (up, 4, ht[i].h_addr_list[j], 4);
  186. ap = ap->ai_next;
  187. ++j;
  188. }
  189. }
  190. }
  191. /* getnameinfo */
  192. for (i = 0; !HOST_ISLAST (&ht[i]); ++i)
  193. {
  194. struct sockaddr_in addr;
  195. int res;
  196. char host_buf[NI_MAXHOST];
  197. memset (&addr, 0, sizeof (addr));
  198. addr.sin_family = AF_INET;
  199. addr.sin_port = 80;
  200. memcpy (& addr.sin_addr, ht[i].h_addr_list[0], 4);
  201. res = getnameinfo ((struct sockaddr *) &addr, sizeof(addr),
  202. host_buf, sizeof(host_buf),
  203. NULL, 0, NI_NOFQDN);
  204. TEST_COMPARE (res, 0);
  205. if (res == 0)
  206. TEST_VERIFY (strcmp (ht[i].h_name, host_buf) == 0);
  207. else
  208. printf ("error %s\n", gai_strerror (res));
  209. }
  210. }
  211. static void
  212. must_be_1 (void)
  213. {
  214. struct passwd *p;
  215. must_be_tests (pwd_table_1, host_table_1);
  216. p = getpwnam("name5");
  217. TEST_VERIFY (p == NULL);
  218. }
  219. static void
  220. must_be_2 (void)
  221. {
  222. struct passwd *p;
  223. must_be_tests (pwd_table_2, host_table_2);
  224. p = getpwnam("name100");
  225. TEST_VERIFY (p == NULL);
  226. }
  227. static void
  228. xrename (const char *a, const char *b)
  229. {
  230. int i = rename (a, b);
  231. if (i != 0)
  232. FAIL_EXIT1 ("rename(%s,%s) failed: %s\n", a, b, strerror(errno));
  233. }
  234. /* If the actions change while in the midst of doing a series of
  235. lookups, make sure they're consistent. */
  236. static void
  237. test_cross_switch_consistency (void)
  238. {
  239. int i;
  240. struct passwd *p;
  241. /* We start by initiating a set/get/end loop on conf1. */
  242. setpwent ();
  243. for (i = 0; !PWD_ISLAST (&pwd_table_1[i]); ++i)
  244. {
  245. p = getpwent ();
  246. TEST_VERIFY (p != NULL);
  247. if (p != NULL)
  248. {
  249. TEST_COMPARE_STRING (p->pw_name, pwd_table_1[i].pw_name);
  250. TEST_COMPARE (p->pw_uid, pwd_table_1[i].pw_uid);
  251. }
  252. /* After the first lookup, switch to conf2 and verify */
  253. if (i == 0)
  254. {
  255. xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1");
  256. xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf");
  257. p = getpwnam (pwd_table_2[0].pw_name);
  258. TEST_COMPARE (p->pw_uid, pwd_table_2[0].pw_uid);
  259. }
  260. /* But the original loop should still be on conf1. */
  261. }
  262. endpwent ();
  263. /* Make sure the set/get/end loop sees conf2 now. */
  264. setpwent ();
  265. for (i = 0; !PWD_ISLAST (&pwd_table_2[i]); ++i)
  266. {
  267. p = getpwent ();
  268. TEST_VERIFY (p != NULL);
  269. if (p != NULL)
  270. {
  271. TEST_COMPARE_STRING (p->pw_name, pwd_table_2[i].pw_name);
  272. TEST_COMPARE (p->pw_uid, pwd_table_2[i].pw_uid);
  273. }
  274. }
  275. endpwent ();
  276. }
  277. static int
  278. do_test (void)
  279. {
  280. /* The test1 module was configured at program start. */
  281. must_be_1 ();
  282. xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf1");
  283. xrename ("/etc/nsswitch.conf2", "/etc/nsswitch.conf");
  284. must_be_2 ();
  285. xrename ("/etc/nsswitch.conf", "/etc/nsswitch.conf2");
  286. xrename ("/etc/nsswitch.conf1", "/etc/nsswitch.conf");
  287. must_be_1 ();
  288. test_cross_switch_consistency ();
  289. return 0;
  290. }
  291. #include <support/test-driver.c>