nwrap_files_getaddrinfo: avoid crash on empty name
[nss_wrapper.git] / tests / test_gethostby_name_addr.c
1 #include "config.h"
2
3 #include <pthread.h>
4
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <setjmp.h>
8 #include <cmocka.h>
9
10 #include <errno.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20
21 #define NSS_WRAPPER_HOSTNAME_ENV "NSS_WRAPPER_HOSTNAME"
22
23 static void test_nwrap_gethostname(void **state)
24 {
25         const char *hostname = "milliways";
26         char sys_host[256] = {0};
27         char host[16] = {0};
28         int rc;
29
30         (void) state; /* unused */
31
32         rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, hostname, 1);
33         assert_int_equal(rc, 0);
34
35         rc = gethostname(host, sizeof(host));
36         assert_int_equal(rc, 0);
37
38         assert_string_equal(host, hostname);
39
40         rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, "this_hostname_is_too_long", 1);
41         assert_int_equal(rc, 0);
42
43         rc = gethostname(host, sizeof(host));
44         assert_int_equal(rc, -1);
45         assert_int_equal(errno, ENAMETOOLONG);
46
47         unsetenv(NSS_WRAPPER_HOSTNAME_ENV);
48
49         rc = gethostname(sys_host, sizeof(sys_host));
50         assert_int_equal(rc, 0);
51
52 }
53
54 static void *thread_test_gethostbyname(void *u)
55 {
56         struct hostent *he;
57
58         (void) u; /* unused */
59
60         he = gethostbyname("magrathea");
61         assert_non_null(he);
62         assert_non_null(he->h_name);
63         assert_string_equal(he->h_name, "magrathea.galaxy.site");
64         pthread_exit(NULL);
65 }
66
67 static void test_nwrap_gethostbyname_thread(void **state)
68 {
69         struct hostent *he;
70         pthread_t th;
71
72         (void) state; /* unused */
73
74         he = gethostbyname("maximegalon.galaxy.site");
75         assert_non_null(he);
76         assert_non_null(he->h_name);
77         assert_string_equal(he->h_name, "maximegalon.galaxy.site");
78
79         pthread_create(&th, NULL, &thread_test_gethostbyname, NULL);
80         pthread_join(th, NULL);
81
82         assert_non_null(he);
83         assert_non_null(he->h_name);
84 #ifdef BSD
85         /*
86          * On *BSD (and Mac OS X) systems,
87          * data is stored in thread local storage.
88          */
89         assert_string_equal(he->h_name, "maximegalon.galaxy.site");
90 #else
91         /*
92          * Glibc doesn't store data in thread local storage, so calling
93          * gethostbyname from a thread overwrites the parent thread's data.
94          */
95         assert_string_equal(he->h_name, "magrathea.galaxy.site");
96 #endif
97 }
98
99 static void test_nwrap_gethostbyname(void **state)
100 {
101         char ip[INET_ADDRSTRLEN];
102         struct hostent *he;
103         const char *a;
104
105         (void) state; /* unused */
106
107         he = gethostbyname("magrathea.galaxy.site");
108         assert_non_null(he);
109         assert_non_null(he->h_name);
110         assert_non_null(he->h_addr_list);
111
112         assert_string_equal(he->h_name, "magrathea.galaxy.site");
113         assert_int_equal(he->h_addrtype, AF_INET);
114
115         a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
116         assert_non_null(a);
117
118         assert_string_equal(ip, "127.0.0.11");
119 }
120
121 static void test_nwrap_gethostbyname_multiple(void **state)
122 {
123         struct hostent *he;
124         char **list;
125
126         /* For inet_ntop call */
127         char buf[4096];
128         const char *result;
129         char *p = buf;
130
131         /* List of ips in hosts file - order matters */
132         const char *const result_ips[] = { "127.0.0.11", "127.0.0.12", NULL };
133         const char *actual_ip = result_ips[0];
134         unsigned int ac;
135
136         (void) state; /* unused */
137
138         he = gethostbyname("magrathea.galaxy.site");
139         assert_non_null(he);
140         assert_non_null(he->h_name);
141         assert_non_null(he->h_addr_list);
142
143         list = he->h_addr_list;
144         for (ac = 0; *list != NULL; ++ac, ++list) {
145                 actual_ip = result_ips[ac];
146                 /* When test fails here more records are returned */
147                 assert_non_null(actual_ip);
148                 result = inet_ntop(AF_INET, *list, p, 4096);
149                 assert_non_null(p);
150                 assert_string_equal(actual_ip, result);
151         }
152 }
153
154 #ifdef HAVE_GETHOSTBYNAME2
155 static void test_nwrap_gethostbyname2(void **state)
156 {
157         char ip[INET6_ADDRSTRLEN];
158         struct hostent *he;
159         const char *a;
160
161         (void) state; /* unused */
162
163         he = gethostbyname2("magrathea.galaxy.site", AF_INET6);
164         assert_non_null(he);
165
166         he = gethostbyname2("magrathea.galaxy.site", AF_INET);
167         assert_non_null(he);
168
169         /* Check ipv6 he */
170         he = gethostbyname2("krikkit.galaxy.site", AF_INET6);
171         assert_non_null(he);
172         assert_non_null(he->h_name);
173         assert_non_null(he->h_addr_list);
174
175         assert_string_equal(he->h_name, "krikkit.galaxy.site");
176         assert_int_equal(he->h_addrtype, AF_INET6);
177
178         a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip));
179         assert_non_null(a);
180
181         assert_string_equal(ip, "::14");
182
183         /* Check ipv4 he */
184         he = gethostbyname2("krikkit.galaxy.site", AF_INET);
185         assert_non_null(he);
186         assert_non_null(he->h_name);
187         assert_non_null(he->h_addr_list);
188
189         assert_string_equal(he->h_name, "krikkit.galaxy.site");
190         assert_int_equal(he->h_addrtype, AF_INET);
191
192         a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
193         assert_non_null(a);
194
195         assert_string_equal(ip, "127.0.0.14");
196 }
197 #endif /* HAVE_GETHOSTBYNAME2 */
198
199 static void test_nwrap_gethostbyaddr(void **state)
200 {
201         struct hostent *he;
202         struct in_addr in;
203         int rc;
204
205         (void) state; /* unused */
206
207         rc = inet_aton("127.0.0.11", &in);
208         assert_int_equal(rc, 1);
209
210         he = gethostbyaddr(&in, sizeof(struct in_addr), AF_INET);
211         assert_non_null(he);
212         assert_non_null(he->h_name);
213         assert_non_null(he->h_addr_list);
214
215         assert_string_equal(he->h_name, "magrathea.galaxy.site");
216         assert_int_equal(he->h_addrtype, AF_INET);
217         assert_memory_equal(&in, he->h_addr_list[0], he->h_length);
218 }
219
220 #ifdef HAVE_GETHOSTBYNAME_R
221 static void test_nwrap_gethostbyname_r(void **state)
222 {
223         char buf[1024] = {0};
224         char ip[INET_ADDRSTRLEN];
225         struct hostent hb, *he;
226         const char *a;
227         int herr = 0;
228         int rc;
229
230         (void) state; /* unused */
231
232         rc = gethostbyname_r("magrathea.galaxy.site",
233                              &hb,
234                              buf, sizeof(buf),
235                              &he,
236                              &herr);
237         assert_int_equal(rc, 0);
238         assert_non_null(he);
239         assert_non_null(he->h_name);
240         assert_non_null(he->h_addr_list);
241
242         assert_string_equal(he->h_name, "magrathea.galaxy.site");
243         assert_int_equal(he->h_addrtype, AF_INET);
244
245         a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
246         assert_non_null(a);
247
248         assert_string_equal(ip, "127.0.0.11");
249 }
250
251 static void test_nwrap_gethostbyname_r_null(void **state)
252 {
253         char buf[2];
254         struct hostent hb, *he;
255         int herr = 0;
256         int rc;
257
258         (void) state; /* unused */
259
260         buf[0] = 'A';
261         buf[1] = '\0';
262
263         /* Check that the returned buffer is zeroed */
264         rc = gethostbyname_r("wurst",
265                              &hb,
266                              buf, sizeof(buf),
267                              &he,
268                              &herr);
269         assert_int_equal(rc, ENOENT);
270         assert_null(he);
271         assert_null(hb.h_name);
272         assert_null(hb.h_addr_list);
273         assert_string_equal(buf, "");
274 }
275 #endif
276
277 #ifdef HAVE_GETHOSTBYNAME2_R
278 static void test_nwrap_gethostbyname2_r_v4(void **state)
279 {
280         char *buf = NULL;
281         size_t buflen = 2;
282         char ip[INET_ADDRSTRLEN];
283         struct hostent hb, *he;
284         const char *a;
285         int herr = 0;
286         int rc;
287
288         (void) state; /* unused */
289
290         for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) {
291                 if (buf != NULL) {
292                         free(buf);
293                 }
294                 buf = calloc(1, buflen);
295                 assert_non_null(buf);
296
297                 rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET,
298                                       &hb,
299                                       buf, buflen,
300                                       &he,
301                                       &herr);
302         }
303
304         assert_int_equal(rc, 0);
305         assert_int_equal(herr, 0);
306         assert_non_null(he);
307         assert_non_null(he->h_name);
308         assert_non_null(he->h_addr_list);
309
310         assert_string_equal(he->h_name, "magrathea.galaxy.site");
311         assert_int_equal(he->h_addrtype, AF_INET);
312
313         assert_non_null(he->h_addr_list[0]);
314         a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
315         assert_non_null(a);
316         assert_string_equal(a, "127.0.0.11");
317
318         assert_non_null(he->h_addr_list[1]);
319         a = inet_ntop(AF_INET, he->h_addr_list[1], ip, sizeof(ip));
320         assert_non_null(a);
321         assert_string_equal(a, "127.0.0.12");
322
323         assert_null(he->h_addr_list[2]);
324
325         free(buf);
326 }
327
328 static void test_nwrap_gethostbyname2_r_v6(void **state)
329 {
330         char *buf = NULL;
331         size_t buflen = 2;
332         char ip[INET6_ADDRSTRLEN];
333         struct hostent hb, *he;
334         const char *a;
335         int herr = 0;
336         int rc;
337
338         (void) state; /* unused */
339
340         for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) {
341                 if (buf != NULL) {
342                         free(buf);
343                 }
344                 buf = calloc(1, buflen);
345                 assert_non_null(buf);
346
347                 rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET6,
348                                       &hb,
349                                       buf, buflen,
350                                       &he,
351                                       &herr);
352         }
353
354         assert_int_equal(rc, 0);
355         assert_int_equal(herr, 0);
356         assert_non_null(he);
357         assert_non_null(he->h_name);
358         assert_non_null(he->h_addr_list);
359
360         assert_string_equal(he->h_name, "magrathea.galaxy.site");
361         assert_int_equal(he->h_addrtype, AF_INET6);
362
363         assert_non_null(he->h_addr_list[0]);
364         a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip));
365         assert_non_null(a);
366         assert_string_equal(a, "::29a");
367
368         assert_null(he->h_addr_list[1]);
369
370         free(buf);
371 }
372 #endif
373
374 #ifdef HAVE_GETHOSTBYADDR_R
375 static void test_nwrap_gethostbyaddr_r(void **state)
376 {
377         char buf[1024] = {0};
378         struct hostent hb, *he;
379         struct in_addr in;
380         int herr = 0;
381         int rc;
382
383         (void) state; /* unused */
384
385         rc = inet_aton("127.0.0.11", &in);
386         assert_int_equal(rc, 1);
387
388         rc = gethostbyaddr_r(&in, sizeof(struct in_addr),
389                              AF_INET,
390                              &hb,
391                              buf, sizeof(buf),
392                              &he,
393                              &herr);
394         assert_int_equal(rc, 0);
395         assert_non_null(he);
396         assert_non_null(he->h_name);
397         assert_non_null(he->h_addr_list);
398
399         assert_string_equal(he->h_name, "magrathea.galaxy.site");
400         assert_int_equal(he->h_addrtype, AF_INET);
401         assert_memory_equal(&in, he->h_addr_list[0], he->h_length);
402 }
403 #endif
404
405 int main(void) {
406         int rc;
407
408         const struct CMUnitTest tests[] = {
409                 cmocka_unit_test(test_nwrap_gethostname),
410                 cmocka_unit_test(test_nwrap_gethostbyname),
411                 cmocka_unit_test(test_nwrap_gethostbyname_thread),
412 #ifdef HAVE_GETHOSTBYNAME2
413                 cmocka_unit_test(test_nwrap_gethostbyname2),
414 #endif
415                 cmocka_unit_test(test_nwrap_gethostbyaddr),
416 #ifdef HAVE_GETHOSTBYNAME_R
417                 cmocka_unit_test(test_nwrap_gethostbyname_r),
418                 cmocka_unit_test(test_nwrap_gethostbyname_r_null),
419 #endif
420 #ifdef HAVE_GETHOSTBYNAME2_R
421                 cmocka_unit_test(test_nwrap_gethostbyname2_r_v4),
422                 cmocka_unit_test(test_nwrap_gethostbyname2_r_v6),
423 #endif
424 #ifdef HAVE_GETHOSTBYADDR_R
425                 cmocka_unit_test(test_nwrap_gethostbyaddr_r),
426 #endif
427                 cmocka_unit_test(test_nwrap_gethostbyname_multiple),
428         };
429
430         rc = cmocka_run_group_tests(tests, NULL, NULL);
431
432         return rc;
433 }
434