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