Line data Source code
1 : /*
2 : * BSD 3-Clause License
3 : *
4 : * Copyright (c) 2007, Stefan Metzmacher <metze@samba.org>
5 : * Copyright (c) 2009, Guenther Deschner <gd@samba.org>
6 : * Copyright (c) 2014-2015, Michael Adam <obnox@samba.org>
7 : * Copyright (c) 2015, Robin Hack <hack.robin@gmail.com>
8 : * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
9 : * All rights reserved.
10 : *
11 : * Redistribution and use in source and binary forms, with or without
12 : * modification, are permitted provided that the following conditions
13 : * are met:
14 : *
15 : * 1. Redistributions of source code must retain the above copyright
16 : * notice, this list of conditions and the following disclaimer.
17 : *
18 : * 2. Redistributions in binary form must reproduce the above copyright
19 : * notice, this list of conditions and the following disclaimer in the
20 : * documentation and/or other materials provided with the distribution.
21 : *
22 : * 3. Neither the name of the author nor the names of its contributors
23 : * may be used to endorse or promote products derived from this software
24 : * without specific prior written permission.
25 : *
26 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 : * SUCH DAMAGE.
37 : */
38 :
39 : #include "config.h"
40 :
41 : #include <pthread.h>
42 :
43 : #include <sys/types.h>
44 : #include <sys/stat.h>
45 : #include <sys/socket.h>
46 : #include <errno.h>
47 : #include <fcntl.h>
48 : #include <stdarg.h>
49 : #include <stdbool.h>
50 : #include <stddef.h>
51 : #include <stdio.h>
52 : #include <stdint.h>
53 : #include <stdlib.h>
54 : #include <string.h>
55 : #include <unistd.h>
56 : #include <ctype.h>
57 :
58 : #include <netinet/in.h>
59 :
60 : #include <search.h>
61 : #include <assert.h>
62 :
63 : /*
64 : * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
65 : * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
66 : * Solaris
67 : */
68 : #ifndef _POSIX_PTHREAD_SEMANTICS
69 : #define _POSIX_PTHREAD_SEMANTICS
70 : #endif
71 :
72 : #include <pwd.h>
73 : #include <grp.h>
74 : #ifdef HAVE_SHADOW_H
75 : #include <shadow.h>
76 : #endif /* HAVE_SHADOW_H */
77 :
78 : #include <netdb.h>
79 : #include <arpa/inet.h>
80 : #include <netinet/in.h>
81 :
82 : #include <dlfcn.h>
83 :
84 : #if defined(HAVE_NSS_H)
85 : /* Linux and BSD */
86 : #include <nss.h>
87 :
88 : typedef enum nss_status NSS_STATUS;
89 : #elif defined(HAVE_NSS_COMMON_H)
90 : /* Solaris */
91 : #include <nss_common.h>
92 : #include <nss_dbdefs.h>
93 : #include <nsswitch.h>
94 :
95 : typedef nss_status_t NSS_STATUS;
96 :
97 : # define NSS_STATUS_SUCCESS NSS_SUCCESS
98 : # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
99 : # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
100 : # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
101 : #else
102 : # error "No nsswitch support detected"
103 : #endif
104 :
105 : #ifndef PTR_DIFF
106 : #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
107 : #endif
108 :
109 : #ifndef _PUBLIC_
110 : #define _PUBLIC_
111 : #endif
112 :
113 : #ifndef EAI_NODATA
114 : #define EAI_NODATA EAI_NONAME
115 : #endif
116 :
117 : #ifndef EAI_ADDRFAMILY
118 : #define EAI_ADDRFAMILY EAI_FAMILY
119 : #endif
120 :
121 : #ifndef __STRING
122 : #define __STRING(x) #x
123 : #endif
124 :
125 : #ifndef __STRINGSTRING
126 : #define __STRINGSTRING(x) __STRING(x)
127 : #endif
128 :
129 : #ifndef __LINESTR__
130 : #define __LINESTR__ __STRINGSTRING(__LINE__)
131 : #endif
132 :
133 : #ifndef __location__
134 : #define __location__ __FILE__ ":" __LINESTR__
135 : #endif
136 :
137 : #ifndef DNS_NAME_MAX
138 : #define DNS_NAME_MAX 255
139 : #endif
140 :
141 : /* GCC have printf type attribute check. */
142 : #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
143 : #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
144 : #else
145 : #define PRINTF_ATTRIBUTE(a,b)
146 : #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
147 :
148 : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
149 : #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
150 : #else
151 : #define CONSTRUCTOR_ATTRIBUTE
152 : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
153 :
154 : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
155 : #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
156 : #else
157 : #define DESTRUCTOR_ATTRIBUTE
158 : #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
159 :
160 : #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
161 :
162 : #ifndef SAFE_FREE
163 : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
164 : #endif
165 :
166 : #ifndef discard_const
167 : #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
168 : #endif
169 :
170 : #ifndef discard_const_p
171 : #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
172 : #endif
173 :
174 : #ifdef HAVE_IPV6
175 : #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
176 : #else
177 : #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
178 : #endif
179 :
180 : static bool nwrap_initialized = false;
181 : static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
182 :
183 : /* The mutex or accessing the id */
184 : static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER;
185 : static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
186 : static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER;
187 : static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER;
188 : static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
189 :
190 : #define nss_wrapper_init_mutex(m) \
191 : _nss_wrapper_init_mutex(m, #m)
192 :
193 : /* Add new global locks here please */
194 : /* Also don't forget to add locks to
195 : * nwrap_init() function.
196 : */
197 : # define NWRAP_REINIT_ALL do { \
198 : int ret; \
199 : ret = nss_wrapper_init_mutex(&nwrap_initialized_mutex); \
200 : if (ret != 0) exit(-1); \
201 : ret = nss_wrapper_init_mutex(&nwrap_global_mutex); \
202 : if (ret != 0) exit(-1); \
203 : ret = nss_wrapper_init_mutex(&nwrap_gr_global_mutex); \
204 : if (ret != 0) exit(-1); \
205 : ret = nss_wrapper_init_mutex(&nwrap_he_global_mutex); \
206 : if (ret != 0) exit(-1); \
207 : ret = nss_wrapper_init_mutex(&nwrap_pw_global_mutex); \
208 : if (ret != 0) exit(-1); \
209 : ret = nss_wrapper_init_mutex(&nwrap_sp_global_mutex); \
210 : if (ret != 0) exit(-1); \
211 : } while(0)
212 :
213 : # define NWRAP_LOCK_ALL do { \
214 : nwrap_mutex_lock(&nwrap_initialized_mutex); \
215 : nwrap_mutex_lock(&nwrap_global_mutex); \
216 : nwrap_mutex_lock(&nwrap_gr_global_mutex); \
217 : nwrap_mutex_lock(&nwrap_he_global_mutex); \
218 : nwrap_mutex_lock(&nwrap_pw_global_mutex); \
219 : nwrap_mutex_lock(&nwrap_sp_global_mutex); \
220 : } while (0);
221 :
222 : # define NWRAP_UNLOCK_ALL do {\
223 : nwrap_mutex_unlock(&nwrap_sp_global_mutex); \
224 : nwrap_mutex_unlock(&nwrap_pw_global_mutex); \
225 : nwrap_mutex_unlock(&nwrap_he_global_mutex); \
226 : nwrap_mutex_unlock(&nwrap_gr_global_mutex); \
227 : nwrap_mutex_unlock(&nwrap_global_mutex); \
228 : nwrap_mutex_unlock(&nwrap_initialized_mutex); \
229 : } while (0);
230 :
231 : static void nwrap_init(void);
232 :
233 : enum nwrap_dbglvl_e {
234 : NWRAP_LOG_ERROR = 0,
235 : NWRAP_LOG_WARN,
236 : NWRAP_LOG_DEBUG,
237 : NWRAP_LOG_TRACE
238 : };
239 :
240 : #ifndef HAVE_GETPROGNAME
241 4190237 : static const char *getprogname(void)
242 : {
243 : #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
244 4190237 : return program_invocation_short_name;
245 : #elif defined(HAVE_GETEXECNAME)
246 : return getexecname();
247 : #else
248 : return NULL;
249 : #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
250 : }
251 : #endif /* HAVE_GETPROGNAME */
252 :
253 : static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
254 : # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
255 :
256 4190237 : static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
257 : const char *func,
258 : const char *format, ...)
259 : {
260 : char buffer[1024];
261 : va_list va;
262 : const char *d;
263 4190237 : unsigned int lvl = 0;
264 4190237 : const char *prefix = "NWRAP";
265 4190237 : const char *progname = getprogname();
266 :
267 4190237 : d = getenv("NSS_WRAPPER_DEBUGLEVEL");
268 4190237 : if (d != NULL) {
269 0 : lvl = atoi(d);
270 : }
271 :
272 4190237 : if (lvl < dbglvl) {
273 4190237 : return;
274 : }
275 :
276 0 : va_start(va, format);
277 0 : vsnprintf(buffer, sizeof(buffer), format, va);
278 0 : va_end(va);
279 :
280 0 : switch (dbglvl) {
281 0 : case NWRAP_LOG_ERROR:
282 0 : prefix = "NWRAP_ERROR";
283 0 : break;
284 0 : case NWRAP_LOG_WARN:
285 0 : prefix = "NWRAP_WARN";
286 0 : break;
287 0 : case NWRAP_LOG_DEBUG:
288 0 : prefix = "NWRAP_DEBUG";
289 0 : break;
290 0 : case NWRAP_LOG_TRACE:
291 0 : prefix = "NWRAP_TRACE";
292 0 : break;
293 : }
294 :
295 0 : if (progname == NULL) {
296 0 : progname = "<unknown>";
297 : }
298 :
299 0 : fprintf(stderr,
300 : "%s[%s (%u)] - %s: %s\n",
301 : prefix,
302 : progname,
303 0 : (unsigned int)getpid(),
304 : func,
305 : buffer);
306 : }
307 :
308 : /*****************
309 : * LIBC
310 : *****************/
311 :
312 : #define LIBC_NAME "libc.so"
313 :
314 : typedef struct passwd *(*__libc_getpwnam)(const char *name);
315 :
316 : typedef int (*__libc_getpwnam_r)(const char *name,
317 : struct passwd *pwd,
318 : char *buf,
319 : size_t buflen,
320 : struct passwd **result);
321 :
322 : typedef struct passwd *(*__libc_getpwuid)(uid_t uid);
323 :
324 : typedef int (*__libc_getpwuid_r)(uid_t uid,
325 : struct passwd *pwd,
326 : char *buf,
327 : size_t buflen,
328 : struct passwd **result);
329 :
330 : typedef void (*__libc_setpwent)(void);
331 :
332 : typedef struct passwd *(*__libc_getpwent)(void);
333 :
334 : #ifdef HAVE_GETPWENT_R
335 : # ifdef HAVE_SOLARIS_GETPWENT_R
336 : typedef struct passwd *(*__libc_getpwent_r)(struct passwd *pwbuf,
337 : char *buf,
338 : size_t buflen);
339 : # else /* HAVE_SOLARIS_GETPWENT_R */
340 : typedef int (*__libc_getpwent_r)(struct passwd *pwbuf,
341 : char *buf,
342 : size_t buflen,
343 : struct passwd **pwbufp);
344 : # endif /* HAVE_SOLARIS_GETPWENT_R */
345 : #endif /* HAVE_GETPWENT_R */
346 :
347 : typedef void (*__libc_endpwent)(void);
348 :
349 : typedef int (*__libc_initgroups)(const char *user, gid_t gid);
350 :
351 : typedef struct group *(*__libc_getgrnam)(const char *name);
352 :
353 : typedef int (*__libc_getgrnam_r)(const char *name,
354 : struct group *grp,
355 : char *buf,
356 : size_t buflen,
357 : struct group **result);
358 :
359 : typedef struct group *(*__libc_getgrgid)(gid_t gid);
360 :
361 : typedef int (*__libc_getgrgid_r)(gid_t gid,
362 : struct group *grp,
363 : char *buf,
364 : size_t buflen,
365 : struct group **result);
366 :
367 : typedef void (*__libc_setgrent)(void);
368 :
369 : typedef struct group *(*__libc_getgrent)(void);
370 :
371 : #ifdef HAVE_GETGRENT_R
372 : # ifdef HAVE_SOLARIS_GETGRENT_R
373 : typedef struct group *(*__libc_getgrent_r)(struct group *group,
374 : char *buf,
375 : size_t buflen);
376 : # else /* HAVE_SOLARIS_GETGRENT_R */
377 : typedef int (*__libc_getgrent_r)(struct group *group,
378 : char *buf,
379 : size_t buflen,
380 : struct group **result);
381 : # endif /* HAVE_SOLARIS_GETGRENT_R */
382 : #endif /* HAVE_GETGRENT_R */
383 :
384 : typedef void (*__libc_endgrent)(void);
385 :
386 : typedef int (*__libc_getgrouplist)(const char *user,
387 : gid_t group,
388 : gid_t *groups,
389 : int *ngroups);
390 :
391 : typedef void (*__libc_sethostent)(int stayopen);
392 :
393 : typedef struct hostent *(*__libc_gethostent)(void);
394 :
395 : typedef void (*__libc_endhostent)(void);
396 :
397 : typedef struct hostent *(*__libc_gethostbyname)(const char *name);
398 :
399 : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
400 : typedef struct hostent *(*__libc_gethostbyname2)(const char *name, int af);
401 : #endif
402 :
403 : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
404 : typedef int (*__libc_gethostbyname2_r)(const char *name,
405 : int af,
406 : struct hostent *ret,
407 : char *buf,
408 : size_t buflen,
409 : struct hostent **result,
410 : int *h_errnop);
411 : #endif
412 :
413 : typedef struct hostent *(*__libc_gethostbyaddr)(const void *addr,
414 : socklen_t len,
415 : int type);
416 :
417 : typedef int (*__libc_getaddrinfo)(const char *node,
418 : const char *service,
419 : const struct addrinfo *hints,
420 : struct addrinfo **res);
421 : typedef int (*__libc_getnameinfo)(const struct sockaddr *sa,
422 : socklen_t salen,
423 : char *host,
424 : size_t hostlen,
425 : char *serv,
426 : size_t servlen,
427 : int flags);
428 :
429 : typedef int (*__libc_gethostname)(char *name, size_t len);
430 :
431 : #ifdef HAVE_GETHOSTBYNAME_R
432 : typedef int (*__libc_gethostbyname_r)(const char *name,
433 : struct hostent *ret,
434 : char *buf, size_t buflen,
435 : struct hostent **result, int *h_errnop);
436 : #endif
437 :
438 : #ifdef HAVE_GETHOSTBYADDR_R
439 : typedef int (*__libc_gethostbyaddr_r)(const void *addr,
440 : socklen_t len,
441 : int type,
442 : struct hostent *ret,
443 : char *buf,
444 : size_t buflen,
445 : struct hostent **result,
446 : int *h_errnop);
447 : #endif
448 :
449 : #define NWRAP_SYMBOL_ENTRY(i) \
450 : union { \
451 : __libc_##i f; \
452 : void *obj; \
453 : } _libc_##i
454 :
455 : struct nwrap_libc_symbols {
456 : NWRAP_SYMBOL_ENTRY(getpwnam);
457 : NWRAP_SYMBOL_ENTRY(getpwnam_r);
458 : NWRAP_SYMBOL_ENTRY(getpwuid);
459 : NWRAP_SYMBOL_ENTRY(getpwuid_r);
460 : NWRAP_SYMBOL_ENTRY(setpwent);
461 : NWRAP_SYMBOL_ENTRY(getpwent);
462 : #ifdef HAVE_GETPWENT_R
463 : NWRAP_SYMBOL_ENTRY(getpwent_r);
464 : #endif
465 : NWRAP_SYMBOL_ENTRY(endpwent);
466 :
467 : NWRAP_SYMBOL_ENTRY(initgroups);
468 : NWRAP_SYMBOL_ENTRY(getgrnam);
469 : NWRAP_SYMBOL_ENTRY(getgrnam_r);
470 : NWRAP_SYMBOL_ENTRY(getgrgid);
471 : NWRAP_SYMBOL_ENTRY(getgrgid_r);
472 : NWRAP_SYMBOL_ENTRY(setgrent);
473 : NWRAP_SYMBOL_ENTRY(getgrent);
474 : #ifdef HAVE_GETGRENT_R
475 : NWRAP_SYMBOL_ENTRY(getgrent_r);
476 : #endif
477 : NWRAP_SYMBOL_ENTRY(endgrent);
478 : NWRAP_SYMBOL_ENTRY(getgrouplist);
479 :
480 : NWRAP_SYMBOL_ENTRY(sethostent);
481 : NWRAP_SYMBOL_ENTRY(gethostent);
482 : NWRAP_SYMBOL_ENTRY(endhostent);
483 : NWRAP_SYMBOL_ENTRY(gethostbyname);
484 : #ifdef HAVE_GETHOSTBYNAME_R
485 : NWRAP_SYMBOL_ENTRY(gethostbyname_r);
486 : #endif
487 : #ifdef HAVE_GETHOSTBYNAME2
488 : NWRAP_SYMBOL_ENTRY(gethostbyname2);
489 : #endif
490 : #ifdef HAVE_GETHOSTBYNAME2_R
491 : NWRAP_SYMBOL_ENTRY(gethostbyname2_r);
492 : #endif
493 : NWRAP_SYMBOL_ENTRY(gethostbyaddr);
494 : #ifdef HAVE_GETHOSTBYADDR_R
495 : NWRAP_SYMBOL_ENTRY(gethostbyaddr_r);
496 : #endif
497 : NWRAP_SYMBOL_ENTRY(getaddrinfo);
498 : NWRAP_SYMBOL_ENTRY(getnameinfo);
499 : NWRAP_SYMBOL_ENTRY(gethostname);
500 : };
501 : #undef NWRAP_SYMBOL_ENTRY
502 :
503 : typedef NSS_STATUS (*__nss_getpwnam_r)(const char *name,
504 : struct passwd *result,
505 : char *buffer,
506 : size_t buflen,
507 : int *errnop);
508 : typedef NSS_STATUS (*__nss_getpwuid_r)(uid_t uid,
509 : struct passwd *result,
510 : char *buffer,
511 : size_t buflen,
512 : int *errnop);
513 : typedef NSS_STATUS (*__nss_setpwent)(void);
514 : typedef NSS_STATUS (*__nss_getpwent_r)(struct passwd *result,
515 : char *buffer,
516 : size_t buflen,
517 : int *errnop);
518 : typedef NSS_STATUS (*__nss_endpwent)(void);
519 : typedef NSS_STATUS (*__nss_initgroups)(const char *user,
520 : gid_t group,
521 : long int *start,
522 : long int *size,
523 : gid_t **groups,
524 : long int limit,
525 : int *errnop);
526 : typedef NSS_STATUS (*__nss_getgrnam_r)(const char *name,
527 : struct group *result,
528 : char *buffer,
529 : size_t buflen,
530 : int *errnop);
531 : typedef NSS_STATUS (*__nss_getgrgid_r)(gid_t gid,
532 : struct group *result,
533 : char *buffer,
534 : size_t buflen,
535 : int *errnop);
536 : typedef NSS_STATUS (*__nss_setgrent)(void);
537 : typedef NSS_STATUS (*__nss_getgrent_r)(struct group *result,
538 : char *buffer,
539 : size_t buflen,
540 : int *errnop);
541 : typedef NSS_STATUS (*__nss_endgrent)(void);
542 : typedef NSS_STATUS (*__nss_gethostbyaddr_r)(const void *addr,
543 : socklen_t addrlen,
544 : int af,
545 : struct hostent *result,
546 : char *buffer,
547 : size_t buflen,
548 : int *errnop,
549 : int *h_errnop);
550 : typedef NSS_STATUS (*__nss_gethostbyname2_r)(const char *name,
551 : int af,
552 : struct hostent *result,
553 : char *buffer,
554 : size_t buflen,
555 : int *errnop,
556 : int *h_errnop);
557 :
558 : #define NWRAP_NSS_MODULE_SYMBOL_ENTRY(i) \
559 : union { \
560 : __nss_##i f; \
561 : void *obj; \
562 : } _nss_##i
563 :
564 : struct nwrap_nss_module_symbols {
565 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwnam_r);
566 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwuid_r);
567 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(setpwent);
568 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwent_r);
569 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(endpwent);
570 :
571 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups);
572 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrnam_r);
573 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrgid_r);
574 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(setgrent);
575 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrent_r);
576 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(endgrent);
577 :
578 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyaddr_r);
579 : NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyname2_r);
580 : };
581 :
582 : struct nwrap_backend {
583 : const char *name;
584 : const char *so_path;
585 : void *so_handle;
586 : struct nwrap_ops *ops;
587 : struct nwrap_nss_module_symbols *symbols;
588 : };
589 :
590 : struct nwrap_vector;
591 :
592 : struct nwrap_ops {
593 : struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
594 : const char *name);
595 : int (*nw_getpwnam_r)(struct nwrap_backend *b,
596 : const char *name, struct passwd *pwdst,
597 : char *buf, size_t buflen, struct passwd **pwdstp);
598 : struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
599 : uid_t uid);
600 : int (*nw_getpwuid_r)(struct nwrap_backend *b,
601 : uid_t uid, struct passwd *pwdst,
602 : char *buf, size_t buflen, struct passwd **pwdstp);
603 : void (*nw_setpwent)(struct nwrap_backend *b);
604 : struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
605 : int (*nw_getpwent_r)(struct nwrap_backend *b,
606 : struct passwd *pwdst, char *buf,
607 : size_t buflen, struct passwd **pwdstp);
608 : void (*nw_endpwent)(struct nwrap_backend *b);
609 : int (*nw_initgroups)(struct nwrap_backend *b,
610 : const char *user, gid_t group);
611 : struct group * (*nw_getgrnam)(struct nwrap_backend *b,
612 : const char *name);
613 : int (*nw_getgrnam_r)(struct nwrap_backend *b,
614 : const char *name, struct group *grdst,
615 : char *buf, size_t buflen, struct group **grdstp);
616 : struct group * (*nw_getgrgid)(struct nwrap_backend *b,
617 : gid_t gid);
618 : int (*nw_getgrgid_r)(struct nwrap_backend *b,
619 : gid_t gid, struct group *grdst,
620 : char *buf, size_t buflen, struct group **grdstp);
621 : void (*nw_setgrent)(struct nwrap_backend *b);
622 : struct group * (*nw_getgrent)(struct nwrap_backend *b);
623 : int (*nw_getgrent_r)(struct nwrap_backend *b,
624 : struct group *grdst, char *buf,
625 : size_t buflen, struct group **grdstp);
626 : void (*nw_endgrent)(struct nwrap_backend *b);
627 : struct hostent *(*nw_gethostbyaddr)(struct nwrap_backend *b,
628 : const void *addr,
629 : socklen_t len, int type);
630 : struct hostent *(*nw_gethostbyname)(struct nwrap_backend *b,
631 : const char *name);
632 : struct hostent *(*nw_gethostbyname2)(struct nwrap_backend *b,
633 : const char *name, int af);
634 : int (*nw_gethostbyname2_r)(struct nwrap_backend *b,
635 : const char *name, int af,
636 : struct hostent *hedst,
637 : char *buf, size_t buflen,
638 : struct hostent **hedstp);
639 : };
640 :
641 : /* Public prototypes */
642 :
643 : bool nss_wrapper_enabled(void);
644 : bool nss_wrapper_shadow_enabled(void);
645 : bool nss_wrapper_hosts_enabled(void);
646 :
647 : /* prototypes for files backend */
648 :
649 :
650 : static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
651 : const char *name);
652 : static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
653 : const char *name, struct passwd *pwdst,
654 : char *buf, size_t buflen, struct passwd **pwdstp);
655 : static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
656 : uid_t uid);
657 : static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
658 : uid_t uid, struct passwd *pwdst,
659 : char *buf, size_t buflen, struct passwd **pwdstp);
660 : static void nwrap_files_setpwent(struct nwrap_backend *b);
661 : static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
662 : static int nwrap_files_getpwent_r(struct nwrap_backend *b,
663 : struct passwd *pwdst, char *buf,
664 : size_t buflen, struct passwd **pwdstp);
665 : static void nwrap_files_endpwent(struct nwrap_backend *b);
666 : static int nwrap_files_initgroups(struct nwrap_backend *b,
667 : const char *user, gid_t group);
668 : static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
669 : const char *name);
670 : static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
671 : const char *name, struct group *grdst,
672 : char *buf, size_t buflen, struct group **grdstp);
673 : static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
674 : gid_t gid);
675 : static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
676 : gid_t gid, struct group *grdst,
677 : char *buf, size_t buflen, struct group **grdstp);
678 : static void nwrap_files_setgrent(struct nwrap_backend *b);
679 : static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
680 : static int nwrap_files_getgrent_r(struct nwrap_backend *b,
681 : struct group *grdst, char *buf,
682 : size_t buflen, struct group **grdstp);
683 : static void nwrap_files_endgrent(struct nwrap_backend *b);
684 : static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
685 : const void *addr,
686 : socklen_t len, int type);
687 : static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
688 : const char *name);
689 : #ifdef HAVE_GETHOSTBYNAME2
690 : static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
691 : const char *name, int af);
692 : #endif /* HAVE_GETHOSTBYNAME2 */
693 : static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
694 : const char *name, int af,
695 : struct hostent *hedst,
696 : char *buf, size_t buflen,
697 : struct hostent **hedstp);
698 :
699 : /* prototypes for module backend */
700 :
701 : static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
702 : static int nwrap_module_getpwent_r(struct nwrap_backend *b,
703 : struct passwd *pwdst, char *buf,
704 : size_t buflen, struct passwd **pwdstp);
705 : static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
706 : const char *name);
707 : static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
708 : const char *name, struct passwd *pwdst,
709 : char *buf, size_t buflen, struct passwd **pwdstp);
710 : static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
711 : uid_t uid);
712 : static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
713 : uid_t uid, struct passwd *pwdst,
714 : char *buf, size_t buflen, struct passwd **pwdstp);
715 : static void nwrap_module_setpwent(struct nwrap_backend *b);
716 : static void nwrap_module_endpwent(struct nwrap_backend *b);
717 : static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
718 : static int nwrap_module_getgrent_r(struct nwrap_backend *b,
719 : struct group *grdst, char *buf,
720 : size_t buflen, struct group **grdstp);
721 : static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
722 : const char *name);
723 : static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
724 : const char *name, struct group *grdst,
725 : char *buf, size_t buflen, struct group **grdstp);
726 : static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
727 : gid_t gid);
728 : static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
729 : gid_t gid, struct group *grdst,
730 : char *buf, size_t buflen, struct group **grdstp);
731 : static void nwrap_module_setgrent(struct nwrap_backend *b);
732 : static void nwrap_module_endgrent(struct nwrap_backend *b);
733 : static int nwrap_module_initgroups(struct nwrap_backend *b,
734 : const char *user, gid_t group);
735 : static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
736 : const void *addr,
737 : socklen_t len, int type);
738 : static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
739 : const char *name);
740 : static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
741 : const char *name, int af);
742 : static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
743 : const char *name, int af,
744 : struct hostent *hedst,
745 : char *buf, size_t buflen,
746 : struct hostent **hedstp);
747 :
748 : struct nwrap_ops nwrap_files_ops = {
749 : .nw_getpwnam = nwrap_files_getpwnam,
750 : .nw_getpwnam_r = nwrap_files_getpwnam_r,
751 : .nw_getpwuid = nwrap_files_getpwuid,
752 : .nw_getpwuid_r = nwrap_files_getpwuid_r,
753 : .nw_setpwent = nwrap_files_setpwent,
754 : .nw_getpwent = nwrap_files_getpwent,
755 : .nw_getpwent_r = nwrap_files_getpwent_r,
756 : .nw_endpwent = nwrap_files_endpwent,
757 : .nw_initgroups = nwrap_files_initgroups,
758 : .nw_getgrnam = nwrap_files_getgrnam,
759 : .nw_getgrnam_r = nwrap_files_getgrnam_r,
760 : .nw_getgrgid = nwrap_files_getgrgid,
761 : .nw_getgrgid_r = nwrap_files_getgrgid_r,
762 : .nw_setgrent = nwrap_files_setgrent,
763 : .nw_getgrent = nwrap_files_getgrent,
764 : .nw_getgrent_r = nwrap_files_getgrent_r,
765 : .nw_endgrent = nwrap_files_endgrent,
766 : .nw_gethostbyaddr = nwrap_files_gethostbyaddr,
767 : .nw_gethostbyname = nwrap_files_gethostbyname,
768 : #ifdef HAVE_GETHOSTBYNAME2
769 : .nw_gethostbyname2 = nwrap_files_gethostbyname2,
770 : #endif /* HAVE_GETHOSTBYNAME2 */
771 : .nw_gethostbyname2_r = nwrap_files_gethostbyname2_r,
772 : };
773 :
774 : struct nwrap_ops nwrap_module_ops = {
775 : .nw_getpwnam = nwrap_module_getpwnam,
776 : .nw_getpwnam_r = nwrap_module_getpwnam_r,
777 : .nw_getpwuid = nwrap_module_getpwuid,
778 : .nw_getpwuid_r = nwrap_module_getpwuid_r,
779 : .nw_setpwent = nwrap_module_setpwent,
780 : .nw_getpwent = nwrap_module_getpwent,
781 : .nw_getpwent_r = nwrap_module_getpwent_r,
782 : .nw_endpwent = nwrap_module_endpwent,
783 : .nw_initgroups = nwrap_module_initgroups,
784 : .nw_getgrnam = nwrap_module_getgrnam,
785 : .nw_getgrnam_r = nwrap_module_getgrnam_r,
786 : .nw_getgrgid = nwrap_module_getgrgid,
787 : .nw_getgrgid_r = nwrap_module_getgrgid_r,
788 : .nw_setgrent = nwrap_module_setgrent,
789 : .nw_getgrent = nwrap_module_getgrent,
790 : .nw_getgrent_r = nwrap_module_getgrent_r,
791 : .nw_endgrent = nwrap_module_endgrent,
792 : .nw_gethostbyaddr = nwrap_module_gethostbyaddr,
793 : .nw_gethostbyname = nwrap_module_gethostbyname,
794 : .nw_gethostbyname2 = nwrap_module_gethostbyname2,
795 : .nw_gethostbyname2_r = nwrap_module_gethostbyname2_r,
796 : };
797 :
798 : struct nwrap_libc {
799 : void *handle;
800 : void *nsl_handle;
801 : void *sock_handle;
802 : struct nwrap_libc_symbols symbols;
803 : };
804 :
805 : struct nwrap_main {
806 : size_t num_backends;
807 : struct nwrap_backend *backends;
808 : struct nwrap_libc *libc;
809 : };
810 :
811 : static struct nwrap_main *nwrap_main_global;
812 : static struct nwrap_main __nwrap_main_global;
813 :
814 : /*
815 : * PROTOTYPES
816 : */
817 : static int nwrap_convert_he_ai(const struct hostent *he,
818 : unsigned short port,
819 : const struct addrinfo *hints,
820 : struct addrinfo **pai,
821 : bool skip_canonname);
822 :
823 : /*
824 : * VECTORS
825 : */
826 :
827 : #define DEFAULT_VECTOR_CAPACITY 16
828 :
829 : struct nwrap_vector {
830 : void **items;
831 : size_t count;
832 : size_t capacity;
833 : };
834 :
835 : /* Macro returns pointer to first element of vector->items array.
836 : *
837 : * nwrap_vector is used as a memory backend which take care of
838 : * memory allocations and other stuff like memory growing.
839 : * nwrap_vectors should not be considered as some abstract structures.
840 : * On this level, vectors are more handy than direct realloc/malloc
841 : * calls.
842 : *
843 : * nwrap_vector->items is array inside nwrap_vector which can be
844 : * directly pointed by libc structure assembled by cwrap itself.
845 : *
846 : * EXAMPLE:
847 : *
848 : * 1) struct hostent contains char **h_addr_list element.
849 : * 2) nwrap_vector holds array of pointers to addresses.
850 : * It's easier to use vector to store results of
851 : * file parsing etc.
852 : *
853 : * Now, pretend that cwrap assembled struct hostent and
854 : * we need to set h_addr_list to point to nwrap_vector.
855 : * Idea behind is to shield users from internal nwrap_vector
856 : * implementation.
857 : * (Yes, not fully - array terminated by NULL is needed because
858 : * it's result expected by libc function caller.)
859 : *
860 : *
861 : * CODE EXAMPLE:
862 : *
863 : * struct hostent he;
864 : * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
865 : * ... don't care about failed allocation now ...
866 : *
867 : * ... fill nwrap vector ...
868 : *
869 : * struct hostent he;
870 : * he.h_addr_list = nwrap_vector_head(vector);
871 : *
872 : */
873 : #define nwrap_vector_head(vect) ((void *)((vect)->items))
874 :
875 : #define nwrap_vector_foreach(item, vect, iter) \
876 : for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
877 : item != NULL; \
878 : (item) = (vect).items[++iter])
879 :
880 : #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
881 :
882 89778 : static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
883 : {
884 89778 : if (vector == NULL) {
885 0 : return false;
886 : }
887 :
888 : /* count is initialized by ZERO_STRUCTP */
889 89778 : ZERO_STRUCTP(vector);
890 89778 : vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
891 89778 : if (vector->items == NULL) {
892 0 : return false;
893 : }
894 89778 : vector->capacity = DEFAULT_VECTOR_CAPACITY;
895 89778 : memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
896 :
897 89778 : return true;
898 : }
899 :
900 419991 : static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
901 : {
902 419991 : assert (vector != NULL);
903 :
904 419991 : if (vector->items == NULL) {
905 89778 : nwrap_vector_init(vector);
906 : }
907 :
908 419991 : if (vector->count == vector->capacity) {
909 : /* Items array _MUST_ be NULL terminated because it's passed
910 : * as result to caller which expect NULL terminated array from libc.
911 : */
912 9371 : void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
913 9371 : if (items == NULL) {
914 0 : return false;
915 : }
916 9371 : vector->items = items;
917 :
918 : /* Don't count ending NULL to capacity */
919 9371 : vector->capacity *= 2;
920 : }
921 :
922 419991 : vector->items[vector->count] = item;
923 :
924 419991 : vector->count += 1;
925 419991 : vector->items[vector->count] = NULL;
926 :
927 419991 : return true;
928 : }
929 :
930 0 : static bool nwrap_vector_merge(struct nwrap_vector *dst,
931 : struct nwrap_vector *src)
932 : {
933 0 : void **dst_items = NULL;
934 : size_t count;
935 :
936 0 : if (src->count == 0) {
937 0 : return true;
938 : }
939 :
940 0 : count = dst->count + src->count;
941 :
942 : /* We don't need reallocation if we have enough capacity. */
943 0 : if (src->count > (dst->capacity - dst->count)) {
944 0 : dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
945 0 : if (dst_items == NULL) {
946 0 : return false;
947 : }
948 0 : dst->items = dst_items;
949 0 : dst->capacity = count;
950 : }
951 :
952 0 : memcpy((void *)(((long *)dst->items) + dst->count),
953 0 : src->items,
954 0 : src->count * sizeof(void *));
955 0 : dst->count = count;
956 :
957 0 : return true;
958 : }
959 :
960 : struct nwrap_cache {
961 : const char *path;
962 : int fd;
963 : FILE *fp;
964 : struct stat st;
965 : void *private_data;
966 :
967 : struct nwrap_vector lines;
968 :
969 : bool (*parse_line)(struct nwrap_cache *, char *line);
970 : void (*unload)(struct nwrap_cache *);
971 : };
972 :
973 : /* passwd */
974 : struct nwrap_pw {
975 : struct nwrap_cache *cache;
976 :
977 : struct passwd *list;
978 : int num;
979 : int idx;
980 : };
981 :
982 : struct nwrap_cache __nwrap_cache_pw;
983 : struct nwrap_pw nwrap_pw_global;
984 :
985 : static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
986 : static void nwrap_pw_unload(struct nwrap_cache *nwrap);
987 :
988 : /* shadow */
989 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
990 : struct nwrap_sp {
991 : struct nwrap_cache *cache;
992 :
993 : struct spwd *list;
994 : int num;
995 : int idx;
996 : };
997 :
998 : struct nwrap_cache __nwrap_cache_sp;
999 : struct nwrap_sp nwrap_sp_global;
1000 :
1001 : static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
1002 : static void nwrap_sp_unload(struct nwrap_cache *nwrap);
1003 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1004 :
1005 : /* group */
1006 : struct nwrap_gr {
1007 : struct nwrap_cache *cache;
1008 :
1009 : struct group *list;
1010 : int num;
1011 : int idx;
1012 : };
1013 :
1014 : struct nwrap_cache __nwrap_cache_gr;
1015 : struct nwrap_gr nwrap_gr_global;
1016 :
1017 : /* hosts */
1018 : static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
1019 : static void nwrap_he_unload(struct nwrap_cache *nwrap);
1020 :
1021 : struct nwrap_addrdata {
1022 : unsigned char host_addr[16]; /* IPv4 or IPv6 address */
1023 : };
1024 :
1025 : static size_t max_hostents = 100;
1026 :
1027 : struct nwrap_entdata {
1028 : struct nwrap_addrdata addr;
1029 : struct hostent ht;
1030 :
1031 : struct nwrap_vector nwrap_addrdata;
1032 :
1033 : ssize_t aliases_count;
1034 : };
1035 :
1036 : struct nwrap_entlist {
1037 : struct nwrap_entlist *next;
1038 : struct nwrap_entdata *ed;
1039 : };
1040 :
1041 : struct nwrap_he {
1042 : struct nwrap_cache *cache;
1043 :
1044 : struct nwrap_vector entries;
1045 : struct nwrap_vector lists;
1046 :
1047 : int num;
1048 : int idx;
1049 : };
1050 :
1051 : static struct nwrap_cache __nwrap_cache_he;
1052 : static struct nwrap_he nwrap_he_global;
1053 :
1054 :
1055 : /*********************************************************
1056 : * NWRAP PROTOTYPES
1057 : *********************************************************/
1058 :
1059 : static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
1060 : static void nwrap_gr_unload(struct nwrap_cache *nwrap);
1061 : #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
1062 : /* xlC and other oldschool compilers support (only) this */
1063 : #pragma init (nwrap_constructor)
1064 : #endif
1065 : void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
1066 : #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
1067 : #pragma fini (nwrap_destructor)
1068 : #endif
1069 : void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
1070 :
1071 : /*********************************************************
1072 : * NWRAP LIBC LOADER FUNCTIONS
1073 : *********************************************************/
1074 :
1075 : enum nwrap_lib {
1076 : NWRAP_LIBC,
1077 : NWRAP_LIBNSL,
1078 : NWRAP_LIBSOCKET,
1079 : };
1080 :
1081 338460 : static const char *nwrap_str_lib(enum nwrap_lib lib)
1082 : {
1083 338460 : switch (lib) {
1084 203076 : case NWRAP_LIBC:
1085 203076 : return "libc";
1086 112820 : case NWRAP_LIBNSL:
1087 112820 : return "libnsl";
1088 22564 : case NWRAP_LIBSOCKET:
1089 22564 : return "libsocket";
1090 : }
1091 :
1092 : /* Compiler would warn us about unhandled enum value if we get here */
1093 0 : return "unknown";
1094 : }
1095 :
1096 338460 : static void *nwrap_load_lib_handle(enum nwrap_lib lib)
1097 : {
1098 338460 : int flags = RTLD_LAZY;
1099 338460 : void *handle = NULL;
1100 : int i;
1101 :
1102 : #ifdef RTLD_DEEPBIND
1103 338460 : const char *env_preload = getenv("LD_PRELOAD");
1104 338460 : const char *env_deepbind = getenv("NSS_WRAPPER_DISABLE_DEEPBIND");
1105 338460 : bool enable_deepbind = true;
1106 :
1107 : /* Don't do a deepbind if we run with libasan */
1108 338460 : if (env_preload != NULL && strlen(env_preload) < 1024) {
1109 338460 : const char *p = strstr(env_preload, "libasan.so");
1110 338460 : if (p != NULL) {
1111 0 : enable_deepbind = false;
1112 : }
1113 : }
1114 :
1115 338460 : if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
1116 0 : enable_deepbind = false;
1117 : }
1118 :
1119 338460 : if (enable_deepbind) {
1120 338460 : flags |= RTLD_DEEPBIND;
1121 : }
1122 : #endif
1123 :
1124 338460 : switch (lib) {
1125 156840 : case NWRAP_LIBNSL:
1126 : #ifdef HAVE_LIBNSL
1127 90810 : handle = nwrap_main_global->libc->nsl_handle;
1128 90810 : if (handle == NULL) {
1129 81729 : for (i = 10; i >= 0; i--) {
1130 81729 : char soname[256] = {0};
1131 :
1132 81729 : snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
1133 81729 : handle = dlopen(soname, flags);
1134 81729 : if (handle != NULL) {
1135 9081 : break;
1136 : }
1137 : }
1138 :
1139 9081 : nwrap_main_global->libc->nsl_handle = handle;
1140 : }
1141 90810 : break;
1142 : #endif
1143 : /* FALL TROUGH */
1144 181620 : case NWRAP_LIBSOCKET:
1145 : #ifdef HAVE_LIBSOCKET
1146 : handle = nwrap_main_global->libc->sock_handle;
1147 : if (handle == NULL) {
1148 : for (i = 10; i >= 0; i--) {
1149 : char soname[256] = {0};
1150 :
1151 : snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
1152 : handle = dlopen(soname, flags);
1153 : if (handle != NULL) {
1154 : break;
1155 : }
1156 : }
1157 :
1158 : nwrap_main_global->libc->sock_handle = handle;
1159 : }
1160 : break;
1161 : #endif
1162 : /* FALL TROUGH */
1163 : case NWRAP_LIBC:
1164 247650 : handle = nwrap_main_global->libc->handle;
1165 247650 : if (handle == NULL) {
1166 56410 : for (i = 10; i >= 0; i--) {
1167 56410 : char soname[256] = {0};
1168 :
1169 56410 : snprintf(soname, sizeof(soname), "libc.so.%d", i);
1170 56410 : handle = dlopen(soname, flags);
1171 56410 : if (handle != NULL) {
1172 11282 : break;
1173 : }
1174 : }
1175 :
1176 11282 : nwrap_main_global->libc->handle = handle;
1177 : }
1178 247650 : break;
1179 : }
1180 :
1181 338460 : if (handle == NULL) {
1182 : #ifdef RTLD_NEXT
1183 0 : handle = nwrap_main_global->libc->handle
1184 0 : = nwrap_main_global->libc->sock_handle
1185 0 : = nwrap_main_global->libc->nsl_handle
1186 0 : = RTLD_NEXT;
1187 : #else
1188 : NWRAP_LOG(NWRAP_LOG_ERROR,
1189 : "Failed to dlopen library: %s\n",
1190 : dlerror());
1191 : exit(-1);
1192 : #endif
1193 : }
1194 :
1195 338460 : return handle;
1196 : }
1197 :
1198 338460 : static void *_nwrap_bind_symbol(enum nwrap_lib lib, const char *fn_name)
1199 : {
1200 : void *handle;
1201 : void *func;
1202 :
1203 338460 : nwrap_init();
1204 :
1205 338460 : handle = nwrap_load_lib_handle(lib);
1206 :
1207 338460 : func = dlsym(handle, fn_name);
1208 338460 : if (func == NULL) {
1209 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
1210 : "Failed to find %s: %s\n",
1211 : fn_name, dlerror());
1212 0 : exit(-1);
1213 : }
1214 :
1215 338460 : NWRAP_LOG(NWRAP_LOG_TRACE,
1216 : "Loaded %s from %s",
1217 : fn_name, nwrap_str_lib(lib));
1218 338460 : return func;
1219 : }
1220 :
1221 : #define nwrap_mutex_lock(m) _nwrap_mutex_lock(m, #m, __func__, __LINE__)
1222 6023262 : static void _nwrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
1223 : {
1224 : int ret;
1225 :
1226 6023262 : ret = pthread_mutex_lock(mutex);
1227 6023262 : if (ret != 0) {
1228 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
1229 : getpid(), getppid(), caller, line, name, strerror(ret));
1230 0 : abort();
1231 : }
1232 6023262 : }
1233 :
1234 : #define nwrap_mutex_unlock(m) _nwrap_mutex_unlock(m, #m, __func__, __LINE__)
1235 6001416 : static void _nwrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line)
1236 : {
1237 : int ret;
1238 :
1239 6001416 : ret = pthread_mutex_unlock(mutex);
1240 6001416 : if (ret != 0) {
1241 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
1242 : getpid(), getppid(), caller, line, name, strerror(ret));
1243 0 : abort();
1244 : }
1245 6001416 : }
1246 :
1247 : #define nwrap_bind_symbol_libc(sym_name) \
1248 : if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1249 : nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1250 : _nwrap_bind_symbol(NWRAP_LIBC, #sym_name); \
1251 : } \
1252 :
1253 : #define nwrap_bind_symbol_libc_posix(sym_name) \
1254 : if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1255 : nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1256 : _nwrap_bind_symbol(NWRAP_LIBC, "__posix_" #sym_name); \
1257 : } \
1258 :
1259 : #define nwrap_bind_symbol_libnsl(sym_name) \
1260 : if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1261 : nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1262 : _nwrap_bind_symbol(NWRAP_LIBNSL, #sym_name); \
1263 : } \
1264 :
1265 : #define nwrap_bind_symbol_libsocket(sym_name) \
1266 : if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1267 : nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1268 : _nwrap_bind_symbol(NWRAP_LIBSOCKET, #sym_name); \
1269 : } \
1270 :
1271 : static void nwrap_bind_symbol_all(void);
1272 :
1273 : /* INTERNAL HELPER FUNCTIONS */
1274 181746 : static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
1275 : {
1276 : size_t p;
1277 : void *item;
1278 560404 : nwrap_vector_foreach(item, nwrap->lines, p) {
1279 : /* Maybe some vectors were merged ... */
1280 378658 : SAFE_FREE(item);
1281 : }
1282 181746 : SAFE_FREE(nwrap->lines.items);
1283 181746 : ZERO_STRUCTP(&nwrap->lines);
1284 181746 : }
1285 :
1286 : /*
1287 : * IMPORTANT
1288 : *
1289 : * Functions expeciall from libc need to be loaded individually, you can't load
1290 : * all at once or gdb will segfault at startup. The same applies to valgrind and
1291 : * has probably something todo with with the linker.
1292 : * So we need load each function at the point it is called the first time.
1293 : */
1294 448 : static struct passwd *libc_getpwnam(const char *name)
1295 : {
1296 448 : nwrap_bind_symbol_all();
1297 :
1298 448 : return nwrap_main_global->libc->symbols._libc_getpwnam.f(name);
1299 : }
1300 :
1301 : #ifdef HAVE_GETPWNAM_R
1302 86 : static int libc_getpwnam_r(const char *name,
1303 : struct passwd *pwd,
1304 : char *buf,
1305 : size_t buflen,
1306 : struct passwd **result)
1307 : {
1308 86 : nwrap_bind_symbol_all();
1309 :
1310 86 : return nwrap_main_global->libc->symbols._libc_getpwnam_r.f(name,
1311 : pwd,
1312 : buf,
1313 : buflen,
1314 : result);
1315 : }
1316 : #endif
1317 :
1318 2439 : static struct passwd *libc_getpwuid(uid_t uid)
1319 : {
1320 2439 : nwrap_bind_symbol_all();
1321 :
1322 2439 : return nwrap_main_global->libc->symbols._libc_getpwuid.f(uid);
1323 : }
1324 :
1325 : #ifdef HAVE_GETPWUID_R
1326 287 : static int libc_getpwuid_r(uid_t uid,
1327 : struct passwd *pwd,
1328 : char *buf,
1329 : size_t buflen,
1330 : struct passwd **result)
1331 : {
1332 287 : nwrap_bind_symbol_all();
1333 :
1334 287 : return nwrap_main_global->libc->symbols._libc_getpwuid_r.f(uid,
1335 : pwd,
1336 : buf,
1337 : buflen,
1338 : result);
1339 : }
1340 : #endif
1341 :
1342 777814 : static inline void str_tolower(char *dst, char *src)
1343 : {
1344 777814 : register char *src_tmp = src;
1345 777814 : register char *dst_tmp = dst;
1346 :
1347 13190735 : while (*src_tmp != '\0') {
1348 12412921 : *dst_tmp = tolower(*src_tmp);
1349 12412921 : ++src_tmp;
1350 12412921 : ++dst_tmp;
1351 : }
1352 777814 : }
1353 :
1354 656722 : static bool str_tolower_copy(char **dst_name, const char *const src_name)
1355 : {
1356 : char *h_name_lower;
1357 :
1358 656722 : if ((dst_name == NULL) || (src_name == NULL)) {
1359 0 : return false;
1360 : }
1361 :
1362 656722 : h_name_lower = strdup(src_name);
1363 656722 : if (h_name_lower == NULL) {
1364 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
1365 0 : return false;
1366 : }
1367 :
1368 656722 : str_tolower(h_name_lower, h_name_lower);
1369 656722 : *dst_name = h_name_lower;
1370 656722 : return true;
1371 : }
1372 :
1373 0 : static void libc_setpwent(void)
1374 : {
1375 0 : nwrap_bind_symbol_all();
1376 :
1377 0 : nwrap_main_global->libc->symbols._libc_setpwent.f();
1378 0 : }
1379 :
1380 0 : static struct passwd *libc_getpwent(void)
1381 : {
1382 0 : nwrap_bind_symbol_all();
1383 :
1384 0 : return nwrap_main_global->libc->symbols._libc_getpwent.f();
1385 : }
1386 :
1387 : #ifdef HAVE_GETPWENT_R
1388 : # ifdef HAVE_SOLARIS_GETPWENT_R
1389 : static struct passwd *libc_getpwent_r(struct passwd *pwdst,
1390 : char *buf,
1391 : int buflen)
1392 : {
1393 : nwrap_bind_symbol_all();
1394 :
1395 : return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
1396 : buf,
1397 : buflen);
1398 : }
1399 : # else /* HAVE_SOLARIS_GETPWENT_R */
1400 0 : static int libc_getpwent_r(struct passwd *pwdst,
1401 : char *buf,
1402 : size_t buflen,
1403 : struct passwd **pwdstp)
1404 : {
1405 0 : nwrap_bind_symbol_all();
1406 :
1407 0 : return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
1408 : buf,
1409 : buflen,
1410 : pwdstp);
1411 : }
1412 : # endif /* HAVE_SOLARIS_GETPWENT_R */
1413 : #endif /* HAVE_GETPWENT_R */
1414 :
1415 213 : static void libc_endpwent(void)
1416 : {
1417 213 : nwrap_bind_symbol_all();
1418 :
1419 213 : nwrap_main_global->libc->symbols._libc_endpwent.f();
1420 213 : }
1421 :
1422 0 : static int libc_initgroups(const char *user, gid_t gid)
1423 : {
1424 0 : nwrap_bind_symbol_all();
1425 :
1426 0 : return nwrap_main_global->libc->symbols._libc_initgroups.f(user, gid);
1427 : }
1428 :
1429 0 : static struct group *libc_getgrnam(const char *name)
1430 : {
1431 0 : nwrap_bind_symbol_all();
1432 :
1433 0 : return nwrap_main_global->libc->symbols._libc_getgrnam.f(name);
1434 : }
1435 :
1436 : #ifdef HAVE_GETGRNAM_R
1437 137 : static int libc_getgrnam_r(const char *name,
1438 : struct group *grp,
1439 : char *buf,
1440 : size_t buflen,
1441 : struct group **result)
1442 : {
1443 137 : nwrap_bind_symbol_all();
1444 :
1445 137 : return nwrap_main_global->libc->symbols._libc_getgrnam_r.f(name,
1446 : grp,
1447 : buf,
1448 : buflen,
1449 : result);
1450 : }
1451 : #endif
1452 :
1453 0 : static struct group *libc_getgrgid(gid_t gid)
1454 : {
1455 0 : nwrap_bind_symbol_all();
1456 :
1457 0 : return nwrap_main_global->libc->symbols._libc_getgrgid.f(gid);
1458 : }
1459 :
1460 : #ifdef HAVE_GETGRGID_R
1461 236 : static int libc_getgrgid_r(gid_t gid,
1462 : struct group *grp,
1463 : char *buf,
1464 : size_t buflen,
1465 : struct group **result)
1466 : {
1467 236 : nwrap_bind_symbol_all();
1468 :
1469 236 : return nwrap_main_global->libc->symbols._libc_getgrgid_r.f(gid,
1470 : grp,
1471 : buf,
1472 : buflen,
1473 : result);
1474 : }
1475 : #endif
1476 :
1477 0 : static void libc_setgrent(void)
1478 : {
1479 0 : nwrap_bind_symbol_all();
1480 :
1481 0 : nwrap_main_global->libc->symbols._libc_setgrent.f();
1482 0 : }
1483 :
1484 0 : static struct group *libc_getgrent(void)
1485 : {
1486 0 : nwrap_bind_symbol_all();
1487 :
1488 0 : return nwrap_main_global->libc->symbols._libc_getgrent.f();
1489 : }
1490 :
1491 : #ifdef HAVE_GETGRENT_R
1492 : # ifdef HAVE_SOLARIS_GETGRENT_R
1493 : static struct group *libc_getgrent_r(struct group *group,
1494 : char *buf,
1495 : size_t buflen)
1496 : {
1497 : nwrap_bind_symbol_all();
1498 :
1499 : return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
1500 : buf,
1501 : buflen);
1502 : }
1503 : # else /* HAVE_SOLARIS_GETGRENT_R */
1504 0 : static int libc_getgrent_r(struct group *group,
1505 : char *buf,
1506 : size_t buflen,
1507 : struct group **result)
1508 : {
1509 0 : nwrap_bind_symbol_all();
1510 :
1511 0 : return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
1512 : buf,
1513 : buflen,
1514 : result);
1515 : }
1516 : # endif /* HAVE_SOLARIS_GETGRENT_R */
1517 : #endif /* HAVE_GETGRENT_R */
1518 :
1519 0 : static void libc_endgrent(void)
1520 : {
1521 0 : nwrap_bind_symbol_all();
1522 :
1523 0 : nwrap_main_global->libc->symbols._libc_endgrent.f();
1524 0 : }
1525 :
1526 : #ifdef HAVE_GETGROUPLIST
1527 0 : static int libc_getgrouplist(const char *user,
1528 : gid_t group,
1529 : gid_t *groups,
1530 : int *ngroups)
1531 : {
1532 0 : nwrap_bind_symbol_all();
1533 :
1534 0 : return nwrap_main_global->libc->symbols._libc_getgrouplist.f(user,
1535 : group,
1536 : groups,
1537 : ngroups);
1538 : }
1539 : #endif
1540 :
1541 0 : static void libc_sethostent(int stayopen)
1542 : {
1543 0 : nwrap_bind_symbol_all();
1544 :
1545 0 : nwrap_main_global->libc->symbols._libc_sethostent.f(stayopen);
1546 0 : }
1547 :
1548 0 : static struct hostent *libc_gethostent(void)
1549 : {
1550 0 : nwrap_bind_symbol_all();
1551 :
1552 0 : return nwrap_main_global->libc->symbols._libc_gethostent.f();
1553 : }
1554 :
1555 0 : static void libc_endhostent(void)
1556 : {
1557 0 : nwrap_bind_symbol_all();
1558 :
1559 0 : nwrap_main_global->libc->symbols._libc_endhostent.f();
1560 0 : }
1561 :
1562 0 : static struct hostent *libc_gethostbyname(const char *name)
1563 : {
1564 0 : nwrap_bind_symbol_all();
1565 :
1566 0 : return nwrap_main_global->libc->symbols._libc_gethostbyname.f(name);
1567 : }
1568 :
1569 : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1570 0 : static struct hostent *libc_gethostbyname2(const char *name, int af)
1571 : {
1572 0 : nwrap_bind_symbol_all();
1573 :
1574 0 : return nwrap_main_global->libc->symbols._libc_gethostbyname2.f(name, af);
1575 : }
1576 : #endif
1577 :
1578 : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
1579 0 : static int libc_gethostbyname2_r(const char *name,
1580 : int af,
1581 : struct hostent *ret,
1582 : char *buf,
1583 : size_t buflen,
1584 : struct hostent **result,
1585 : int *h_errnop)
1586 : {
1587 0 : nwrap_bind_symbol_all();
1588 :
1589 0 : return nwrap_main_global->libc->symbols._libc_gethostbyname2_r.f(name,
1590 : af,
1591 : ret,
1592 : buf,
1593 : buflen,
1594 : result,
1595 : h_errnop);
1596 : }
1597 : #endif
1598 :
1599 0 : static struct hostent *libc_gethostbyaddr(const void *addr,
1600 : socklen_t len,
1601 : int type)
1602 : {
1603 0 : nwrap_bind_symbol_all();
1604 :
1605 0 : return nwrap_main_global->libc->symbols._libc_gethostbyaddr.f(addr,
1606 : len,
1607 : type);
1608 : }
1609 :
1610 7249 : static int libc_gethostname(char *name, size_t len)
1611 : {
1612 7249 : nwrap_bind_symbol_all();
1613 :
1614 7249 : return nwrap_main_global->libc->symbols._libc_gethostname.f(name, len);
1615 : }
1616 :
1617 : #ifdef HAVE_GETHOSTBYNAME_R
1618 0 : static int libc_gethostbyname_r(const char *name,
1619 : struct hostent *ret,
1620 : char *buf,
1621 : size_t buflen,
1622 : struct hostent **result,
1623 : int *h_errnop)
1624 : {
1625 0 : nwrap_bind_symbol_all();
1626 :
1627 0 : return nwrap_main_global->libc->symbols._libc_gethostbyname_r.f(name,
1628 : ret,
1629 : buf,
1630 : buflen,
1631 : result,
1632 : h_errnop);
1633 : }
1634 : #endif
1635 :
1636 : #ifdef HAVE_GETHOSTBYADDR_R
1637 0 : static int libc_gethostbyaddr_r(const void *addr,
1638 : socklen_t len,
1639 : int type,
1640 : struct hostent *ret,
1641 : char *buf,
1642 : size_t buflen,
1643 : struct hostent **result,
1644 : int *h_errnop)
1645 : {
1646 0 : nwrap_bind_symbol_all();
1647 :
1648 0 : return nwrap_main_global->libc->symbols._libc_gethostbyaddr_r.f(addr,
1649 : len,
1650 : type,
1651 : ret,
1652 : buf,
1653 : buflen,
1654 : result,
1655 : h_errnop);
1656 : }
1657 : #endif
1658 :
1659 484818 : static int libc_getaddrinfo(const char *node,
1660 : const char *service,
1661 : const struct addrinfo *hints,
1662 : struct addrinfo **res)
1663 : {
1664 484818 : nwrap_bind_symbol_all();
1665 :
1666 484818 : return nwrap_main_global->libc->symbols._libc_getaddrinfo.f(node,
1667 : service,
1668 : hints,
1669 : res);
1670 : }
1671 :
1672 5584 : static int libc_getnameinfo(const struct sockaddr *sa,
1673 : socklen_t salen,
1674 : char *host,
1675 : size_t hostlen,
1676 : char *serv,
1677 : size_t servlen,
1678 : int flags)
1679 : {
1680 5584 : nwrap_bind_symbol_all();
1681 :
1682 5584 : return nwrap_main_global->libc->symbols._libc_getnameinfo.f(sa,
1683 : salen,
1684 : host,
1685 : hostlen,
1686 : serv,
1687 : servlen,
1688 : flags);
1689 : }
1690 :
1691 11282 : static void __nwrap_bind_symbol_all_once(void)
1692 : {
1693 11282 : nwrap_bind_symbol_libc(getpwnam);
1694 : #ifdef HAVE_GETPWNAM_R
1695 : # ifdef HAVE___POSIX_GETPWNAM_R
1696 : nwrap_bind_symbol_libc_posix(getpwnam_r);
1697 : # else
1698 11282 : nwrap_bind_symbol_libc(getpwnam_r);
1699 : # endif
1700 : #endif
1701 11282 : nwrap_bind_symbol_libc(getpwuid);
1702 : #ifdef HAVE_GETPWUID_R
1703 : # ifdef HAVE___POSIX_GETPWUID_R
1704 : nwrap_bind_symbol_libc_posix(getpwuid_r);
1705 : # else
1706 11282 : nwrap_bind_symbol_libc(getpwuid_r);
1707 : # endif
1708 : #endif
1709 11282 : nwrap_bind_symbol_libc(setpwent);
1710 11282 : nwrap_bind_symbol_libc(getpwent);
1711 : #ifdef HAVE_GETPWENT_R
1712 11282 : nwrap_bind_symbol_libc(getpwent_r);
1713 : #endif
1714 11282 : nwrap_bind_symbol_libc(endpwent);
1715 11282 : nwrap_bind_symbol_libc(initgroups);
1716 11282 : nwrap_bind_symbol_libc(getgrnam);
1717 : #ifdef HAVE_GETGRNAM_R
1718 : # ifdef HAVE___POSIX_GETGRNAM_R
1719 : nwrap_bind_symbol_libc_posix(getgrnam_r);
1720 : # else
1721 11282 : nwrap_bind_symbol_libc(getgrnam_r);
1722 : # endif
1723 : #endif
1724 11282 : nwrap_bind_symbol_libc(getgrgid);
1725 : #ifdef HAVE_GETGRGID_R
1726 : # ifdef HAVE___POSIX_GETGRGID_R
1727 : nwrap_bind_symbol_libc_posix(getgrgid_r);
1728 : # else
1729 11282 : nwrap_bind_symbol_libc(getgrgid_r);
1730 : # endif
1731 : #endif
1732 11282 : nwrap_bind_symbol_libc(setgrent);
1733 11282 : nwrap_bind_symbol_libc(getgrent);
1734 11282 : nwrap_bind_symbol_libc(getgrent_r);
1735 11282 : nwrap_bind_symbol_libc(endgrent);
1736 11282 : nwrap_bind_symbol_libc(getgrouplist);
1737 11282 : nwrap_bind_symbol_libnsl(sethostent);
1738 11282 : nwrap_bind_symbol_libnsl(gethostent);
1739 11282 : nwrap_bind_symbol_libnsl(endhostent);
1740 11282 : nwrap_bind_symbol_libnsl(gethostbyname);
1741 : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1742 11282 : nwrap_bind_symbol_libnsl(gethostbyname2);
1743 : #endif
1744 : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
1745 11282 : nwrap_bind_symbol_libnsl(gethostbyname2_r);
1746 : #endif
1747 11282 : nwrap_bind_symbol_libnsl(gethostbyaddr);
1748 11282 : nwrap_bind_symbol_libnsl(gethostname);
1749 : #ifdef HAVE_GETHOSTBYNAME_R
1750 11282 : nwrap_bind_symbol_libnsl(gethostbyname_r);
1751 : #endif
1752 : #ifdef HAVE_GETHOSTBYADDR_R
1753 11282 : nwrap_bind_symbol_libnsl(gethostbyaddr_r);
1754 : #endif
1755 11282 : nwrap_bind_symbol_libsocket(getaddrinfo);
1756 11282 : nwrap_bind_symbol_libsocket(getnameinfo);
1757 11282 : }
1758 :
1759 501497 : static void nwrap_bind_symbol_all(void)
1760 : {
1761 : static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT;
1762 :
1763 501497 : pthread_once(&all_symbol_binding_once, __nwrap_bind_symbol_all_once);
1764 501497 : }
1765 :
1766 : /*********************************************************
1767 : * NWRAP NSS MODULE LOADER FUNCTIONS
1768 : *********************************************************/
1769 :
1770 152867 : static void *_nwrap_bind_nss_module_symbol(struct nwrap_backend *b,
1771 : const char *fn_name)
1772 : {
1773 152867 : void *res = NULL;
1774 152867 : char *s = NULL;
1775 : int rc;
1776 :
1777 152867 : if (b->so_handle == NULL) {
1778 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
1779 0 : return NULL;
1780 : }
1781 :
1782 152867 : rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name);
1783 152867 : if (rc == -1) {
1784 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1785 0 : return NULL;
1786 : }
1787 :
1788 152867 : res = dlsym(b->so_handle, s);
1789 152867 : if (res == NULL) {
1790 23518 : NWRAP_LOG(NWRAP_LOG_WARN,
1791 : "Cannot find function %s in %s",
1792 : s, b->so_path);
1793 : }
1794 152867 : SAFE_FREE(s);
1795 152867 : return res;
1796 : }
1797 :
1798 : #define nwrap_nss_module_bind_symbol(sym_name) \
1799 : if (symbols->_nss_##sym_name.obj == NULL) { \
1800 : symbols->_nss_##sym_name.obj = \
1801 : _nwrap_bind_nss_module_symbol(b, #sym_name); \
1802 : }
1803 :
1804 : #define nwrap_nss_module_bind_symbol2(sym_name, alt_name) \
1805 : if (symbols->_nss_##sym_name.obj == NULL) { \
1806 : symbols->_nss_##sym_name.obj = \
1807 : _nwrap_bind_nss_module_symbol(b, #alt_name); \
1808 : }
1809 :
1810 : static struct nwrap_nss_module_symbols *
1811 11759 : nwrap_bind_nss_module_symbols(struct nwrap_backend *b)
1812 : {
1813 : struct nwrap_nss_module_symbols *symbols;
1814 :
1815 11759 : if (!b->so_handle) {
1816 0 : return NULL;
1817 : }
1818 :
1819 11759 : symbols = calloc(1, sizeof(struct nwrap_nss_module_symbols));
1820 11759 : if (symbols == NULL) {
1821 0 : return NULL;
1822 : }
1823 :
1824 11759 : nwrap_nss_module_bind_symbol(getpwnam_r);
1825 11759 : nwrap_nss_module_bind_symbol(getpwuid_r);
1826 11759 : nwrap_nss_module_bind_symbol(setpwent);
1827 11759 : nwrap_nss_module_bind_symbol(getpwent_r);
1828 11759 : nwrap_nss_module_bind_symbol(endpwent);
1829 11759 : nwrap_nss_module_bind_symbol2(initgroups, initgroups_dyn);
1830 11759 : nwrap_nss_module_bind_symbol(getgrnam_r);
1831 11759 : nwrap_nss_module_bind_symbol(getgrgid_r);
1832 11759 : nwrap_nss_module_bind_symbol(setgrent);
1833 11759 : nwrap_nss_module_bind_symbol(getgrent_r);
1834 11759 : nwrap_nss_module_bind_symbol(endgrent);
1835 11759 : nwrap_nss_module_bind_symbol(gethostbyaddr_r);
1836 11759 : nwrap_nss_module_bind_symbol(gethostbyname2_r);
1837 :
1838 11759 : return symbols;
1839 : }
1840 :
1841 11759 : static void *nwrap_load_module(const char *so_path)
1842 : {
1843 : void *h;
1844 :
1845 11759 : if (!so_path || !strlen(so_path)) {
1846 0 : return NULL;
1847 : }
1848 :
1849 11759 : h = dlopen(so_path, RTLD_LAZY);
1850 11759 : if (!h) {
1851 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
1852 : "Cannot open shared library %s",
1853 : so_path);
1854 0 : return NULL;
1855 : }
1856 :
1857 11759 : return h;
1858 : }
1859 :
1860 31248 : static bool nwrap_module_init(const char *name,
1861 : struct nwrap_ops *ops,
1862 : const char *so_path,
1863 : size_t *num_backends,
1864 : struct nwrap_backend **backends)
1865 : {
1866 31248 : struct nwrap_backend *b = NULL;
1867 31248 : size_t n = *num_backends + 1;
1868 :
1869 31248 : b = realloc(*backends, sizeof(struct nwrap_backend) * n);
1870 31248 : if (b == NULL) {
1871 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1872 0 : return false;
1873 : }
1874 31248 : *backends = b;
1875 :
1876 31248 : b = &((*backends)[*num_backends]);
1877 :
1878 31248 : *b = (struct nwrap_backend) {
1879 : .name = name,
1880 : .ops = ops,
1881 : .so_path = so_path,
1882 : };
1883 :
1884 31248 : if (so_path != NULL) {
1885 11759 : b->so_handle = nwrap_load_module(so_path);
1886 11759 : b->symbols = nwrap_bind_nss_module_symbols(b);
1887 11759 : if (b->symbols == NULL) {
1888 0 : return false;
1889 : }
1890 : }
1891 :
1892 31248 : *num_backends = n;
1893 :
1894 31248 : return true;
1895 : }
1896 :
1897 19489 : static void nwrap_libc_init(struct nwrap_main *r)
1898 : {
1899 19489 : r->libc = calloc(1, sizeof(struct nwrap_libc));
1900 19489 : if (r->libc == NULL) {
1901 0 : printf("Failed to allocate memory for libc");
1902 0 : exit(-1);
1903 : }
1904 19489 : }
1905 :
1906 19489 : static void nwrap_backend_init(struct nwrap_main *r)
1907 : {
1908 19489 : const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
1909 19489 : const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1910 :
1911 19489 : r->num_backends = 0;
1912 19489 : r->backends = NULL;
1913 :
1914 19489 : if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
1915 : &r->num_backends,
1916 : &r->backends)) {
1917 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
1918 : "Failed to initialize 'files' backend");
1919 0 : return;
1920 : }
1921 :
1922 19489 : if (module_so_path != NULL &&
1923 11816 : module_so_path[0] != '\0' &&
1924 11759 : module_fn_name != NULL &&
1925 11759 : module_fn_name[0] != '\0') {
1926 11759 : if (!nwrap_module_init(module_fn_name,
1927 : &nwrap_module_ops,
1928 : module_so_path,
1929 : &r->num_backends,
1930 : &r->backends)) {
1931 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
1932 : "Failed to initialize '%s' backend",
1933 : module_fn_name);
1934 0 : return;
1935 : }
1936 : }
1937 : }
1938 :
1939 373998 : static int _nss_wrapper_init_mutex(pthread_mutex_t *m, const char *name)
1940 : {
1941 : pthread_mutexattr_t ma;
1942 373998 : bool need_destroy = false;
1943 373998 : int ret = 0;
1944 :
1945 : #define __CHECK(cmd) do { \
1946 : ret = cmd; \
1947 : if (ret != 0) { \
1948 : NWRAP_LOG(NWRAP_LOG_ERROR, \
1949 : "%s: %s - failed %d", \
1950 : name, #cmd, ret); \
1951 : goto done; \
1952 : } \
1953 : } while(0)
1954 :
1955 373998 : *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
1956 373998 : __CHECK(pthread_mutexattr_init(&ma));
1957 373998 : need_destroy = true;
1958 373998 : __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK));
1959 373998 : __CHECK(pthread_mutex_init(m, &ma));
1960 373998 : done:
1961 373998 : if (need_destroy) {
1962 373998 : pthread_mutexattr_destroy(&ma);
1963 : }
1964 373998 : return ret;
1965 : }
1966 :
1967 3016015 : static void nwrap_init(void)
1968 : {
1969 : const char *env;
1970 : char *endptr;
1971 : size_t max_hostents_tmp;
1972 : int ok;
1973 :
1974 3016015 : nwrap_mutex_lock(&nwrap_initialized_mutex);
1975 3016015 : if (nwrap_initialized) {
1976 2996526 : nwrap_mutex_unlock(&nwrap_initialized_mutex);
1977 2996526 : return;
1978 : }
1979 :
1980 : /*
1981 : * Still holding nwrap_initialized lock here.
1982 : * We don't use NWRAP_(UN)LOCK_ALL macros here because we
1983 : * want to avoid overhead when other threads do their job.
1984 : */
1985 19489 : nwrap_mutex_lock(&nwrap_global_mutex);
1986 19489 : nwrap_mutex_lock(&nwrap_gr_global_mutex);
1987 19489 : nwrap_mutex_lock(&nwrap_he_global_mutex);
1988 19489 : nwrap_mutex_lock(&nwrap_pw_global_mutex);
1989 19489 : nwrap_mutex_lock(&nwrap_sp_global_mutex);
1990 :
1991 19489 : nwrap_initialized = true;
1992 :
1993 19489 : env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
1994 19489 : if (env != NULL) {
1995 19489 : max_hostents_tmp = (size_t)strtoul(env, &endptr, 10);
1996 19489 : if ((*env == '\0') ||
1997 19489 : (*endptr != '\0') ||
1998 : (max_hostents_tmp == 0)) {
1999 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
2000 : "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
2001 : "value or value is too small. "
2002 : "Using default value: %lu.",
2003 : (unsigned long)max_hostents);
2004 : } else {
2005 19489 : max_hostents = max_hostents_tmp;
2006 : }
2007 : }
2008 : /* Initialize hash table */
2009 19489 : NWRAP_LOG(NWRAP_LOG_DEBUG,
2010 : "Initializing hash table of size %lu items.",
2011 : (unsigned long)max_hostents);
2012 19489 : ok = hcreate(max_hostents);
2013 19489 : if (!ok) {
2014 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2015 : "Failed to initialize hash table");
2016 0 : exit(-1);
2017 : }
2018 :
2019 19489 : nwrap_main_global = &__nwrap_main_global;
2020 :
2021 19489 : nwrap_libc_init(nwrap_main_global);
2022 :
2023 19489 : nwrap_backend_init(nwrap_main_global);
2024 :
2025 : /* passwd */
2026 19489 : nwrap_pw_global.cache = &__nwrap_cache_pw;
2027 :
2028 19489 : nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
2029 19489 : nwrap_pw_global.cache->fp = NULL;
2030 19489 : nwrap_pw_global.cache->fd = -1;
2031 19489 : nwrap_pw_global.cache->private_data = &nwrap_pw_global;
2032 19489 : nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
2033 19489 : nwrap_pw_global.cache->unload = nwrap_pw_unload;
2034 :
2035 : /* shadow */
2036 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2037 19489 : nwrap_sp_global.cache = &__nwrap_cache_sp;
2038 :
2039 19489 : nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
2040 19489 : nwrap_sp_global.cache->fp = NULL;
2041 19489 : nwrap_sp_global.cache->fd = -1;
2042 19489 : nwrap_sp_global.cache->private_data = &nwrap_sp_global;
2043 19489 : nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
2044 19489 : nwrap_sp_global.cache->unload = nwrap_sp_unload;
2045 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2046 :
2047 : /* group */
2048 19489 : nwrap_gr_global.cache = &__nwrap_cache_gr;
2049 :
2050 19489 : nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
2051 19489 : nwrap_gr_global.cache->fp = NULL;
2052 19489 : nwrap_gr_global.cache->fd = -1;
2053 19489 : nwrap_gr_global.cache->private_data = &nwrap_gr_global;
2054 19489 : nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
2055 19489 : nwrap_gr_global.cache->unload = nwrap_gr_unload;
2056 :
2057 : /* hosts */
2058 19489 : nwrap_he_global.cache = &__nwrap_cache_he;
2059 :
2060 19489 : nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
2061 19489 : nwrap_he_global.cache->fp = NULL;
2062 19489 : nwrap_he_global.cache->fd = -1;
2063 19489 : nwrap_he_global.cache->private_data = &nwrap_he_global;
2064 19489 : nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
2065 19489 : nwrap_he_global.cache->unload = nwrap_he_unload;
2066 :
2067 : /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
2068 19489 : nwrap_mutex_unlock(&nwrap_sp_global_mutex);
2069 19489 : nwrap_mutex_unlock(&nwrap_pw_global_mutex);
2070 19489 : nwrap_mutex_unlock(&nwrap_he_global_mutex);
2071 19489 : nwrap_mutex_unlock(&nwrap_gr_global_mutex);
2072 19489 : nwrap_mutex_unlock(&nwrap_global_mutex);
2073 19489 : nwrap_mutex_unlock(&nwrap_initialized_mutex);
2074 : }
2075 :
2076 69295 : bool nss_wrapper_enabled(void)
2077 : {
2078 69295 : nwrap_init();
2079 :
2080 69295 : if (nwrap_pw_global.cache->path == NULL ||
2081 65351 : nwrap_pw_global.cache->path[0] == '\0') {
2082 3944 : return false;
2083 : }
2084 65351 : if (nwrap_gr_global.cache->path == NULL ||
2085 65351 : nwrap_gr_global.cache->path[0] == '\0') {
2086 0 : return false;
2087 : }
2088 :
2089 65351 : return true;
2090 : }
2091 :
2092 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2093 0 : bool nss_wrapper_shadow_enabled(void)
2094 : {
2095 0 : nwrap_init();
2096 :
2097 0 : if (nwrap_sp_global.cache->path == NULL ||
2098 0 : nwrap_sp_global.cache->path[0] == '\0') {
2099 0 : return false;
2100 : }
2101 :
2102 0 : return true;
2103 : }
2104 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2105 :
2106 2178873 : bool nss_wrapper_hosts_enabled(void)
2107 : {
2108 2178873 : nwrap_init();
2109 :
2110 2178873 : if (nwrap_he_global.cache->path == NULL ||
2111 2160656 : nwrap_he_global.cache->path[0] == '\0') {
2112 18217 : return false;
2113 : }
2114 :
2115 2160656 : return true;
2116 : }
2117 :
2118 24471 : static bool nwrap_hostname_enabled(void)
2119 : {
2120 24471 : nwrap_init();
2121 :
2122 24471 : if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
2123 7249 : return false;
2124 : }
2125 :
2126 17222 : return true;
2127 : }
2128 :
2129 18354 : static bool nwrap_parse_file(struct nwrap_cache *nwrap)
2130 : {
2131 18354 : char *line = NULL;
2132 : ssize_t n;
2133 : /* Unused but getline needs it */
2134 : size_t len;
2135 : bool ok;
2136 :
2137 18354 : if (nwrap->st.st_size == 0) {
2138 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
2139 0 : return true;
2140 : }
2141 :
2142 : /* Support for 32-bit system I guess */
2143 18354 : if (nwrap->st.st_size > INT32_MAX) {
2144 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2145 : "Size[%u] larger than INT32_MAX",
2146 : (unsigned)nwrap->st.st_size);
2147 0 : return false;
2148 : }
2149 :
2150 18354 : rewind(nwrap->fp);
2151 :
2152 : do {
2153 207411 : n = getline(&line, &len, nwrap->fp);
2154 207411 : if (n < 0) {
2155 18354 : SAFE_FREE(line);
2156 18354 : if (feof(nwrap->fp)) {
2157 18354 : break;
2158 : }
2159 :
2160 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2161 : "Unable to read line from file: %s",
2162 : nwrap->path);
2163 0 : return false;
2164 : }
2165 :
2166 189057 : if (line[n - 1] == '\n') {
2167 189057 : line[n - 1] = '\0';
2168 : }
2169 :
2170 189057 : if (line[0] == '\0') {
2171 0 : SAFE_FREE(line);
2172 0 : continue;
2173 : }
2174 :
2175 189057 : ok = nwrap->parse_line(nwrap, line);
2176 189057 : if (!ok) {
2177 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2178 : "Unable to parse line file: %s",
2179 : line);
2180 0 : SAFE_FREE(line);
2181 0 : return false;
2182 : }
2183 :
2184 : /* Line is parsed without issues so add it to list */
2185 189057 : ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
2186 189057 : if (!ok) {
2187 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2188 : "Unable to add line to vector");
2189 0 : return false;
2190 : }
2191 :
2192 : /* This forces getline to allocate new memory for line. */
2193 189057 : line = NULL;
2194 189057 : } while (!feof(nwrap->fp));
2195 :
2196 18354 : return true;
2197 : }
2198 :
2199 181746 : static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
2200 : {
2201 181746 : nwrap->unload(nwrap);
2202 :
2203 181746 : nwrap_lines_unload(nwrap);
2204 181746 : }
2205 :
2206 702548 : static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
2207 : {
2208 : struct stat st;
2209 : int ret;
2210 : bool ok;
2211 702548 : bool retried = false;
2212 :
2213 702548 : assert(nwrap != NULL);
2214 :
2215 560949 : reopen:
2216 703054 : if (nwrap->fd < 0) {
2217 17807 : nwrap->fp = fopen(nwrap->path, "re");
2218 17807 : if (nwrap->fp == NULL) {
2219 0 : nwrap->fd = -1;
2220 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2221 : "Unable to open '%s' readonly %d:%s",
2222 : nwrap->path, nwrap->fd,
2223 : strerror(errno));
2224 0 : return false;
2225 :
2226 : }
2227 17807 : nwrap->fd = fileno(nwrap->fp);
2228 17807 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
2229 : }
2230 :
2231 703054 : ret = fstat(nwrap->fd, &st);
2232 703054 : if (ret != 0 && errno == EBADF && retried == false) {
2233 : /* maybe something closed the fd on our behalf */
2234 0 : NWRAP_LOG(NWRAP_LOG_TRACE,
2235 : "fstat(%s) - %d:%s - reopen",
2236 : nwrap->path,
2237 : ret,
2238 : strerror(errno));
2239 0 : retried = true;
2240 0 : memset(&nwrap->st, 0, sizeof(nwrap->st));
2241 0 : fclose(nwrap->fp);
2242 0 : nwrap->fp = NULL;
2243 0 : nwrap->fd = -1;
2244 0 : goto reopen;
2245 : }
2246 703054 : else if (ret != 0) {
2247 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2248 : "fstat(%s) - %d:%s",
2249 : nwrap->path,
2250 : ret,
2251 : strerror(errno));
2252 0 : fclose(nwrap->fp);
2253 0 : nwrap->fp = NULL;
2254 0 : nwrap->fd = -1;
2255 0 : return false;
2256 : }
2257 :
2258 703054 : if (retried == false && st.st_nlink == 0) {
2259 : /* maybe someone has replaced the file... */
2260 506 : NWRAP_LOG(NWRAP_LOG_TRACE,
2261 : "st_nlink == 0, reopen %s",
2262 : nwrap->path);
2263 506 : retried = true;
2264 506 : memset(&nwrap->st, 0, sizeof(nwrap->st));
2265 506 : fclose(nwrap->fp);
2266 506 : nwrap->fp = NULL;
2267 506 : nwrap->fd = -1;
2268 506 : goto reopen;
2269 : }
2270 :
2271 702548 : if (st.st_mtime == nwrap->st.st_mtime) {
2272 684194 : NWRAP_LOG(NWRAP_LOG_TRACE,
2273 : "st_mtime[%u] hasn't changed, skip reload",
2274 : (unsigned)st.st_mtime);
2275 684194 : return true;
2276 : }
2277 :
2278 18354 : NWRAP_LOG(NWRAP_LOG_TRACE,
2279 : "st_mtime has changed [%u] => [%u], start reload",
2280 : (unsigned)st.st_mtime,
2281 : (unsigned)nwrap->st.st_mtime);
2282 :
2283 18354 : nwrap->st = st;
2284 :
2285 18354 : nwrap_files_cache_unload(nwrap);
2286 :
2287 18354 : ok = nwrap_parse_file(nwrap);
2288 18354 : if (!ok) {
2289 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
2290 0 : nwrap_files_cache_unload(nwrap);
2291 0 : return false;
2292 : }
2293 :
2294 18354 : NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
2295 18354 : return true;
2296 : }
2297 :
2298 : /*
2299 : * the caller has to call nwrap_unload() on failure
2300 : */
2301 128220 : static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
2302 : {
2303 : struct nwrap_pw *nwrap_pw;
2304 : char *c;
2305 : char *p;
2306 : char *e;
2307 : struct passwd *pw;
2308 : size_t list_size;
2309 :
2310 128220 : nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
2311 :
2312 128220 : list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
2313 128220 : pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
2314 128220 : if (!pw) {
2315 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2316 : "realloc(%u) failed",
2317 : (unsigned)list_size);
2318 0 : return false;
2319 : }
2320 128220 : nwrap_pw->list = pw;
2321 :
2322 128220 : pw = &nwrap_pw->list[nwrap_pw->num];
2323 :
2324 128220 : c = line;
2325 :
2326 : /* name */
2327 128220 : p = strchr(c, ':');
2328 128220 : if (!p) {
2329 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2330 : "Invalid line[%s]: '%s'",
2331 : line,
2332 : c);
2333 0 : return false;
2334 : }
2335 128220 : *p = '\0';
2336 128220 : p++;
2337 128220 : pw->pw_name = c;
2338 128220 : c = p;
2339 :
2340 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
2341 :
2342 : /* password */
2343 128220 : p = strchr(c, ':');
2344 128220 : if (!p) {
2345 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2346 0 : return false;
2347 : }
2348 128220 : *p = '\0';
2349 128220 : p++;
2350 128220 : pw->pw_passwd = c;
2351 128220 : c = p;
2352 :
2353 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
2354 :
2355 : /* uid */
2356 128220 : p = strchr(c, ':');
2357 128220 : if (!p) {
2358 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2359 0 : return false;
2360 : }
2361 128220 : *p = '\0';
2362 128220 : p++;
2363 128220 : e = NULL;
2364 128220 : pw->pw_uid = (uid_t)strtoul(c, &e, 10);
2365 128220 : if (c == e) {
2366 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2367 : "Invalid line[%s]: '%s' - %s",
2368 : line, c, strerror(errno));
2369 0 : return false;
2370 : }
2371 128220 : if (e == NULL) {
2372 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2373 : "Invalid line[%s]: '%s' - %s",
2374 : line, c, strerror(errno));
2375 0 : return false;
2376 : }
2377 128220 : if (e[0] != '\0') {
2378 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2379 : "Invalid line[%s]: '%s' - %s",
2380 : line, c, strerror(errno));
2381 0 : return false;
2382 : }
2383 128220 : c = p;
2384 :
2385 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
2386 :
2387 : /* gid */
2388 128220 : p = strchr(c, ':');
2389 128220 : if (!p) {
2390 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2391 0 : return false;
2392 : }
2393 128220 : *p = '\0';
2394 128220 : p++;
2395 128220 : e = NULL;
2396 128220 : pw->pw_gid = (gid_t)strtoul(c, &e, 10);
2397 128220 : if (c == e) {
2398 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2399 : "Invalid line[%s]: '%s' - %s",
2400 : line, c, strerror(errno));
2401 0 : return false;
2402 : }
2403 128220 : if (e == NULL) {
2404 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2405 : "Invalid line[%s]: '%s' - %s",
2406 : line, c, strerror(errno));
2407 0 : return false;
2408 : }
2409 128220 : if (e[0] != '\0') {
2410 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2411 : "Invalid line[%s]: '%s' - %s",
2412 : line, c, strerror(errno));
2413 0 : return false;
2414 : }
2415 128220 : c = p;
2416 :
2417 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
2418 :
2419 : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
2420 : pw->pw_class = discard_const_p(char, "");
2421 :
2422 : NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class);
2423 : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
2424 :
2425 : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
2426 : pw->pw_change = 0;
2427 :
2428 : NWRAP_LOG(NWRAP_LOG_TRACE,
2429 : "change[%lu]",
2430 : (unsigned long)pw->pw_change);
2431 : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
2432 :
2433 : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
2434 : pw->pw_expire = 0;
2435 :
2436 : NWRAP_LOG(NWRAP_LOG_TRACE,
2437 : "expire[%lu]",
2438 : (unsigned long)pw->pw_expire);
2439 : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
2440 :
2441 : /* gecos */
2442 128220 : p = strchr(c, ':');
2443 128220 : if (!p) {
2444 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
2445 0 : return false;
2446 : }
2447 128220 : *p = '\0';
2448 128220 : p++;
2449 128220 : pw->pw_gecos = c;
2450 128220 : c = p;
2451 :
2452 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
2453 :
2454 : /* dir */
2455 128220 : p = strchr(c, ':');
2456 128220 : if (!p) {
2457 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
2458 0 : return false;
2459 : }
2460 128220 : *p = '\0';
2461 128220 : p++;
2462 128220 : pw->pw_dir = c;
2463 128220 : c = p;
2464 :
2465 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
2466 :
2467 : /* shell */
2468 128220 : pw->pw_shell = c;
2469 128220 : NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
2470 :
2471 128220 : NWRAP_LOG(NWRAP_LOG_DEBUG,
2472 : "Added user[%s:%s:%u:%u:%s:%s:%s]",
2473 : pw->pw_name, pw->pw_passwd,
2474 : pw->pw_uid, pw->pw_gid,
2475 : pw->pw_gecos, pw->pw_dir, pw->pw_shell);
2476 :
2477 128220 : nwrap_pw->num++;
2478 128220 : return true;
2479 : }
2480 :
2481 51442 : static void nwrap_pw_unload(struct nwrap_cache *nwrap)
2482 : {
2483 : struct nwrap_pw *nwrap_pw;
2484 51442 : nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
2485 :
2486 51442 : SAFE_FREE(nwrap_pw->list);
2487 51442 : nwrap_pw->num = 0;
2488 51442 : nwrap_pw->idx = 0;
2489 51442 : }
2490 :
2491 2351 : static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
2492 : char *buf, size_t buflen, struct passwd **dstp)
2493 : {
2494 : char *first;
2495 : char *last;
2496 : off_t ofs;
2497 :
2498 2351 : first = src->pw_name;
2499 :
2500 2351 : last = src->pw_shell;
2501 25861 : while (*last) last++;
2502 :
2503 2351 : ofs = PTR_DIFF(last + 1, first);
2504 :
2505 2351 : if (ofs > (off_t) buflen) {
2506 0 : return ERANGE;
2507 : }
2508 :
2509 2351 : memcpy(buf, first, ofs);
2510 :
2511 2351 : ofs = PTR_DIFF(src->pw_name, first);
2512 2351 : dst->pw_name = buf + ofs;
2513 2351 : ofs = PTR_DIFF(src->pw_passwd, first);
2514 2351 : dst->pw_passwd = buf + ofs;
2515 2351 : dst->pw_uid = src->pw_uid;
2516 2351 : dst->pw_gid = src->pw_gid;
2517 : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
2518 : ofs = PTR_DIFF(src->pw_class, first);
2519 : dst->pw_class = buf + ofs;
2520 : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
2521 :
2522 : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
2523 : dst->pw_change = 0;
2524 : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
2525 :
2526 : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
2527 : dst->pw_expire = 0;
2528 : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
2529 :
2530 2351 : ofs = PTR_DIFF(src->pw_gecos, first);
2531 2351 : dst->pw_gecos = buf + ofs;
2532 2351 : ofs = PTR_DIFF(src->pw_dir, first);
2533 2351 : dst->pw_dir = buf + ofs;
2534 2351 : ofs = PTR_DIFF(src->pw_shell, first);
2535 2351 : dst->pw_shell = buf + ofs;
2536 :
2537 2351 : if (dstp) {
2538 2351 : *dstp = dst;
2539 : }
2540 :
2541 2351 : return 0;
2542 : }
2543 :
2544 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2545 0 : static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
2546 : {
2547 : struct nwrap_sp *nwrap_sp;
2548 : struct spwd *sp;
2549 : size_t list_size;
2550 : char *c;
2551 : char *e;
2552 : char *p;
2553 :
2554 0 : nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
2555 :
2556 0 : list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
2557 0 : sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
2558 0 : if (sp == NULL) {
2559 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2560 : "realloc(%u) failed",
2561 : (unsigned)list_size);
2562 0 : return false;
2563 : }
2564 0 : nwrap_sp->list = sp;
2565 :
2566 0 : sp = &nwrap_sp->list[nwrap_sp->num];
2567 :
2568 0 : c = line;
2569 :
2570 : /* name */
2571 0 : p = strchr(c, ':');
2572 0 : if (p == NULL) {
2573 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2574 : "name -- Invalid line[%s]: '%s'",
2575 : line,
2576 : c);
2577 0 : return false;
2578 : }
2579 0 : *p = '\0';
2580 0 : p++;
2581 0 : sp->sp_namp = c;
2582 0 : c = p;
2583 :
2584 0 : NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
2585 :
2586 : /* pwd */
2587 0 : p = strchr(c, ':');
2588 0 : if (p == NULL) {
2589 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2590 : "pwd -- Invalid line[%s]: '%s'",
2591 : line,
2592 : c);
2593 0 : return false;
2594 : }
2595 0 : *p = '\0';
2596 0 : p++;
2597 0 : sp->sp_pwdp = c;
2598 0 : c = p;
2599 :
2600 : /* lstchg (long) */
2601 0 : if (c[0] == ':') {
2602 0 : sp->sp_lstchg = -1;
2603 0 : p++;
2604 : } else {
2605 0 : p = strchr(c, ':');
2606 0 : if (p == NULL) {
2607 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2608 : "lstchg -- Invalid line[%s]: '%s'",
2609 : line,
2610 : c);
2611 0 : return false;
2612 : }
2613 0 : *p = '\0';
2614 0 : p++;
2615 0 : sp->sp_lstchg = strtol(c, &e, 10);
2616 0 : if (c == e) {
2617 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2618 : "lstchg -- Invalid line[%s]: '%s' - %s",
2619 : line, c, strerror(errno));
2620 0 : return false;
2621 : }
2622 0 : if (e == NULL) {
2623 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2624 : "lstchg -- Invalid line[%s]: '%s' - %s",
2625 : line, c, strerror(errno));
2626 0 : return false;
2627 : }
2628 0 : if (e[0] != '\0') {
2629 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2630 : "lstchg -- Invalid line[%s]: '%s' - %s",
2631 : line, c, strerror(errno));
2632 0 : return false;
2633 : }
2634 : }
2635 0 : c = p;
2636 :
2637 : /* min (long) */
2638 0 : if (c[0] == ':') {
2639 0 : sp->sp_min = -1;
2640 0 : p++;
2641 : } else {
2642 0 : p = strchr(c, ':');
2643 0 : if (p == NULL) {
2644 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2645 : "min -- Invalid line[%s]: '%s'",
2646 : line,
2647 : c);
2648 0 : return false;
2649 : }
2650 0 : *p = '\0';
2651 0 : p++;
2652 0 : sp->sp_min = strtol(c, &e, 10);
2653 0 : if (c == e) {
2654 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2655 : "min -- Invalid line[%s]: '%s' - %s",
2656 : line, c, strerror(errno));
2657 0 : return false;
2658 : }
2659 0 : if (e == NULL) {
2660 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2661 : "min -- Invalid line[%s]: '%s' - %s",
2662 : line, c, strerror(errno));
2663 0 : return false;
2664 : }
2665 0 : if (e[0] != '\0') {
2666 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2667 : "min -- Invalid line[%s]: '%s' - %s",
2668 : line, c, strerror(errno));
2669 0 : return false;
2670 : }
2671 : }
2672 0 : c = p;
2673 :
2674 : /* max (long) */
2675 0 : if (c[0] == ':') {
2676 0 : sp->sp_max = -1;
2677 0 : p++;
2678 : } else {
2679 0 : p = strchr(c, ':');
2680 0 : if (p == NULL) {
2681 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2682 : "max -- Invalid line[%s]: '%s'",
2683 : line,
2684 : c);
2685 0 : return false;
2686 : }
2687 0 : *p = '\0';
2688 0 : p++;
2689 0 : sp->sp_max = strtol(c, &e, 10);
2690 0 : if (c == e) {
2691 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2692 : "max -- Invalid line[%s]: '%s' - %s",
2693 : line, c, strerror(errno));
2694 0 : return false;
2695 : }
2696 0 : if (e == NULL) {
2697 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2698 : "max -- Invalid line[%s]: '%s' - %s",
2699 : line, c, strerror(errno));
2700 0 : return false;
2701 : }
2702 0 : if (e[0] != '\0') {
2703 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2704 : "max -- Invalid line[%s]: '%s' - %s",
2705 : line, c, strerror(errno));
2706 0 : return false;
2707 : }
2708 : }
2709 0 : c = p;
2710 :
2711 : /* warn (long) */
2712 0 : if (c[0] == ':') {
2713 0 : sp->sp_warn = -1;
2714 0 : p++;
2715 : } else {
2716 0 : p = strchr(c, ':');
2717 0 : if (p == NULL) {
2718 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2719 : "warn -- Invalid line[%s]: '%s'",
2720 : line,
2721 : c);
2722 0 : return false;
2723 : }
2724 0 : *p = '\0';
2725 0 : p++;
2726 0 : sp->sp_warn = strtol(c, &e, 10);
2727 0 : if (c == e) {
2728 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2729 : "warn -- Invalid line[%s]: '%s' - %s",
2730 : line, c, strerror(errno));
2731 0 : return false;
2732 : }
2733 0 : if (e == NULL) {
2734 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2735 : "warn -- Invalid line[%s]: '%s' - %s",
2736 : line, c, strerror(errno));
2737 0 : return false;
2738 : }
2739 0 : if (e[0] != '\0') {
2740 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2741 : "warn -- Invalid line[%s]: '%s' - %s",
2742 : line, c, strerror(errno));
2743 0 : return false;
2744 : }
2745 : }
2746 0 : c = p;
2747 :
2748 : /* inact (long) */
2749 0 : if (c[0] == ':') {
2750 0 : sp->sp_inact = -1;
2751 0 : p++;
2752 : } else {
2753 0 : p = strchr(c, ':');
2754 0 : if (p == NULL) {
2755 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2756 : "inact -- Invalid line[%s]: '%s'",
2757 : line,
2758 : c);
2759 0 : return false;
2760 : }
2761 0 : *p = '\0';
2762 0 : p++;
2763 0 : sp->sp_inact = strtol(c, &e, 10);
2764 0 : if (c == e) {
2765 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2766 : "inact -- Invalid line[%s]: '%s' - %s",
2767 : line, c, strerror(errno));
2768 0 : return false;
2769 : }
2770 0 : if (e == NULL) {
2771 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2772 : "inact -- Invalid line[%s]: '%s' - %s",
2773 : line, c, strerror(errno));
2774 0 : return false;
2775 : }
2776 0 : if (e[0] != '\0') {
2777 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2778 : "inact -- Invalid line[%s]: '%s' - %s",
2779 : line, c, strerror(errno));
2780 0 : return false;
2781 : }
2782 : }
2783 0 : c = p;
2784 :
2785 : /* expire (long) */
2786 0 : if (c[0] == ':') {
2787 0 : sp->sp_expire = -1;
2788 0 : p++;
2789 : } else {
2790 0 : p = strchr(c, ':');
2791 0 : if (p == NULL) {
2792 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2793 : "expire -- Invalid line[%s]: '%s'",
2794 : line,
2795 : c);
2796 0 : return false;
2797 : }
2798 0 : *p = '\0';
2799 0 : p++;
2800 0 : sp->sp_expire = strtol(c, &e, 10);
2801 0 : if (c == e) {
2802 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2803 : "expire -- Invalid line[%s]: '%s' - %s",
2804 : line, c, strerror(errno));
2805 0 : return false;
2806 : }
2807 0 : if (e == NULL) {
2808 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2809 : "expire -- Invalid line[%s]: '%s' - %s",
2810 : line, c, strerror(errno));
2811 0 : return false;
2812 : }
2813 0 : if (e[0] != '\0') {
2814 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2815 : "expire -- Invalid line[%s]: '%s' - %s",
2816 : line, c, strerror(errno));
2817 0 : return false;
2818 : }
2819 : }
2820 0 : c = p;
2821 :
2822 0 : nwrap_sp->num++;
2823 0 : return true;
2824 : }
2825 :
2826 40848 : static void nwrap_sp_unload(struct nwrap_cache *nwrap)
2827 : {
2828 : struct nwrap_sp *nwrap_sp;
2829 40848 : nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
2830 :
2831 40848 : SAFE_FREE(nwrap_sp->list);
2832 40848 : nwrap_sp->num = 0;
2833 40848 : nwrap_sp->idx = 0;
2834 40848 : }
2835 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2836 :
2837 : /*
2838 : * the caller has to call nwrap_unload() on failure
2839 : */
2840 4041 : static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
2841 : {
2842 : struct nwrap_gr *nwrap_gr;
2843 : char *c;
2844 : char *p;
2845 : char *e;
2846 : struct group *gr;
2847 : size_t list_size;
2848 : unsigned nummem;
2849 :
2850 4041 : nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2851 :
2852 4041 : list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
2853 4041 : gr = (struct group *)realloc(nwrap_gr->list, list_size);
2854 4041 : if (!gr) {
2855 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
2856 0 : return false;
2857 : }
2858 4041 : nwrap_gr->list = gr;
2859 :
2860 4041 : gr = &nwrap_gr->list[nwrap_gr->num];
2861 :
2862 4041 : c = line;
2863 :
2864 : /* name */
2865 4041 : p = strchr(c, ':');
2866 4041 : if (!p) {
2867 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2868 0 : return false;
2869 : }
2870 4041 : *p = '\0';
2871 4041 : p++;
2872 4041 : gr->gr_name = c;
2873 4041 : c = p;
2874 :
2875 4041 : NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
2876 :
2877 : /* password */
2878 4041 : p = strchr(c, ':');
2879 4041 : if (!p) {
2880 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2881 0 : return false;
2882 : }
2883 4041 : *p = '\0';
2884 4041 : p++;
2885 4041 : gr->gr_passwd = c;
2886 4041 : c = p;
2887 :
2888 4041 : NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
2889 :
2890 : /* gid */
2891 4041 : p = strchr(c, ':');
2892 4041 : if (!p) {
2893 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2894 0 : return false;
2895 : }
2896 4041 : *p = '\0';
2897 4041 : p++;
2898 4041 : e = NULL;
2899 4041 : gr->gr_gid = (gid_t)strtoul(c, &e, 10);
2900 4041 : if (c == e) {
2901 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2902 : "Invalid line[%s]: '%s' - %s",
2903 : line, c, strerror(errno));
2904 0 : return false;
2905 : }
2906 4041 : if (e == NULL) {
2907 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2908 : "Invalid line[%s]: '%s' - %s",
2909 : line, c, strerror(errno));
2910 0 : return false;
2911 : }
2912 4041 : if (e[0] != '\0') {
2913 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2914 : "Invalid line[%s]: '%s' - %s",
2915 : line, c, strerror(errno));
2916 0 : return false;
2917 : }
2918 4041 : c = p;
2919 :
2920 4041 : NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
2921 :
2922 : /* members */
2923 4041 : gr->gr_mem = (char **)malloc(sizeof(char *));
2924 4041 : if (!gr->gr_mem) {
2925 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
2926 0 : return false;
2927 : }
2928 4041 : gr->gr_mem[0] = NULL;
2929 :
2930 5306 : for(nummem = 0; p != NULL && p[0] != '\0'; nummem++) {
2931 : char **m;
2932 : size_t m_size;
2933 1265 : c = p;
2934 1265 : p = strchr(c, ',');
2935 1265 : if (p) {
2936 0 : *p = '\0';
2937 0 : p++;
2938 : }
2939 :
2940 1265 : if (strlen(c) == 0) {
2941 0 : break;
2942 : }
2943 :
2944 1265 : m_size = sizeof(char *) * (nummem+2);
2945 1265 : m = (char **)realloc(gr->gr_mem, m_size);
2946 1265 : if (!m) {
2947 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
2948 : "realloc(%zd) failed",
2949 : m_size);
2950 0 : return false;
2951 : }
2952 1265 : gr->gr_mem = m;
2953 1265 : gr->gr_mem[nummem] = c;
2954 1265 : gr->gr_mem[nummem+1] = NULL;
2955 :
2956 1265 : NWRAP_LOG(NWRAP_LOG_TRACE,
2957 : "member[%u]: '%s'",
2958 : nummem, gr->gr_mem[nummem]);
2959 : }
2960 :
2961 4041 : NWRAP_LOG(NWRAP_LOG_DEBUG,
2962 : "Added group[%s:%s:%u:] with %u members",
2963 : gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
2964 :
2965 4041 : nwrap_gr->num++;
2966 4041 : return true;
2967 : }
2968 :
2969 41294 : static void nwrap_gr_unload(struct nwrap_cache *nwrap)
2970 : {
2971 : int i;
2972 : struct nwrap_gr *nwrap_gr;
2973 41294 : nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2974 :
2975 41294 : if (nwrap_gr->list) {
2976 48864 : for (i=0; i < nwrap_gr->num; i++) {
2977 43167 : SAFE_FREE(nwrap_gr->list[i].gr_mem);
2978 : }
2979 5697 : SAFE_FREE(nwrap_gr->list);
2980 : }
2981 :
2982 41294 : nwrap_gr->num = 0;
2983 41294 : nwrap_gr->idx = 0;
2984 41294 : }
2985 :
2986 2027 : static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
2987 : char *buf, size_t buflen, struct group **dstp)
2988 : {
2989 2027 : char *p = NULL;
2990 2027 : uintptr_t align = 0;
2991 2027 : unsigned int gr_mem_cnt = 0;
2992 : unsigned i;
2993 : size_t total_len;
2994 2027 : size_t gr_name_len = strlen(src->gr_name) + 1;
2995 2027 : size_t gr_passwd_len = strlen(src->gr_passwd) + 1;
2996 : union {
2997 : char *ptr;
2998 : char **data;
2999 : } g_mem;
3000 :
3001 2075 : for (i = 0; src->gr_mem[i] != NULL; i++) {
3002 48 : gr_mem_cnt++;
3003 : }
3004 :
3005 : /* Align the memory for storing pointers */
3006 2027 : align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *));
3007 2027 : total_len = align +
3008 2027 : (1 + gr_mem_cnt) * sizeof(char *) +
3009 : gr_name_len + gr_passwd_len;
3010 :
3011 2027 : if (total_len > buflen) {
3012 0 : errno = ERANGE;
3013 0 : return -1;
3014 : }
3015 2027 : buflen -= total_len;
3016 :
3017 : /* gr_mem */
3018 2027 : p = buf + align;
3019 2027 : g_mem.ptr = p;
3020 2027 : dst->gr_mem = g_mem.data;
3021 :
3022 : /* gr_name */
3023 2027 : p += (1 + gr_mem_cnt) * sizeof(char *);
3024 2027 : dst->gr_name = p;
3025 :
3026 : /* gr_passwd */
3027 2027 : p += gr_name_len;
3028 2027 : dst->gr_passwd = p;
3029 :
3030 : /* gr_mem[x] */
3031 2027 : p += gr_passwd_len;
3032 :
3033 : /* gr_gid */
3034 2027 : dst->gr_gid = src->gr_gid;
3035 :
3036 2027 : memcpy(dst->gr_name, src->gr_name, gr_name_len);
3037 :
3038 2027 : memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len);
3039 :
3040 : /* Set the terminating entry */
3041 2027 : dst->gr_mem[gr_mem_cnt] = NULL;
3042 :
3043 : /* Now add the group members content */
3044 2027 : total_len = 0;
3045 2075 : for (i = 0; i < gr_mem_cnt; i++) {
3046 48 : size_t len = strlen(src->gr_mem[i]) + 1;
3047 :
3048 48 : dst->gr_mem[i] = p;
3049 48 : total_len += len;
3050 48 : p += len;
3051 : }
3052 :
3053 2027 : if (total_len > buflen) {
3054 0 : errno = ERANGE;
3055 0 : return -1;
3056 : }
3057 :
3058 2075 : for (i = 0; i < gr_mem_cnt; i++) {
3059 48 : size_t len = strlen(src->gr_mem[i]) + 1;
3060 :
3061 48 : memcpy(dst->gr_mem[i],
3062 48 : src->gr_mem[i],
3063 : len);
3064 : }
3065 :
3066 2027 : if (dstp != NULL) {
3067 2027 : *dstp = dst;
3068 : }
3069 :
3070 2027 : return 0;
3071 : }
3072 :
3073 177888 : static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
3074 : {
3075 : struct nwrap_entlist *el;
3076 :
3077 177888 : if (ed == NULL) {
3078 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3079 : "entry is NULL, can't create list item");
3080 0 : return NULL;
3081 : }
3082 :
3083 177888 : el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
3084 177888 : if (el == NULL) {
3085 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
3086 0 : return NULL;
3087 : }
3088 :
3089 177888 : el->next = NULL;
3090 177888 : el->ed = ed;
3091 :
3092 177888 : return el;
3093 : }
3094 :
3095 117342 : static bool nwrap_ed_inventarize_add_new(char *const h_name,
3096 : struct nwrap_entdata *const ed)
3097 : {
3098 : ENTRY e;
3099 : ENTRY *p;
3100 : struct nwrap_entlist *el;
3101 : bool ok;
3102 :
3103 117342 : if (h_name == NULL) {
3104 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
3105 0 : return false;
3106 : }
3107 :
3108 117342 : el = nwrap_entlist_init(ed);
3109 117342 : if (el == NULL) {
3110 0 : return false;
3111 : }
3112 :
3113 117342 : e.key = h_name;
3114 117342 : e.data = (void *)el;
3115 :
3116 117342 : p = hsearch(e, ENTER);
3117 117342 : if (p == NULL) {
3118 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3119 : "Hash table is full (%s)!",
3120 : strerror(errno));
3121 0 : return false;
3122 : }
3123 :
3124 117342 : ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
3125 117342 : if (!ok) {
3126 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3127 : "Failed to add list entry to vector.");
3128 0 : return false;
3129 : }
3130 :
3131 117342 : return true;
3132 : }
3133 :
3134 60546 : static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
3135 : struct nwrap_entlist *const el)
3136 : {
3137 : struct nwrap_entlist *cursor;
3138 : struct nwrap_entlist *el_new;
3139 :
3140 60546 : if (el == NULL) {
3141 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
3142 0 : return false;
3143 : }
3144 :
3145 :
3146 60546 : for (cursor = el; cursor->next != NULL; cursor = cursor->next)
3147 : {
3148 0 : if (cursor->ed == ed) {
3149 : /* The entry already exists in this list. */
3150 0 : return true;
3151 : }
3152 : }
3153 :
3154 60546 : if (cursor->ed == ed) {
3155 : /* The entry already exists in this list. */
3156 0 : return true;
3157 : }
3158 :
3159 60546 : el_new = nwrap_entlist_init(ed);
3160 60546 : if (el_new == NULL) {
3161 0 : return false;
3162 : }
3163 :
3164 60546 : cursor->next = el_new;
3165 60546 : return true;
3166 : }
3167 :
3168 177888 : static bool nwrap_ed_inventarize(char *const name,
3169 : struct nwrap_entdata *const ed)
3170 : {
3171 : ENTRY e;
3172 : ENTRY *p;
3173 : bool ok;
3174 :
3175 177888 : e.key = name;
3176 177888 : e.data = NULL;
3177 :
3178 177888 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
3179 :
3180 177888 : p = hsearch(e, FIND);
3181 177888 : if (p == NULL) {
3182 117342 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
3183 117342 : ok = nwrap_ed_inventarize_add_new(name, ed);
3184 : } else {
3185 60546 : struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
3186 :
3187 60546 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
3188 60546 : ok = nwrap_ed_inventarize_add_to_existing(ed, el);
3189 : }
3190 :
3191 177888 : return ok;
3192 : }
3193 :
3194 56796 : static bool nwrap_add_hname(struct nwrap_entdata *const ed)
3195 : {
3196 56796 : char *const h_name = (char *const)(ed->ht.h_name);
3197 : unsigned i;
3198 : bool ok;
3199 :
3200 56796 : ok = nwrap_ed_inventarize(h_name, ed);
3201 56796 : if (!ok) {
3202 0 : return false;
3203 : }
3204 :
3205 56796 : if (ed->ht.h_aliases == NULL) {
3206 0 : return true;
3207 : }
3208 :
3209 : /* Itemize aliases */
3210 121092 : for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
3211 : char *h_name_alias;
3212 :
3213 64296 : h_name_alias = ed->ht.h_aliases[i];
3214 :
3215 64296 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
3216 :
3217 64296 : if (!nwrap_ed_inventarize(h_name_alias, ed)) {
3218 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3219 : "Unable to add alias: %s", h_name_alias);
3220 0 : return false;
3221 : }
3222 : }
3223 :
3224 56796 : return true;
3225 : }
3226 :
3227 56796 : static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
3228 : {
3229 56796 : struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
3230 56796 : bool do_aliases = true;
3231 56796 : ssize_t aliases_count = 0;
3232 : char *p;
3233 : char *i;
3234 : char *n;
3235 :
3236 : char *ip;
3237 : bool ok;
3238 :
3239 : struct nwrap_entdata *ed = (struct nwrap_entdata *)
3240 56796 : malloc(sizeof(struct nwrap_entdata));
3241 56796 : if (ed == NULL) {
3242 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3243 : "Unable to allocate memory for nwrap_entdata");
3244 0 : return false;
3245 : }
3246 56796 : ZERO_STRUCTP(ed);
3247 :
3248 56796 : i = line;
3249 :
3250 : /*
3251 : * IP
3252 : */
3253 :
3254 : /* Walk to first char */
3255 56796 : for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
3256 0 : if (*p == '\0') {
3257 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3258 : "Invalid line[%s]: '%s'",
3259 : line, i);
3260 0 : free(ed);
3261 0 : return false;
3262 : }
3263 : }
3264 :
3265 1475981 : for (i = p; !isspace((int)*p); p++) {
3266 1419185 : if (*p == '\0') {
3267 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3268 : "Invalid line[%s]: '%s'",
3269 : line, i);
3270 0 : free(ed);
3271 0 : return false;
3272 : }
3273 : }
3274 :
3275 56796 : *p = '\0';
3276 :
3277 56796 : if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
3278 28398 : ed->ht.h_addrtype = AF_INET;
3279 28398 : ed->ht.h_length = 4;
3280 : #ifdef HAVE_IPV6
3281 28398 : } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
3282 28398 : ed->ht.h_addrtype = AF_INET6;
3283 28398 : ed->ht.h_length = 16;
3284 : #endif
3285 : } else {
3286 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3287 : "Invalid line[%s]: '%s'",
3288 : line, i);
3289 :
3290 0 : free(ed);
3291 0 : return false;
3292 : }
3293 56796 : ip = i;
3294 :
3295 56796 : ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
3296 56796 : (void *const)ed->addr.host_addr);
3297 56796 : if (!ok) {
3298 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
3299 0 : free(ed);
3300 0 : return false;
3301 : }
3302 56796 : ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
3303 :
3304 56796 : p++;
3305 :
3306 : /*
3307 : * FQDN
3308 : */
3309 :
3310 : /* Walk to first char */
3311 56796 : for (n = p; *p != '_' && !isalnum((int) *p); p++) {
3312 0 : if (*p == '\0') {
3313 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3314 : "Invalid line[%s]: '%s'",
3315 : line, n);
3316 :
3317 0 : free(ed);
3318 0 : return false;
3319 : }
3320 : }
3321 :
3322 1729148 : for (n = p; !isspace((int)*p); p++) {
3323 1672352 : if (*p == '\0') {
3324 0 : do_aliases = false;
3325 0 : break;
3326 : }
3327 : }
3328 :
3329 56796 : *p = '\0';
3330 :
3331 : /* Convert to lowercase. This operate on same memory region */
3332 56796 : str_tolower(n, n);
3333 56796 : ed->ht.h_name = n;
3334 :
3335 : /* glib's getent always dereferences he->h_aliases */
3336 56796 : ed->ht.h_aliases = malloc(sizeof(char *));
3337 56796 : if (ed->ht.h_aliases == NULL) {
3338 0 : free(ed);
3339 0 : return false;
3340 : }
3341 56796 : ed->ht.h_aliases[0] = NULL;
3342 :
3343 : /*
3344 : * Aliases
3345 : */
3346 121092 : while (do_aliases) {
3347 : char **aliases;
3348 : char *a;
3349 :
3350 64296 : p++;
3351 :
3352 : /* Walk to first char */
3353 64296 : for (a = p; *p != '_' && !isalnum((int) *p); p++) {
3354 0 : if (*p == '\0') {
3355 0 : do_aliases = false;
3356 0 : break;
3357 : }
3358 : }
3359 : /* Only trailing spaces are left */
3360 64296 : if (!do_aliases) {
3361 0 : break;
3362 : }
3363 :
3364 612978 : for (a = p; !isspace((int)*p); p++) {
3365 605478 : if (*p == '\0') {
3366 56796 : do_aliases = false;
3367 56796 : break;
3368 : }
3369 : }
3370 :
3371 64296 : *p = '\0';
3372 :
3373 64296 : aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
3374 64296 : if (aliases == NULL) {
3375 0 : free(ed);
3376 0 : return false;
3377 : }
3378 64296 : ed->ht.h_aliases = aliases;
3379 :
3380 64296 : str_tolower(a, a);
3381 64296 : aliases[aliases_count] = a;
3382 64296 : aliases[aliases_count + 1] = NULL;
3383 :
3384 64296 : aliases_count += 1;
3385 : }
3386 :
3387 56796 : ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
3388 56796 : if (!ok) {
3389 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
3390 0 : free(ed);
3391 0 : return false;
3392 : }
3393 :
3394 56796 : ed->aliases_count = aliases_count;
3395 : /* Inventarize item */
3396 56796 : ok = nwrap_add_hname(ed);
3397 56796 : if (!ok) {
3398 0 : return false;
3399 : }
3400 :
3401 56796 : ok = nwrap_ed_inventarize(ip, ed);
3402 56796 : if (!ok) {
3403 0 : return false;
3404 : }
3405 :
3406 56796 : nwrap_he->num++;
3407 56796 : return true;
3408 : }
3409 :
3410 48162 : static void nwrap_he_unload(struct nwrap_cache *nwrap)
3411 : {
3412 48162 : struct nwrap_he *nwrap_he =
3413 : (struct nwrap_he *)nwrap->private_data;
3414 : struct nwrap_entdata *ed;
3415 : struct nwrap_entlist *el;
3416 : size_t i;
3417 : int rc;
3418 :
3419 201912 : nwrap_vector_foreach (ed, nwrap_he->entries, i)
3420 : {
3421 153750 : SAFE_FREE(ed->nwrap_addrdata.items);
3422 153750 : SAFE_FREE(ed->ht.h_aliases);
3423 153750 : SAFE_FREE(ed);
3424 : }
3425 48162 : SAFE_FREE(nwrap_he->entries.items);
3426 48162 : nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
3427 :
3428 365923 : nwrap_vector_foreach(el, nwrap_he->lists, i)
3429 : {
3430 799533 : while (el != NULL) {
3431 : struct nwrap_entlist *el_next;
3432 :
3433 481772 : el_next = el->next;
3434 481772 : SAFE_FREE(el);
3435 481772 : el = el_next;
3436 : }
3437 : }
3438 48162 : SAFE_FREE(nwrap_he->lists.items);
3439 48162 : nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
3440 :
3441 48162 : nwrap_he->num = 0;
3442 48162 : nwrap_he->idx = 0;
3443 :
3444 : /*
3445 : * If we unload the file, the pointers in the hash table point to
3446 : * invalid memory. So we need to destroy the hash table and recreate
3447 : * it.
3448 : */
3449 48162 : hdestroy();
3450 48162 : rc = hcreate(max_hostents);
3451 48162 : if (rc == 0) {
3452 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
3453 0 : exit(-1);
3454 : }
3455 48162 : }
3456 :
3457 :
3458 : /* user functions */
3459 13512 : static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
3460 : const char *name)
3461 : {
3462 : int i;
3463 : bool ok;
3464 :
3465 : (void) b; /* unused */
3466 :
3467 13512 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
3468 :
3469 13512 : ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
3470 13512 : if (!ok) {
3471 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
3472 0 : return NULL;
3473 : }
3474 :
3475 113322 : for (i=0; i<nwrap_pw_global.num; i++) {
3476 102301 : if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
3477 2491 : NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
3478 2491 : return &nwrap_pw_global.list[i];
3479 : }
3480 99810 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3481 : "user[%s] does not match [%s]",
3482 : name,
3483 : nwrap_pw_global.list[i].pw_name);
3484 : }
3485 :
3486 11021 : NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
3487 :
3488 11021 : errno = ENOENT;
3489 11021 : return NULL;
3490 : }
3491 :
3492 342 : static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
3493 : const char *name, struct passwd *pwdst,
3494 : char *buf, size_t buflen, struct passwd **pwdstp)
3495 : {
3496 : struct passwd *pw;
3497 :
3498 342 : pw = nwrap_files_getpwnam(b, name);
3499 342 : if (!pw) {
3500 52 : if (errno == 0) {
3501 0 : return ENOENT;
3502 : }
3503 52 : return errno;
3504 : }
3505 :
3506 290 : return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3507 : }
3508 :
3509 26292 : static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
3510 : uid_t uid)
3511 : {
3512 : int i;
3513 : bool ok;
3514 :
3515 : (void) b; /* unused */
3516 :
3517 26292 : ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
3518 26292 : if (!ok) {
3519 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
3520 0 : return NULL;
3521 : }
3522 :
3523 84739 : for (i=0; i<nwrap_pw_global.num; i++) {
3524 81933 : if (nwrap_pw_global.list[i].pw_uid == uid) {
3525 23486 : NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
3526 23486 : return &nwrap_pw_global.list[i];
3527 : }
3528 58447 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3529 : "uid[%u] does not match [%u]",
3530 : uid,
3531 : nwrap_pw_global.list[i].pw_uid);
3532 : }
3533 :
3534 2806 : NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
3535 :
3536 2806 : errno = ENOENT;
3537 2806 : return NULL;
3538 : }
3539 :
3540 2041 : static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
3541 : uid_t uid, struct passwd *pwdst,
3542 : char *buf, size_t buflen, struct passwd **pwdstp)
3543 : {
3544 : struct passwd *pw;
3545 :
3546 2041 : pw = nwrap_files_getpwuid(b, uid);
3547 2041 : if (!pw) {
3548 52 : if (errno == 0) {
3549 0 : return ENOENT;
3550 : }
3551 52 : return errno;
3552 : }
3553 :
3554 1989 : return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3555 : }
3556 :
3557 : /* user enum functions */
3558 10 : static void nwrap_files_setpwent(struct nwrap_backend *b)
3559 : {
3560 : (void) b; /* unused */
3561 :
3562 10 : nwrap_pw_global.idx = 0;
3563 10 : }
3564 :
3565 320 : static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
3566 : {
3567 : struct passwd *pw;
3568 :
3569 : (void) b; /* unused */
3570 :
3571 320 : if (nwrap_pw_global.idx == 0) {
3572 : bool ok;
3573 10 : ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
3574 10 : if (!ok) {
3575 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
3576 0 : return NULL;
3577 : }
3578 : }
3579 :
3580 320 : if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
3581 140 : errno = ENOENT;
3582 140 : return NULL;
3583 : }
3584 :
3585 180 : pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
3586 :
3587 180 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3588 : "return user[%s] uid[%u]",
3589 : pw->pw_name, pw->pw_uid);
3590 :
3591 180 : return pw;
3592 : }
3593 :
3594 128 : static int nwrap_files_getpwent_r(struct nwrap_backend *b,
3595 : struct passwd *pwdst, char *buf,
3596 : size_t buflen, struct passwd **pwdstp)
3597 : {
3598 : struct passwd *pw;
3599 :
3600 128 : pw = nwrap_files_getpwent(b);
3601 128 : if (!pw) {
3602 56 : if (errno == 0) {
3603 0 : return ENOENT;
3604 : }
3605 56 : return errno;
3606 : }
3607 :
3608 72 : return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3609 : }
3610 :
3611 3811 : static void nwrap_files_endpwent(struct nwrap_backend *b)
3612 : {
3613 : (void) b; /* unused */
3614 :
3615 3811 : nwrap_pw_global.idx = 0;
3616 3811 : }
3617 :
3618 : /* shadow */
3619 :
3620 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
3621 :
3622 : #ifdef HAVE_SETSPENT
3623 : static void nwrap_files_setspent(void)
3624 : {
3625 : nwrap_sp_global.idx = 0;
3626 : }
3627 :
3628 : static struct spwd *nwrap_files_getspent(void)
3629 : {
3630 : struct spwd *sp;
3631 :
3632 : if (nwrap_sp_global.idx == 0) {
3633 : bool ok;
3634 :
3635 : ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
3636 : if (!ok) {
3637 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
3638 : return NULL;
3639 : }
3640 : }
3641 :
3642 : if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
3643 : errno = ENOENT;
3644 : return NULL;
3645 : }
3646 :
3647 : sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
3648 :
3649 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3650 : "return user[%s]",
3651 : sp->sp_namp);
3652 :
3653 : return sp;
3654 : }
3655 :
3656 : static void nwrap_files_endspent(void)
3657 : {
3658 : nwrap_sp_global.idx = 0;
3659 : }
3660 : #endif /* HAVE_SETSPENT */
3661 :
3662 0 : static struct spwd *nwrap_files_getspnam(const char *name)
3663 : {
3664 : int i;
3665 : bool ok;
3666 :
3667 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
3668 :
3669 0 : ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
3670 0 : if (!ok) {
3671 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
3672 0 : return NULL;
3673 : }
3674 :
3675 0 : for (i=0; i<nwrap_sp_global.num; i++) {
3676 0 : if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
3677 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
3678 0 : return &nwrap_sp_global.list[i];
3679 : }
3680 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3681 : "user[%s] does not match [%s]",
3682 : name,
3683 : nwrap_sp_global.list[i].sp_namp);
3684 : }
3685 :
3686 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
3687 :
3688 0 : errno = ENOENT;
3689 0 : return NULL;
3690 : }
3691 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
3692 :
3693 : /* misc functions */
3694 0 : static int nwrap_files_initgroups(struct nwrap_backend *b,
3695 : const char *user,
3696 : gid_t group)
3697 : {
3698 : struct group *grp;
3699 : gid_t *groups;
3700 0 : int size = 1;
3701 : int rc;
3702 :
3703 0 : groups = (gid_t *)malloc(size * sizeof(gid_t));
3704 0 : if (groups == NULL) {
3705 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
3706 0 : errno = ENOMEM;
3707 0 : return -1;
3708 : }
3709 0 : groups[0] = group;
3710 :
3711 0 : nwrap_files_setgrent(b);
3712 0 : while ((grp = nwrap_files_getgrent(b)) != NULL) {
3713 0 : int i = 0;
3714 :
3715 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3716 : "Inspecting %s for group membership",
3717 : grp->gr_name);
3718 :
3719 0 : for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
3720 0 : if (group != grp->gr_gid &&
3721 0 : (strcmp(user, grp->gr_mem[i]) == 0)) {
3722 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3723 : "%s is member of %s",
3724 : user,
3725 : grp->gr_name);
3726 :
3727 0 : groups = (gid_t *)realloc(groups,
3728 0 : (size + 1) * sizeof(gid_t));
3729 0 : if (groups == NULL) {
3730 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
3731 : "Out of memory");
3732 0 : errno = ENOMEM;
3733 0 : return -1;
3734 : }
3735 :
3736 0 : groups[size] = grp->gr_gid;
3737 0 : size++;
3738 : }
3739 : }
3740 : }
3741 :
3742 0 : nwrap_files_endgrent(b);
3743 :
3744 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3745 : "%s is member of %d groups",
3746 : user, size);
3747 :
3748 : /* This really only works if uid_wrapper is loaded */
3749 0 : rc = setgroups(size, groups);
3750 :
3751 0 : free(groups);
3752 :
3753 0 : return rc;
3754 : }
3755 :
3756 : /* group functions */
3757 771 : static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
3758 : const char *name)
3759 : {
3760 : int i;
3761 : bool ok;
3762 :
3763 : (void) b; /* unused */
3764 :
3765 771 : ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3766 771 : if (!ok) {
3767 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3768 0 : return NULL;
3769 : }
3770 :
3771 5474 : for (i=0; i<nwrap_gr_global.num; i++) {
3772 5086 : if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
3773 383 : NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
3774 383 : return &nwrap_gr_global.list[i];
3775 : }
3776 4703 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3777 : "group[%s] does not match [%s]",
3778 : name,
3779 : nwrap_gr_global.list[i].gr_name);
3780 : }
3781 :
3782 388 : NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
3783 :
3784 388 : errno = ENOENT;
3785 388 : return NULL;
3786 : }
3787 :
3788 452 : static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
3789 : const char *name, struct group *grdst,
3790 : char *buf, size_t buflen, struct group **grdstp)
3791 : {
3792 : struct group *gr;
3793 :
3794 452 : gr = nwrap_files_getgrnam(b, name);
3795 452 : if (!gr) {
3796 302 : if (errno == 0) {
3797 0 : return ENOENT;
3798 : }
3799 302 : return errno;
3800 : }
3801 :
3802 150 : return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3803 : }
3804 :
3805 2158 : static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
3806 : gid_t gid)
3807 : {
3808 : int i;
3809 : bool ok;
3810 :
3811 : (void) b; /* unused */
3812 :
3813 2158 : ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3814 2158 : if (!ok) {
3815 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3816 0 : return NULL;
3817 : }
3818 :
3819 7056 : for (i=0; i<nwrap_gr_global.num; i++) {
3820 6820 : if (nwrap_gr_global.list[i].gr_gid == gid) {
3821 1922 : NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
3822 1922 : return &nwrap_gr_global.list[i];
3823 : }
3824 4898 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3825 : "gid[%u] does not match [%u]",
3826 : gid,
3827 : nwrap_gr_global.list[i].gr_gid);
3828 : }
3829 :
3830 236 : NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
3831 :
3832 236 : errno = ENOENT;
3833 236 : return NULL;
3834 : }
3835 :
3836 1905 : static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
3837 : gid_t gid, struct group *grdst,
3838 : char *buf, size_t buflen, struct group **grdstp)
3839 : {
3840 : struct group *gr;
3841 :
3842 1905 : gr = nwrap_files_getgrgid(b, gid);
3843 1905 : if (!gr) {
3844 72 : if (errno == 0) {
3845 0 : return ENOENT;
3846 : }
3847 72 : return errno;
3848 : }
3849 :
3850 1833 : return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3851 : }
3852 :
3853 : /* group enum functions */
3854 2986 : static void nwrap_files_setgrent(struct nwrap_backend *b)
3855 : {
3856 : (void) b; /* unused */
3857 :
3858 2986 : nwrap_gr_global.idx = 0;
3859 2986 : }
3860 :
3861 35038 : static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
3862 : {
3863 : struct group *gr;
3864 :
3865 : (void) b; /* unused */
3866 :
3867 35038 : if (nwrap_gr_global.idx == 0) {
3868 : bool ok;
3869 :
3870 2986 : ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3871 2986 : if (!ok) {
3872 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3873 0 : return NULL;
3874 : }
3875 : }
3876 :
3877 35038 : if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
3878 5542 : errno = ENOENT;
3879 5542 : return NULL;
3880 : }
3881 :
3882 29496 : gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
3883 :
3884 29496 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3885 : "return group[%s] gid[%u]",
3886 : gr->gr_name, gr->gr_gid);
3887 :
3888 29496 : return gr;
3889 : }
3890 :
3891 120 : static int nwrap_files_getgrent_r(struct nwrap_backend *b,
3892 : struct group *grdst, char *buf,
3893 : size_t buflen, struct group **grdstp)
3894 : {
3895 : struct group *gr;
3896 :
3897 120 : gr = nwrap_files_getgrent(b);
3898 120 : if (!gr) {
3899 76 : if (errno == 0) {
3900 0 : return ENOENT;
3901 : }
3902 76 : return errno;
3903 : }
3904 :
3905 44 : return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3906 : }
3907 :
3908 2986 : static void nwrap_files_endgrent(struct nwrap_backend *b)
3909 : {
3910 : (void) b; /* unused */
3911 :
3912 2986 : nwrap_gr_global.idx = 0;
3913 2986 : }
3914 :
3915 : /* hosts functions */
3916 0 : static int nwrap_files_internal_gethostbyname(const char *name, int af,
3917 : struct hostent *result,
3918 : struct nwrap_vector *addr_list)
3919 : {
3920 : struct nwrap_entlist *el;
3921 : struct hostent *he;
3922 : char *h_name_lower;
3923 : ENTRY e;
3924 : ENTRY *e_p;
3925 0 : char canon_name[DNS_NAME_MAX] = { 0 };
3926 : size_t name_len;
3927 0 : bool he_found = false;
3928 : bool ok;
3929 :
3930 : /*
3931 : * We need to make sure we have zeroed return pointer for consumers
3932 : * which don't check return values, e.g. OpenLDAP.
3933 : */
3934 0 : ZERO_STRUCTP(result);
3935 :
3936 0 : ok = nwrap_files_cache_reload(nwrap_he_global.cache);
3937 0 : if (!ok) {
3938 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
3939 0 : goto no_ent;
3940 : }
3941 :
3942 0 : name_len = strlen(name);
3943 0 : if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
3944 0 : memcpy(canon_name, name, name_len - 1);
3945 0 : canon_name[name_len] = '\0';
3946 0 : name = canon_name;
3947 : }
3948 :
3949 0 : if (!str_tolower_copy(&h_name_lower, name)) {
3950 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3951 : "Out of memory while converting to lower case");
3952 0 : goto no_ent;
3953 : }
3954 :
3955 : /* Look at hash table for element */
3956 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
3957 0 : e.key = h_name_lower;
3958 0 : e.data = NULL;
3959 0 : e_p = hsearch(e, FIND);
3960 0 : if (e_p == NULL) {
3961 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
3962 0 : SAFE_FREE(h_name_lower);
3963 0 : goto no_ent;
3964 : }
3965 0 : SAFE_FREE(h_name_lower);
3966 :
3967 : /* Always cleanup vector and results */
3968 0 : if (!nwrap_vector_is_initialized(addr_list)) {
3969 0 : if (!nwrap_vector_init(addr_list)) {
3970 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
3971 : "Unable to initialize memory for addr_list vector");
3972 0 : goto no_ent;
3973 : }
3974 : } else {
3975 : /* When vector is initialized data are valid no more.
3976 : * Quick way how to free vector is: */
3977 0 : addr_list->count = 0;
3978 : }
3979 :
3980 : /* Iterate through results */
3981 0 : for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
3982 : {
3983 0 : he = &(el->ed->ht);
3984 :
3985 : /* Filter by address familiy if provided */
3986 0 : if (af != AF_UNSPEC && he->h_addrtype != af) {
3987 0 : continue;
3988 : }
3989 :
3990 : /*
3991 : * GLIBC HACK?
3992 : * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
3993 : */
3994 0 : if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
3995 0 : continue;
3996 : }
3997 :
3998 0 : if (!he_found) {
3999 0 : memcpy(result, he, sizeof(struct hostent));
4000 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
4001 : "Name found. Returning record for %s",
4002 : he->h_name);
4003 0 : he_found = true;
4004 : }
4005 0 : nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
4006 0 : result->h_addr_list = nwrap_vector_head(addr_list);
4007 : }
4008 :
4009 0 : if (he_found) {
4010 0 : return 0;
4011 : }
4012 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
4013 : "Name found in database. No records matches type.");
4014 :
4015 0 : no_ent:
4016 0 : errno = ENOENT;
4017 0 : return -1;
4018 : }
4019 :
4020 0 : static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
4021 : const char *name, int af,
4022 : struct hostent *hedst,
4023 : char *buf, size_t buflen,
4024 : struct hostent **hedstp)
4025 : {
4026 0 : struct nwrap_vector *addr_list = NULL;
4027 : union {
4028 : char *ptr;
4029 : char **list;
4030 : } g;
4031 : int rc;
4032 :
4033 : (void) b; /* unused */
4034 : (void) af; /* unused */
4035 :
4036 0 : if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) {
4037 0 : errno = EINVAL;
4038 0 : return -1;
4039 : }
4040 0 : *hedstp = NULL;
4041 0 : buf[0] = '\0';
4042 :
4043 0 : addr_list = calloc(1, sizeof(struct nwrap_vector));
4044 0 : if (addr_list == NULL) {
4045 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
4046 : "Unable to allocate memory for address list");
4047 0 : errno = ENOENT;
4048 0 : return -1;
4049 : }
4050 :
4051 0 : rc = nwrap_files_internal_gethostbyname(name, af, hedst,
4052 : addr_list);
4053 0 : if (rc == -1) {
4054 0 : SAFE_FREE(addr_list->items);
4055 0 : SAFE_FREE(addr_list);
4056 0 : errno = ENOENT;
4057 0 : return -1;
4058 : }
4059 :
4060 : /* +1 i for ending NULL pointer */
4061 0 : if (buflen < ((addr_list->count + 1) * sizeof(void *))) {
4062 0 : SAFE_FREE(addr_list->items);
4063 0 : SAFE_FREE(addr_list);
4064 0 : return ERANGE;
4065 : }
4066 :
4067 : /* Copy all to user provided buffer and change
4068 : * pointers in returned structure.
4069 : * +1 is for ending NULL pointer. */
4070 0 : memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
4071 :
4072 0 : SAFE_FREE(addr_list->items);
4073 0 : SAFE_FREE(addr_list);
4074 :
4075 0 : g.ptr = buf;
4076 0 : hedst->h_addr_list = g.list;
4077 0 : *hedstp = hedst;
4078 0 : return 0;
4079 : }
4080 :
4081 : #ifdef HAVE_GETHOSTBYNAME_R
4082 0 : static int nwrap_gethostbyname_r(const char *name,
4083 : struct hostent *ret,
4084 : char *buf, size_t buflen,
4085 : struct hostent **result, int *h_errnop)
4086 : {
4087 : int rc;
4088 : size_t i;
4089 :
4090 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
4091 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
4092 0 : rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret,
4093 : buf, buflen, result);
4094 0 : if (rc == 0) {
4095 0 : return 0;
4096 0 : } else if (rc == ERANGE) {
4097 0 : return ERANGE;
4098 : }
4099 : }
4100 0 : *h_errnop = h_errno;
4101 0 : return ENOENT;
4102 : }
4103 :
4104 : int gethostbyname_r(const char *name,
4105 : struct hostent *ret,
4106 : char *buf, size_t buflen,
4107 : struct hostent **result, int *h_errnop)
4108 : {
4109 0 : if (!nss_wrapper_hosts_enabled()) {
4110 0 : return libc_gethostbyname_r(name,
4111 : ret,
4112 : buf,
4113 : buflen,
4114 : result,
4115 : h_errnop);
4116 : }
4117 :
4118 0 : return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
4119 : }
4120 : #endif
4121 :
4122 : #ifdef HAVE_GETHOSTBYNAME2_R
4123 0 : static int nwrap_gethostbyname2_r(const char *name, int af,
4124 : struct hostent *ret,
4125 : char *buf, size_t buflen,
4126 : struct hostent **result, int *h_errnop)
4127 : {
4128 : int rc;
4129 : size_t i;
4130 :
4131 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
4132 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
4133 0 : rc = b->ops->nw_gethostbyname2_r(b, name, af, ret,
4134 : buf, buflen, result);
4135 0 : if (rc == 0) {
4136 0 : return 0;
4137 0 : } else if (rc == ERANGE) {
4138 0 : return ERANGE;
4139 : }
4140 : }
4141 0 : *h_errnop = h_errno;
4142 0 : return ENOENT;
4143 : }
4144 :
4145 : int gethostbyname2_r(const char *name, int af,
4146 : struct hostent *ret,
4147 : char *buf, size_t buflen,
4148 : struct hostent **result, int *h_errnop)
4149 : {
4150 0 : if (!nss_wrapper_hosts_enabled()) {
4151 0 : return libc_gethostbyname2_r(name, af, ret, buf, buflen,
4152 : result, h_errnop);
4153 : }
4154 :
4155 0 : return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result,
4156 : h_errnop);
4157 : }
4158 : #endif
4159 :
4160 656722 : static int nwrap_files_getaddrinfo(const char *name,
4161 : unsigned short port,
4162 : const struct addrinfo *hints,
4163 : struct addrinfo **ai)
4164 : {
4165 : struct nwrap_entlist *el;
4166 : struct hostent *he;
4167 656722 : struct addrinfo *ai_head = NULL;
4168 656722 : struct addrinfo *ai_cur = NULL;
4169 : char *h_name_lower;
4170 : size_t name_len;
4171 656722 : char canon_name[DNS_NAME_MAX] = { 0 };
4172 656722 : bool skip_canonname = false;
4173 656722 : ENTRY e = {
4174 : .key = NULL,
4175 : };
4176 656722 : ENTRY *e_p = NULL;
4177 : int rc;
4178 : bool ok;
4179 :
4180 656722 : ok = nwrap_files_cache_reload(nwrap_he_global.cache);
4181 656722 : if (!ok) {
4182 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
4183 0 : return EAI_SYSTEM;
4184 : }
4185 :
4186 656722 : name_len = strlen(name);
4187 656722 : if (name_len == 0) {
4188 0 : return EAI_NONAME;
4189 : }
4190 :
4191 656722 : if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
4192 38 : memcpy(canon_name, name, name_len - 1);
4193 38 : canon_name[name_len] = '\0';
4194 38 : name = canon_name;
4195 : }
4196 :
4197 656722 : if (!str_tolower_copy(&h_name_lower, name)) {
4198 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
4199 : "Out of memory while converting to lower case");
4200 0 : return EAI_MEMORY;
4201 : }
4202 :
4203 656722 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
4204 656722 : e.key = h_name_lower;
4205 656722 : e.data = NULL;
4206 656722 : e_p = hsearch(e, FIND);
4207 656722 : if (e_p == NULL) {
4208 472185 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
4209 472185 : SAFE_FREE(h_name_lower);
4210 472185 : errno = ENOENT;
4211 472185 : return EAI_NONAME;
4212 : }
4213 184537 : NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
4214 184537 : SAFE_FREE(h_name_lower);
4215 :
4216 184537 : rc = EAI_NONAME;
4217 377962 : for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
4218 : {
4219 : int rc2;
4220 193425 : struct addrinfo *ai_new = NULL;
4221 :
4222 193425 : he = &(el->ed->ht);
4223 :
4224 193425 : if (hints->ai_family != AF_UNSPEC &&
4225 682 : he->h_addrtype != hints->ai_family)
4226 : {
4227 0 : NWRAP_LOG(NWRAP_LOG_DEBUG,
4228 : "Entry found but with wrong AF - "
4229 : "remembering EAI_ADDRINFO.");
4230 0 : rc = EAI_ADDRFAMILY;
4231 0 : continue;
4232 : }
4233 :
4234 : /* Function allocates memory and returns it in ai. */
4235 193425 : rc2 = nwrap_convert_he_ai(he,
4236 : port,
4237 : hints,
4238 : &ai_new,
4239 : skip_canonname);
4240 193425 : if (rc2 != 0) {
4241 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
4242 0 : if (ai_head != NULL) {
4243 0 : freeaddrinfo(ai_head);
4244 : }
4245 0 : return rc2;
4246 : }
4247 193425 : skip_canonname = true;
4248 :
4249 193425 : if (ai_head == NULL) {
4250 184537 : ai_head = ai_new;
4251 : }
4252 193425 : if (ai_cur != NULL) {
4253 8888 : ai_cur->ai_next = ai_new;
4254 : }
4255 193425 : ai_cur = ai_new;
4256 : }
4257 :
4258 184537 : if (ai_head != NULL) {
4259 184537 : rc = 0;
4260 : }
4261 :
4262 184537 : *ai = ai_head;
4263 :
4264 184537 : return rc;
4265 : }
4266 :
4267 97 : static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
4268 : const void *addr,
4269 : socklen_t len, int type)
4270 : {
4271 : struct hostent *he;
4272 97 : char ip[NWRAP_INET_ADDRSTRLEN] = {0};
4273 : struct nwrap_entdata *ed;
4274 : const char *a;
4275 : size_t i;
4276 : bool ok;
4277 :
4278 : (void) b; /* unused */
4279 : (void) len; /* unused */
4280 :
4281 97 : ok = nwrap_files_cache_reload(nwrap_he_global.cache);
4282 97 : if (!ok) {
4283 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
4284 0 : return NULL;
4285 : }
4286 :
4287 97 : a = inet_ntop(type, addr, ip, sizeof(ip));
4288 97 : if (a == NULL) {
4289 0 : errno = EINVAL;
4290 0 : return NULL;
4291 : }
4292 :
4293 391 : nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
4294 : {
4295 391 : he = &(ed->ht);
4296 391 : if (he->h_addrtype != type) {
4297 147 : continue;
4298 : }
4299 :
4300 244 : if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
4301 97 : return he;
4302 : }
4303 : }
4304 :
4305 0 : errno = ENOENT;
4306 0 : return NULL;
4307 : }
4308 :
4309 : #ifdef HAVE_GETHOSTBYADDR_R
4310 0 : static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
4311 : struct hostent *ret,
4312 : char *buf, size_t buflen,
4313 : struct hostent **result, int *h_errnop)
4314 : {
4315 : size_t i;
4316 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
4317 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
4318 0 : *result = b->ops->nw_gethostbyaddr(b, addr, len, type);
4319 0 : if (*result != NULL) {
4320 0 : break;
4321 : }
4322 : }
4323 :
4324 0 : if (*result != NULL) {
4325 0 : memset(buf, '\0', buflen);
4326 0 : *ret = **result;
4327 0 : return 0;
4328 : }
4329 :
4330 0 : *h_errnop = h_errno;
4331 0 : return -1;
4332 : }
4333 :
4334 : int gethostbyaddr_r(const void *addr, socklen_t len, int type,
4335 : struct hostent *ret,
4336 : char *buf, size_t buflen,
4337 : struct hostent **result, int *h_errnop)
4338 : {
4339 0 : if (!nss_wrapper_hosts_enabled()) {
4340 0 : return libc_gethostbyaddr_r(addr,
4341 : len,
4342 : type,
4343 : ret,
4344 : buf,
4345 : buflen,
4346 : result,
4347 : h_errnop);
4348 : }
4349 :
4350 0 : return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
4351 : }
4352 : #endif
4353 :
4354 : /* hosts enum functions */
4355 0 : static void nwrap_files_sethostent(void)
4356 : {
4357 0 : nwrap_he_global.idx = 0;
4358 0 : }
4359 :
4360 0 : static struct hostent *nwrap_files_gethostent(void)
4361 : {
4362 : struct hostent *he;
4363 :
4364 0 : if (nwrap_he_global.idx == 0) {
4365 : bool ok;
4366 :
4367 0 : ok = nwrap_files_cache_reload(nwrap_he_global.cache);
4368 0 : if (!ok) {
4369 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
4370 0 : return NULL;
4371 : }
4372 : }
4373 :
4374 0 : if (nwrap_he_global.idx >= nwrap_he_global.num) {
4375 0 : errno = ENOENT;
4376 0 : return NULL;
4377 : }
4378 :
4379 0 : he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
4380 :
4381 0 : NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
4382 :
4383 0 : return he;
4384 : }
4385 :
4386 0 : static void nwrap_files_endhostent(void)
4387 : {
4388 0 : nwrap_he_global.idx = 0;
4389 0 : }
4390 :
4391 : /*
4392 : * module backend
4393 : */
4394 :
4395 :
4396 5985 : static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
4397 : const char *name)
4398 : {
4399 : static struct passwd pwd;
4400 : static char buf[1000];
4401 : NSS_STATUS status;
4402 :
4403 5985 : if (b->symbols->_nss_getpwnam_r.f == NULL) {
4404 0 : return NULL;
4405 : }
4406 :
4407 5985 : status = b->symbols->_nss_getpwnam_r.f(name,
4408 : &pwd,
4409 : buf,
4410 : sizeof(buf),
4411 : &errno);
4412 5985 : if (status == NSS_STATUS_NOTFOUND) {
4413 913 : return NULL;
4414 : }
4415 5072 : if (status != NSS_STATUS_SUCCESS) {
4416 4 : return NULL;
4417 : }
4418 :
4419 5068 : return &pwd;
4420 : }
4421 :
4422 52 : static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
4423 : const char *name, struct passwd *pwdst,
4424 : char *buf, size_t buflen, struct passwd **pwdstp)
4425 : {
4426 : int ret;
4427 :
4428 52 : *pwdstp = NULL;
4429 :
4430 52 : if (b->symbols->_nss_getpwnam_r.f == NULL) {
4431 0 : return NSS_STATUS_NOTFOUND;
4432 : }
4433 :
4434 52 : ret = b->symbols->_nss_getpwnam_r.f(name, pwdst, buf, buflen, &errno);
4435 52 : switch (ret) {
4436 52 : case NSS_STATUS_SUCCESS:
4437 52 : *pwdstp = pwdst;
4438 52 : return 0;
4439 0 : case NSS_STATUS_NOTFOUND:
4440 0 : if (errno != 0) {
4441 0 : return errno;
4442 : }
4443 0 : return ENOENT;
4444 0 : case NSS_STATUS_TRYAGAIN:
4445 0 : if (errno != 0) {
4446 0 : return errno;
4447 : }
4448 0 : return ERANGE;
4449 0 : default:
4450 0 : if (errno != 0) {
4451 0 : return errno;
4452 : }
4453 0 : return ret;
4454 : }
4455 : }
4456 :
4457 2552 : static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
4458 : uid_t uid)
4459 : {
4460 : static struct passwd pwd;
4461 : static char buf[1000];
4462 : NSS_STATUS status;
4463 :
4464 2552 : if (b->symbols->_nss_getpwuid_r.f == NULL) {
4465 0 : return NULL;
4466 : }
4467 :
4468 2552 : status = b->symbols->_nss_getpwuid_r.f(uid,
4469 : &pwd,
4470 : buf,
4471 : sizeof(buf),
4472 : &errno);
4473 2552 : if (status == NSS_STATUS_NOTFOUND) {
4474 1694 : return NULL;
4475 : }
4476 858 : if (status != NSS_STATUS_SUCCESS) {
4477 13 : return NULL;
4478 : }
4479 845 : return &pwd;
4480 : }
4481 :
4482 52 : static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
4483 : uid_t uid, struct passwd *pwdst,
4484 : char *buf, size_t buflen, struct passwd **pwdstp)
4485 : {
4486 : int ret;
4487 :
4488 52 : *pwdstp = NULL;
4489 :
4490 52 : if (b->symbols->_nss_getpwuid_r.f == NULL) {
4491 0 : return ENOENT;
4492 : }
4493 :
4494 52 : ret = b->symbols->_nss_getpwuid_r.f(uid, pwdst, buf, buflen, &errno);
4495 52 : switch (ret) {
4496 52 : case NSS_STATUS_SUCCESS:
4497 52 : *pwdstp = pwdst;
4498 52 : return 0;
4499 0 : case NSS_STATUS_NOTFOUND:
4500 0 : if (errno != 0) {
4501 0 : return errno;
4502 : }
4503 0 : return ENOENT;
4504 0 : case NSS_STATUS_TRYAGAIN:
4505 0 : if (errno != 0) {
4506 0 : return errno;
4507 : }
4508 0 : return ERANGE;
4509 0 : default:
4510 0 : if (errno != 0) {
4511 0 : return errno;
4512 : }
4513 0 : return ret;
4514 : }
4515 : }
4516 :
4517 10 : static void nwrap_module_setpwent(struct nwrap_backend *b)
4518 : {
4519 10 : if (b->symbols->_nss_setpwent.f == NULL) {
4520 0 : return;
4521 : }
4522 :
4523 10 : b->symbols->_nss_setpwent.f();
4524 : }
4525 :
4526 84 : static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
4527 : {
4528 : static struct passwd pwd;
4529 : static char buf[1000];
4530 : NSS_STATUS status;
4531 :
4532 84 : if (b->symbols->_nss_getpwent_r.f == NULL) {
4533 0 : return NULL;
4534 : }
4535 :
4536 84 : status = b->symbols->_nss_getpwent_r.f(&pwd, buf, sizeof(buf), &errno);
4537 84 : if (status == NSS_STATUS_NOTFOUND) {
4538 6 : return NULL;
4539 : }
4540 78 : if (status != NSS_STATUS_SUCCESS) {
4541 0 : return NULL;
4542 : }
4543 78 : return &pwd;
4544 : }
4545 :
4546 56 : static int nwrap_module_getpwent_r(struct nwrap_backend *b,
4547 : struct passwd *pwdst, char *buf,
4548 : size_t buflen, struct passwd **pwdstp)
4549 : {
4550 : int ret;
4551 :
4552 56 : *pwdstp = NULL;
4553 :
4554 56 : if (b->symbols->_nss_getpwent_r.f == NULL) {
4555 0 : return ENOENT;
4556 : }
4557 :
4558 56 : ret = b->symbols->_nss_getpwent_r.f(pwdst, buf, buflen, &errno);
4559 56 : switch (ret) {
4560 52 : case NSS_STATUS_SUCCESS:
4561 52 : *pwdstp = pwdst;
4562 52 : return 0;
4563 4 : case NSS_STATUS_NOTFOUND:
4564 4 : if (errno != 0) {
4565 4 : return errno;
4566 : }
4567 0 : return ENOENT;
4568 0 : case NSS_STATUS_TRYAGAIN:
4569 0 : if (errno != 0) {
4570 0 : return errno;
4571 : }
4572 0 : return ERANGE;
4573 0 : default:
4574 0 : if (errno != 0) {
4575 0 : return errno;
4576 : }
4577 0 : return ret;
4578 : }
4579 : }
4580 :
4581 3805 : static void nwrap_module_endpwent(struct nwrap_backend *b)
4582 : {
4583 3805 : if (b->symbols->_nss_endpwent.f == NULL) {
4584 0 : return;
4585 : }
4586 :
4587 3805 : b->symbols->_nss_endpwent.f();
4588 : }
4589 :
4590 0 : static int nwrap_module_initgroups(struct nwrap_backend *b,
4591 : const char *user, gid_t group)
4592 : {
4593 : gid_t *groups;
4594 : long int start;
4595 : long int size;
4596 :
4597 0 : if (b->symbols->_nss_initgroups.f == NULL) {
4598 0 : return NSS_STATUS_UNAVAIL;
4599 : }
4600 :
4601 0 : return b->symbols->_nss_initgroups.f(user,
4602 : group,
4603 : &start,
4604 : &size,
4605 : &groups,
4606 : 0,
4607 : &errno);
4608 : }
4609 :
4610 86 : static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
4611 : const char *name)
4612 : {
4613 : static struct group grp;
4614 : static char *buf;
4615 : static int buflen = 1000;
4616 : NSS_STATUS status;
4617 :
4618 86 : if (b->symbols->_nss_getgrnam_r.f == NULL) {
4619 0 : return NULL;
4620 : }
4621 :
4622 86 : if (!buf) {
4623 16 : buf = (char *)malloc(buflen);
4624 : }
4625 86 : again:
4626 86 : status = b->symbols->_nss_getgrnam_r.f(name, &grp, buf, buflen, &errno);
4627 86 : if (status == NSS_STATUS_TRYAGAIN) {
4628 0 : buflen *= 2;
4629 0 : buf = (char *)realloc(buf, buflen);
4630 0 : if (!buf) {
4631 0 : return NULL;
4632 : }
4633 0 : goto again;
4634 : }
4635 86 : if (status == NSS_STATUS_NOTFOUND) {
4636 6 : SAFE_FREE(buf);
4637 6 : return NULL;
4638 : }
4639 80 : if (status != NSS_STATUS_SUCCESS) {
4640 0 : SAFE_FREE(buf);
4641 0 : return NULL;
4642 : }
4643 80 : return &grp;
4644 : }
4645 :
4646 214 : static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
4647 : const char *name, struct group *grdst,
4648 : char *buf, size_t buflen, struct group **grdstp)
4649 : {
4650 : int ret;
4651 :
4652 214 : *grdstp = NULL;
4653 :
4654 214 : if (b->symbols->_nss_getgrnam_r.f == NULL) {
4655 0 : return ENOENT;
4656 : }
4657 :
4658 214 : ret = b->symbols->_nss_getgrnam_r.f(name, grdst, buf, buflen, &errno);
4659 214 : switch (ret) {
4660 72 : case NSS_STATUS_SUCCESS:
4661 72 : *grdstp = grdst;
4662 72 : return 0;
4663 142 : case NSS_STATUS_NOTFOUND:
4664 142 : if (errno != 0) {
4665 142 : return errno;
4666 : }
4667 0 : return ENOENT;
4668 0 : case NSS_STATUS_TRYAGAIN:
4669 0 : if (errno != 0) {
4670 0 : return errno;
4671 : }
4672 0 : return ERANGE;
4673 0 : default:
4674 0 : if (errno != 0) {
4675 0 : return errno;
4676 : }
4677 0 : return ret;
4678 : }
4679 : }
4680 :
4681 164 : static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
4682 : gid_t gid)
4683 : {
4684 : static struct group grp;
4685 : static char *buf;
4686 : static int buflen = 1000;
4687 : NSS_STATUS status;
4688 :
4689 164 : if (b->symbols->_nss_getgrgid_r.f == NULL) {
4690 0 : return NULL;
4691 : }
4692 :
4693 164 : if (!buf) {
4694 32 : buf = (char *)malloc(buflen);
4695 : }
4696 :
4697 164 : again:
4698 164 : status = b->symbols->_nss_getgrgid_r.f(gid, &grp, buf, buflen, &errno);
4699 164 : if (status == NSS_STATUS_TRYAGAIN) {
4700 0 : buflen *= 2;
4701 0 : buf = (char *)realloc(buf, buflen);
4702 0 : if (!buf) {
4703 0 : return NULL;
4704 : }
4705 0 : goto again;
4706 : }
4707 164 : if (status == NSS_STATUS_NOTFOUND) {
4708 4 : SAFE_FREE(buf);
4709 4 : return NULL;
4710 : }
4711 160 : if (status != NSS_STATUS_SUCCESS) {
4712 0 : SAFE_FREE(buf);
4713 0 : return NULL;
4714 : }
4715 160 : return &grp;
4716 : }
4717 :
4718 72 : static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
4719 : gid_t gid, struct group *grdst,
4720 : char *buf, size_t buflen, struct group **grdstp)
4721 : {
4722 : int ret;
4723 :
4724 72 : *grdstp = NULL;
4725 :
4726 72 : if (b->symbols->_nss_getgrgid_r.f == NULL) {
4727 0 : return ENOENT;
4728 : }
4729 :
4730 72 : ret = b->symbols->_nss_getgrgid_r.f(gid, grdst, buf, buflen, &errno);
4731 72 : switch (ret) {
4732 72 : case NSS_STATUS_SUCCESS:
4733 72 : *grdstp = grdst;
4734 72 : return 0;
4735 0 : case NSS_STATUS_NOTFOUND:
4736 0 : if (errno != 0) {
4737 0 : return errno;
4738 : }
4739 0 : return ENOENT;
4740 0 : case NSS_STATUS_TRYAGAIN:
4741 0 : if (errno != 0) {
4742 0 : return errno;
4743 : }
4744 0 : return ERANGE;
4745 0 : default:
4746 0 : if (errno != 0) {
4747 0 : return errno;
4748 : }
4749 0 : return ret;
4750 : }
4751 : }
4752 :
4753 2904 : static void nwrap_module_setgrent(struct nwrap_backend *b)
4754 : {
4755 2904 : if (b->symbols->_nss_setgrent.f == NULL) {
4756 0 : return;
4757 : }
4758 :
4759 2904 : b->symbols->_nss_setgrent.f();
4760 : }
4761 :
4762 5384 : static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
4763 : {
4764 : static struct group grp;
4765 : static char *buf;
4766 : static int buflen = 1024;
4767 : NSS_STATUS status;
4768 :
4769 5384 : if (b->symbols->_nss_getgrent_r.f == NULL) {
4770 0 : return NULL;
4771 : }
4772 :
4773 5384 : if (!buf) {
4774 2900 : buf = (char *)malloc(buflen);
4775 : }
4776 :
4777 5384 : again:
4778 5384 : status = b->symbols->_nss_getgrent_r.f(&grp, buf, buflen, &errno);
4779 5384 : if (status == NSS_STATUS_TRYAGAIN) {
4780 0 : buflen *= 2;
4781 0 : buf = (char *)realloc(buf, buflen);
4782 0 : if (!buf) {
4783 0 : return NULL;
4784 : }
4785 0 : goto again;
4786 : }
4787 5384 : if (status == NSS_STATUS_NOTFOUND) {
4788 2900 : SAFE_FREE(buf);
4789 2900 : return NULL;
4790 : }
4791 2484 : if (status != NSS_STATUS_SUCCESS) {
4792 0 : SAFE_FREE(buf);
4793 0 : return NULL;
4794 : }
4795 2484 : return &grp;
4796 : }
4797 :
4798 76 : static int nwrap_module_getgrent_r(struct nwrap_backend *b,
4799 : struct group *grdst, char *buf,
4800 : size_t buflen, struct group **grdstp)
4801 : {
4802 : int ret;
4803 :
4804 76 : *grdstp = NULL;
4805 :
4806 76 : if (b->symbols->_nss_getgrent_r.f == NULL) {
4807 0 : return ENOENT;
4808 : }
4809 :
4810 76 : ret = b->symbols->_nss_getgrent_r.f(grdst, buf, buflen, &errno);
4811 76 : switch (ret) {
4812 72 : case NSS_STATUS_SUCCESS:
4813 72 : *grdstp = grdst;
4814 72 : return 0;
4815 4 : case NSS_STATUS_NOTFOUND:
4816 4 : if (errno != 0) {
4817 4 : return errno;
4818 : }
4819 0 : return ENOENT;
4820 0 : case NSS_STATUS_TRYAGAIN:
4821 0 : if (errno != 0) {
4822 0 : return errno;
4823 : }
4824 0 : return ERANGE;
4825 0 : default:
4826 0 : if (errno != 0) {
4827 0 : return errno;
4828 : }
4829 0 : return ret;
4830 : }
4831 : }
4832 :
4833 2904 : static void nwrap_module_endgrent(struct nwrap_backend *b)
4834 : {
4835 2904 : if (b->symbols->_nss_endgrent.f == NULL) {
4836 0 : return;
4837 : }
4838 :
4839 2904 : b->symbols->_nss_endgrent.f();
4840 : }
4841 :
4842 0 : static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
4843 : const void *addr,
4844 : socklen_t len, int type)
4845 : {
4846 : static struct hostent he;
4847 : static char *buf = NULL;
4848 : static size_t buflen = 1000;
4849 : NSS_STATUS status;
4850 :
4851 0 : if (b->symbols->_nss_gethostbyaddr_r.f == NULL) {
4852 0 : return NULL;
4853 : }
4854 :
4855 0 : if (buf == NULL) {
4856 0 : buf = (char *)malloc(buflen);
4857 0 : if (buf == NULL) {
4858 0 : return NULL;
4859 : }
4860 : }
4861 0 : again:
4862 0 : status = b->symbols->_nss_gethostbyaddr_r.f(addr,
4863 : len,
4864 : type,
4865 : &he,
4866 : buf,
4867 : buflen,
4868 : &errno,
4869 : &h_errno);
4870 0 : if (status == NSS_STATUS_TRYAGAIN) {
4871 0 : char *p = NULL;
4872 :
4873 0 : buflen *= 2;
4874 0 : p = (char *)realloc(buf, buflen);
4875 0 : if (p == NULL) {
4876 0 : SAFE_FREE(buf);
4877 0 : return NULL;
4878 : }
4879 0 : buf = p;
4880 0 : goto again;
4881 : }
4882 0 : if (status == NSS_STATUS_NOTFOUND) {
4883 0 : SAFE_FREE(buf);
4884 0 : return NULL;
4885 : }
4886 0 : if (status != NSS_STATUS_SUCCESS) {
4887 0 : SAFE_FREE(buf);
4888 0 : return NULL;
4889 : }
4890 :
4891 0 : return &he;
4892 : }
4893 :
4894 0 : static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
4895 : const char *name, int af,
4896 : struct hostent *hedst,
4897 : char *buf, size_t buflen,
4898 : struct hostent **hedstp)
4899 : {
4900 : NSS_STATUS status;
4901 :
4902 0 : *hedstp = NULL;
4903 :
4904 0 : if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
4905 0 : return ENOENT;
4906 : }
4907 :
4908 0 : status = b->symbols->_nss_gethostbyname2_r.f(name,
4909 : af,
4910 : hedst,
4911 : buf,
4912 : buflen,
4913 : &errno,
4914 : &h_errno);
4915 0 : switch (status) {
4916 0 : case NSS_STATUS_SUCCESS:
4917 0 : *hedstp = hedst;
4918 0 : return 0;
4919 0 : case NSS_STATUS_NOTFOUND:
4920 0 : if (errno != 0) {
4921 0 : return errno;
4922 : }
4923 0 : return ENOENT;
4924 0 : case NSS_STATUS_TRYAGAIN:
4925 0 : if (errno != 0) {
4926 0 : return errno;
4927 : }
4928 0 : return ERANGE;
4929 0 : default:
4930 0 : if (errno != 0) {
4931 0 : return errno;
4932 : }
4933 0 : return status;
4934 : }
4935 : }
4936 :
4937 0 : static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
4938 : const char *name)
4939 : {
4940 : static struct hostent he;
4941 : static char *buf = NULL;
4942 : static size_t buflen = 1000;
4943 : NSS_STATUS status;
4944 :
4945 0 : if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
4946 0 : return NULL;
4947 : }
4948 :
4949 0 : if (buf == NULL) {
4950 0 : buf = (char *)malloc(buflen);
4951 0 : if (buf == NULL) {
4952 0 : return NULL;
4953 : }
4954 : }
4955 :
4956 0 : again:
4957 0 : status = b->symbols->_nss_gethostbyname2_r.f(name,
4958 : AF_UNSPEC,
4959 : &he,
4960 : buf,
4961 : buflen,
4962 : &errno,
4963 : &h_errno);
4964 0 : if (status == NSS_STATUS_TRYAGAIN) {
4965 0 : char *p = NULL;
4966 :
4967 0 : buflen *= 2;
4968 0 : p = (char *)realloc(buf, buflen);
4969 0 : if (p == NULL) {
4970 0 : SAFE_FREE(buf);
4971 0 : return NULL;
4972 : }
4973 0 : buf = p;
4974 0 : goto again;
4975 : }
4976 0 : if (status == NSS_STATUS_NOTFOUND) {
4977 0 : SAFE_FREE(buf);
4978 0 : return NULL;
4979 : }
4980 0 : if (status != NSS_STATUS_SUCCESS) {
4981 0 : SAFE_FREE(buf);
4982 0 : return NULL;
4983 : }
4984 :
4985 0 : return &he;
4986 : }
4987 :
4988 0 : static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
4989 : const char *name, int af)
4990 : {
4991 : static struct hostent he;
4992 : static char *buf = NULL;
4993 : static size_t buflen = 1000;
4994 : NSS_STATUS status;
4995 :
4996 0 : if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
4997 0 : return NULL;
4998 : }
4999 :
5000 0 : if (buf == NULL) {
5001 0 : buf = (char *)malloc(buflen);
5002 0 : if (buf == NULL) {
5003 0 : return NULL;
5004 : }
5005 : }
5006 :
5007 0 : again:
5008 0 : status = b->symbols->_nss_gethostbyname2_r.f(name,
5009 : af,
5010 : &he,
5011 : buf,
5012 : buflen,
5013 : &errno,
5014 : &h_errno);
5015 0 : if (status == NSS_STATUS_TRYAGAIN) {
5016 0 : char *p = NULL;
5017 :
5018 0 : buflen *= 2;
5019 0 : p = (char *)realloc(buf, buflen);
5020 0 : if (p == NULL) {
5021 0 : SAFE_FREE(buf);
5022 0 : return NULL;
5023 : }
5024 0 : buf = p;
5025 0 : goto again;
5026 : }
5027 0 : if (status == NSS_STATUS_NOTFOUND) {
5028 0 : SAFE_FREE(buf);
5029 0 : return NULL;
5030 : }
5031 0 : if (status != NSS_STATUS_SUCCESS) {
5032 0 : SAFE_FREE(buf);
5033 0 : return NULL;
5034 : }
5035 :
5036 0 : return &he;
5037 : }
5038 :
5039 : /****************************************************************************
5040 : * GETPWNAM
5041 : ***************************************************************************/
5042 :
5043 13170 : static struct passwd *nwrap_getpwnam(const char *name)
5044 : {
5045 : size_t i;
5046 : struct passwd *pwd;
5047 :
5048 25056 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5049 19155 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5050 19155 : pwd = b->ops->nw_getpwnam(b, name);
5051 19155 : if (pwd) {
5052 7269 : return pwd;
5053 : }
5054 : }
5055 :
5056 5901 : return NULL;
5057 : }
5058 :
5059 : struct passwd *getpwnam(const char *name)
5060 : {
5061 13618 : if (!nss_wrapper_enabled()) {
5062 448 : return libc_getpwnam(name);
5063 : }
5064 :
5065 13170 : return nwrap_getpwnam(name);
5066 : }
5067 :
5068 : /****************************************************************************
5069 : * GETPWNAM_R
5070 : ***************************************************************************/
5071 :
5072 342 : static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
5073 : char *buf, size_t buflen, struct passwd **pwdstp)
5074 : {
5075 : size_t i;
5076 : int ret;
5077 :
5078 394 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5079 394 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5080 394 : ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
5081 394 : if (ret == ENOENT) {
5082 52 : continue;
5083 : }
5084 342 : return ret;
5085 : }
5086 :
5087 0 : return ENOENT;
5088 : }
5089 :
5090 : #ifdef HAVE_GETPWNAM_R
5091 : # ifdef HAVE_SOLARIS_GETPWNAM_R
5092 : int getpwnam_r(const char *name, struct passwd *pwdst,
5093 : char *buf, int buflen, struct passwd **pwdstp)
5094 : # else /* HAVE_SOLARIS_GETPWNAM_R */
5095 : int getpwnam_r(const char *name, struct passwd *pwdst,
5096 : char *buf, size_t buflen, struct passwd **pwdstp)
5097 : # endif /* HAVE_SOLARIS_GETPWNAM_R */
5098 : {
5099 428 : if (!nss_wrapper_enabled()) {
5100 86 : return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
5101 : }
5102 :
5103 342 : return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
5104 : }
5105 : #endif
5106 :
5107 : /****************************************************************************
5108 : * GETPWUID
5109 : ***************************************************************************/
5110 :
5111 24251 : static struct passwd *nwrap_getpwuid(uid_t uid)
5112 : {
5113 : size_t i;
5114 : struct passwd *pwd;
5115 :
5116 28712 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5117 26803 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5118 26803 : pwd = b->ops->nw_getpwuid(b, uid);
5119 26803 : if (pwd) {
5120 22342 : return pwd;
5121 : }
5122 : }
5123 :
5124 1909 : return NULL;
5125 : }
5126 :
5127 : struct passwd *getpwuid(uid_t uid)
5128 : {
5129 26690 : if (!nss_wrapper_enabled()) {
5130 2439 : return libc_getpwuid(uid);
5131 : }
5132 :
5133 24251 : return nwrap_getpwuid(uid);
5134 : }
5135 :
5136 : /****************************************************************************
5137 : * GETPWUID_R
5138 : ***************************************************************************/
5139 :
5140 2041 : static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
5141 : char *buf, size_t buflen, struct passwd **pwdstp)
5142 : {
5143 : size_t i;
5144 : int ret;
5145 :
5146 2093 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5147 2093 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5148 2093 : ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
5149 2093 : if (ret == ENOENT) {
5150 52 : continue;
5151 : }
5152 2041 : return ret;
5153 : }
5154 :
5155 0 : return ENOENT;
5156 : }
5157 :
5158 : #ifdef HAVE_SOLARIS_GETPWUID_R
5159 : int getpwuid_r(uid_t uid, struct passwd *pwdst,
5160 : char *buf, int buflen, struct passwd **pwdstp)
5161 : #else
5162 : int getpwuid_r(uid_t uid, struct passwd *pwdst,
5163 : char *buf, size_t buflen, struct passwd **pwdstp)
5164 : #endif
5165 : {
5166 2328 : if (!nss_wrapper_enabled()) {
5167 287 : return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
5168 : }
5169 :
5170 2041 : return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
5171 : }
5172 :
5173 : /****************************************************************************
5174 : * SETPWENT
5175 : ***************************************************************************/
5176 :
5177 10 : static void nwrap_setpwent(void)
5178 : {
5179 : size_t i;
5180 :
5181 30 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5182 20 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5183 20 : b->ops->nw_setpwent(b);
5184 : }
5185 10 : }
5186 :
5187 : void setpwent(void)
5188 : {
5189 10 : if (!nss_wrapper_enabled()) {
5190 0 : libc_setpwent();
5191 0 : return;
5192 : }
5193 :
5194 10 : nwrap_setpwent();
5195 : }
5196 :
5197 : /****************************************************************************
5198 : * GETPWENT
5199 : ***************************************************************************/
5200 :
5201 192 : static struct passwd *nwrap_getpwent(void)
5202 : {
5203 : size_t i;
5204 : struct passwd *pwd;
5205 :
5206 282 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5207 276 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5208 276 : pwd = b->ops->nw_getpwent(b);
5209 276 : if (pwd) {
5210 186 : return pwd;
5211 : }
5212 : }
5213 :
5214 6 : return NULL;
5215 : }
5216 :
5217 : struct passwd *getpwent(void)
5218 : {
5219 192 : if (!nss_wrapper_enabled()) {
5220 0 : return libc_getpwent();
5221 : }
5222 :
5223 192 : return nwrap_getpwent();
5224 : }
5225 :
5226 : /****************************************************************************
5227 : * GETPWENT_R
5228 : ***************************************************************************/
5229 :
5230 : #ifdef HAVE_GETPWENT_R
5231 128 : static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
5232 : size_t buflen, struct passwd **pwdstp)
5233 : {
5234 : size_t i;
5235 : int ret;
5236 :
5237 188 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5238 184 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5239 184 : ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
5240 184 : if (ret == ENOENT) {
5241 60 : continue;
5242 : }
5243 124 : return ret;
5244 : }
5245 :
5246 4 : return ENOENT;
5247 : }
5248 :
5249 : # ifdef HAVE_SOLARIS_GETPWENT_R
5250 : struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
5251 : {
5252 : struct passwd *pwdstp = NULL;
5253 : int rc;
5254 :
5255 : if (!nss_wrapper_enabled()) {
5256 : return libc_getpwent_r(pwdst, buf, buflen);
5257 : }
5258 : rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
5259 : if (rc < 0) {
5260 : return NULL;
5261 : }
5262 :
5263 : return pwdstp;
5264 : }
5265 : # else /* HAVE_SOLARIS_GETPWENT_R */
5266 : int getpwent_r(struct passwd *pwdst, char *buf,
5267 : size_t buflen, struct passwd **pwdstp)
5268 : {
5269 128 : if (!nss_wrapper_enabled()) {
5270 0 : return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
5271 : }
5272 :
5273 128 : return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
5274 : }
5275 : # endif /* HAVE_SOLARIS_GETPWENT_R */
5276 : #endif /* HAVE_GETPWENT_R */
5277 :
5278 : /****************************************************************************
5279 : * ENDPWENT
5280 : ***************************************************************************/
5281 :
5282 3811 : static void nwrap_endpwent(void)
5283 : {
5284 : size_t i;
5285 :
5286 11427 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5287 7616 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5288 7616 : b->ops->nw_endpwent(b);
5289 : }
5290 3811 : }
5291 :
5292 : void endpwent(void)
5293 : {
5294 4024 : if (!nss_wrapper_enabled()) {
5295 213 : libc_endpwent();
5296 213 : return;
5297 : }
5298 :
5299 3811 : nwrap_endpwent();
5300 : }
5301 :
5302 : /****************************************************************************
5303 : * INITGROUPS
5304 : ***************************************************************************/
5305 :
5306 0 : static int nwrap_initgroups(const char *user, gid_t group)
5307 : {
5308 : size_t i;
5309 :
5310 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5311 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5312 : int rc;
5313 :
5314 0 : rc = b->ops->nw_initgroups(b, user, group);
5315 0 : if (rc == 0) {
5316 0 : return 0;
5317 : }
5318 : }
5319 :
5320 0 : errno = ENOENT;
5321 0 : return -1;
5322 : }
5323 :
5324 : int initgroups(const char *user, gid_t group)
5325 : {
5326 0 : if (!nss_wrapper_enabled()) {
5327 0 : return libc_initgroups(user, group);
5328 : }
5329 :
5330 0 : return nwrap_initgroups(user, group);
5331 : }
5332 :
5333 : /****************************************************************************
5334 : * GETGRNAM
5335 : ***************************************************************************/
5336 :
5337 319 : static struct group *nwrap_getgrnam(const char *name)
5338 : {
5339 : size_t i;
5340 : struct group *grp;
5341 :
5342 411 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5343 405 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5344 405 : grp = b->ops->nw_getgrnam(b, name);
5345 405 : if (grp) {
5346 313 : return grp;
5347 : }
5348 : }
5349 :
5350 6 : return NULL;
5351 : }
5352 :
5353 : struct group *getgrnam(const char *name)
5354 : {
5355 319 : if (!nss_wrapper_enabled()) {
5356 0 : return libc_getgrnam(name);
5357 : }
5358 :
5359 319 : return nwrap_getgrnam(name);
5360 : }
5361 :
5362 : /****************************************************************************
5363 : * GETGRNAM_R
5364 : ***************************************************************************/
5365 :
5366 452 : static int nwrap_getgrnam_r(const char *name, struct group *grdst,
5367 : char *buf, size_t buflen, struct group **grdstp)
5368 : {
5369 : size_t i;
5370 : int ret;
5371 :
5372 834 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5373 666 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5374 666 : ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
5375 666 : if (ret == ENOENT) {
5376 382 : continue;
5377 : }
5378 284 : return ret;
5379 : }
5380 :
5381 168 : return ENOENT;
5382 : }
5383 :
5384 : #ifdef HAVE_GETGRNAM_R
5385 : # ifdef HAVE_SOLARIS_GETGRNAM_R
5386 : int getgrnam_r(const char *name, struct group *grp,
5387 : char *buf, int buflen, struct group **pgrp)
5388 : # else /* HAVE_SOLARIS_GETGRNAM_R */
5389 : int getgrnam_r(const char *name, struct group *grp,
5390 : char *buf, size_t buflen, struct group **pgrp)
5391 : # endif /* HAVE_SOLARIS_GETGRNAM_R */
5392 : {
5393 589 : if (!nss_wrapper_enabled()) {
5394 137 : return libc_getgrnam_r(name,
5395 : grp,
5396 : buf,
5397 : buflen,
5398 : pgrp);
5399 : }
5400 :
5401 452 : return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
5402 : }
5403 : #endif /* HAVE_GETGRNAM_R */
5404 :
5405 : /****************************************************************************
5406 : * GETGRGID
5407 : ***************************************************************************/
5408 :
5409 253 : static struct group *nwrap_getgrgid(gid_t gid)
5410 : {
5411 : size_t i;
5412 : struct group *grp;
5413 :
5414 421 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5415 417 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5416 417 : grp = b->ops->nw_getgrgid(b, gid);
5417 417 : if (grp) {
5418 249 : return grp;
5419 : }
5420 : }
5421 :
5422 4 : return NULL;
5423 : }
5424 :
5425 : struct group *getgrgid(gid_t gid)
5426 : {
5427 253 : if (!nss_wrapper_enabled()) {
5428 0 : return libc_getgrgid(gid);
5429 : }
5430 :
5431 253 : return nwrap_getgrgid(gid);
5432 : }
5433 :
5434 : /****************************************************************************
5435 : * GETGRGID_R
5436 : ***************************************************************************/
5437 :
5438 1905 : static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
5439 : char *buf, size_t buflen, struct group **grdstp)
5440 : {
5441 : size_t i;
5442 : int ret;
5443 :
5444 1977 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5445 1977 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5446 1977 : ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
5447 1977 : if (ret == ENOENT) {
5448 72 : continue;
5449 : }
5450 1905 : return ret;
5451 : }
5452 :
5453 0 : return ENOENT;
5454 : }
5455 :
5456 : #ifdef HAVE_GETGRGID_R
5457 : # ifdef HAVE_SOLARIS_GETGRGID_R
5458 : int getgrgid_r(gid_t gid, struct group *grdst,
5459 : char *buf, int buflen, struct group **grdstp)
5460 : # else /* HAVE_SOLARIS_GETGRGID_R */
5461 : int getgrgid_r(gid_t gid, struct group *grdst,
5462 : char *buf, size_t buflen, struct group **grdstp)
5463 : # endif /* HAVE_SOLARIS_GETGRGID_R */
5464 : {
5465 2141 : if (!nss_wrapper_enabled()) {
5466 236 : return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
5467 : }
5468 :
5469 1905 : return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
5470 : }
5471 : #endif
5472 :
5473 : /****************************************************************************
5474 : * SETGRENT
5475 : ***************************************************************************/
5476 :
5477 2986 : static void nwrap_setgrent(void)
5478 : {
5479 : size_t i;
5480 :
5481 8876 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5482 5890 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5483 5890 : b->ops->nw_setgrent(b);
5484 : }
5485 2986 : }
5486 :
5487 : #ifdef HAVE_BSD_SETGRENT
5488 : int setgrent(void)
5489 : #else
5490 : void setgrent(void)
5491 : #endif
5492 : {
5493 10 : if (!nss_wrapper_enabled()) {
5494 0 : libc_setgrent();
5495 0 : goto out;
5496 : }
5497 :
5498 10 : nwrap_setgrent();
5499 :
5500 10 : out:
5501 : #ifdef HAVE_BSD_SETGRENT
5502 : return 0;
5503 : #else
5504 10 : return;
5505 : #endif
5506 : }
5507 :
5508 : /****************************************************************************
5509 : * GETGRENT
5510 : ***************************************************************************/
5511 :
5512 34918 : static struct group *nwrap_getgrent(void)
5513 : {
5514 : size_t i;
5515 : struct group *grp;
5516 :
5517 43284 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5518 40302 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5519 40302 : grp = b->ops->nw_getgrent(b);
5520 40302 : if (grp) {
5521 31936 : return grp;
5522 : }
5523 : }
5524 :
5525 2982 : return NULL;
5526 : }
5527 :
5528 : struct group *getgrent(void)
5529 : {
5530 180 : if (!nss_wrapper_enabled()) {
5531 0 : return libc_getgrent();
5532 : }
5533 :
5534 180 : return nwrap_getgrent();
5535 : }
5536 :
5537 : /****************************************************************************
5538 : * GETGRENT_R
5539 : ***************************************************************************/
5540 :
5541 : #ifdef HAVE_GETGRENT_R
5542 120 : static int nwrap_getgrent_r(struct group *grdst, char *buf,
5543 : size_t buflen, struct group **grdstp)
5544 : {
5545 : size_t i;
5546 : int ret;
5547 :
5548 200 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5549 196 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5550 196 : ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
5551 196 : if (ret == ENOENT) {
5552 80 : continue;
5553 : }
5554 116 : return ret;
5555 : }
5556 :
5557 4 : return ENOENT;
5558 : }
5559 :
5560 : # ifdef HAVE_SOLARIS_GETGRENT_R
5561 : struct group *getgrent_r(struct group *src, char *buf, int buflen)
5562 : {
5563 : struct group *grdstp = NULL;
5564 : int rc;
5565 :
5566 : if (!nss_wrapper_enabled()) {
5567 : return libc_getgrent_r(src, buf, buflen);
5568 : }
5569 :
5570 : rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
5571 : if (rc < 0) {
5572 : return NULL;
5573 : }
5574 :
5575 : return grdstp;
5576 : }
5577 : # else /* HAVE_SOLARIS_GETGRENT_R */
5578 : int getgrent_r(struct group *src, char *buf,
5579 : size_t buflen, struct group **grdstp)
5580 : {
5581 120 : if (!nss_wrapper_enabled()) {
5582 0 : return libc_getgrent_r(src, buf, buflen, grdstp);
5583 : }
5584 :
5585 120 : return nwrap_getgrent_r(src, buf, buflen, grdstp);
5586 : }
5587 : # endif /* HAVE_SOLARIS_GETGRENT_R */
5588 : #endif /* HAVE_GETGRENT_R */
5589 :
5590 : /****************************************************************************
5591 : * ENDGRENT
5592 : ***************************************************************************/
5593 :
5594 2986 : static void nwrap_endgrent(void)
5595 : {
5596 : size_t i;
5597 :
5598 8876 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5599 5890 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5600 5890 : b->ops->nw_endgrent(b);
5601 : }
5602 2986 : }
5603 :
5604 : void endgrent(void)
5605 : {
5606 10 : if (!nss_wrapper_enabled()) {
5607 0 : libc_endgrent();
5608 0 : return;
5609 : }
5610 :
5611 10 : nwrap_endgrent();
5612 : }
5613 :
5614 : /****************************************************************************
5615 : * GETGROUPLIST
5616 : ***************************************************************************/
5617 :
5618 : #ifdef HAVE_GETGROUPLIST
5619 2976 : static int nwrap_getgrouplist(const char *user, gid_t group,
5620 : gid_t *groups, int *ngroups)
5621 : {
5622 : struct group *grp;
5623 : gid_t *groups_tmp;
5624 2976 : int count = 1;
5625 :
5626 2976 : NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
5627 :
5628 2976 : groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
5629 2976 : if (!groups_tmp) {
5630 0 : NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
5631 0 : errno = ENOMEM;
5632 0 : return -1;
5633 : }
5634 2976 : groups_tmp[0] = group;
5635 :
5636 2976 : nwrap_setgrent();
5637 34738 : while ((grp = nwrap_getgrent()) != NULL) {
5638 31762 : int i = 0;
5639 :
5640 31762 : NWRAP_LOG(NWRAP_LOG_DEBUG,
5641 : "Inspecting %s for group membership",
5642 : grp->gr_name);
5643 :
5644 41656 : for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
5645 :
5646 9894 : if (group != grp->gr_gid &&
5647 9824 : (strcmp(user, grp->gr_mem[i]) == 0)) {
5648 :
5649 1357 : NWRAP_LOG(NWRAP_LOG_DEBUG,
5650 : "%s is member of %s",
5651 : user,
5652 : grp->gr_name);
5653 :
5654 1357 : groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
5655 1357 : if (!groups_tmp) {
5656 0 : NWRAP_LOG(NWRAP_LOG_ERROR,
5657 : "Out of memory");
5658 0 : errno = ENOMEM;
5659 0 : return -1;
5660 : }
5661 1357 : groups_tmp[count] = grp->gr_gid;
5662 :
5663 1357 : count++;
5664 : }
5665 : }
5666 : }
5667 :
5668 2976 : nwrap_endgrent();
5669 :
5670 2976 : NWRAP_LOG(NWRAP_LOG_DEBUG,
5671 : "%s is member of %d groups",
5672 : user, *ngroups);
5673 :
5674 2976 : if (*ngroups < count) {
5675 62 : *ngroups = count;
5676 62 : free(groups_tmp);
5677 62 : return -1;
5678 : }
5679 :
5680 2914 : *ngroups = count;
5681 2914 : memcpy(groups, groups_tmp, count * sizeof(gid_t));
5682 2914 : free(groups_tmp);
5683 :
5684 2914 : return count;
5685 : }
5686 :
5687 : int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
5688 : {
5689 2976 : if (!nss_wrapper_enabled()) {
5690 0 : return libc_getgrouplist(user, group, groups, ngroups);
5691 : }
5692 :
5693 2976 : return nwrap_getgrouplist(user, group, groups, ngroups);
5694 : }
5695 : #endif
5696 :
5697 : /**********************************************************
5698 : * SHADOW
5699 : **********************************************************/
5700 :
5701 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
5702 :
5703 : #ifdef HAVE_SETSPENT
5704 : static void nwrap_setspent(void)
5705 : {
5706 : nwrap_files_setspent();
5707 : }
5708 :
5709 : void setspent(void)
5710 : {
5711 : if (!nss_wrapper_shadow_enabled()) {
5712 : return;
5713 : }
5714 :
5715 : nwrap_setspent();
5716 : }
5717 :
5718 : static struct spwd *nwrap_getspent(void)
5719 : {
5720 : return nwrap_files_getspent();
5721 : }
5722 :
5723 : struct spwd *getspent(void)
5724 : {
5725 : if (!nss_wrapper_shadow_enabled()) {
5726 : return NULL;
5727 : }
5728 :
5729 : return nwrap_getspent();
5730 : }
5731 :
5732 : static void nwrap_endspent(void)
5733 : {
5734 : nwrap_files_endspent();
5735 : }
5736 :
5737 : void endspent(void)
5738 : {
5739 : if (!nss_wrapper_shadow_enabled()) {
5740 : return;
5741 : }
5742 :
5743 : nwrap_endspent();
5744 : }
5745 : #endif /* HAVE_SETSPENT */
5746 :
5747 0 : static struct spwd *nwrap_getspnam(const char *name)
5748 : {
5749 0 : return nwrap_files_getspnam(name);
5750 : }
5751 :
5752 : struct spwd *getspnam(const char *name)
5753 : {
5754 0 : if (!nss_wrapper_shadow_enabled()) {
5755 0 : return NULL;
5756 : }
5757 :
5758 0 : return nwrap_getspnam(name);
5759 : }
5760 :
5761 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
5762 :
5763 : /**********************************************************
5764 : * NETDB
5765 : **********************************************************/
5766 :
5767 0 : static void nwrap_sethostent(int stayopen) {
5768 : (void) stayopen; /* ignored */
5769 :
5770 0 : nwrap_files_sethostent();
5771 0 : }
5772 :
5773 : #ifdef HAVE_SOLARIS_SETHOSTENT
5774 : int sethostent(int stayopen)
5775 : {
5776 : if (!nss_wrapper_hosts_enabled()) {
5777 : libc_sethostent(stayopen);
5778 : return 0;
5779 : }
5780 :
5781 : nwrap_sethostent(stayopen);
5782 :
5783 : return 0;
5784 : }
5785 : #else /* HAVE_SOLARIS_SETHOSTENT */
5786 : void sethostent(int stayopen)
5787 : {
5788 0 : if (!nss_wrapper_hosts_enabled()) {
5789 0 : libc_sethostent(stayopen);
5790 0 : return;
5791 : }
5792 :
5793 0 : nwrap_sethostent(stayopen);
5794 : }
5795 : #endif /* HAVE_SOLARIS_SETHOSTENT */
5796 :
5797 0 : static struct hostent *nwrap_gethostent(void)
5798 : {
5799 0 : return nwrap_files_gethostent();
5800 : }
5801 :
5802 : struct hostent *gethostent(void) {
5803 0 : if (!nss_wrapper_hosts_enabled()) {
5804 0 : return libc_gethostent();
5805 : }
5806 :
5807 0 : return nwrap_gethostent();
5808 : }
5809 :
5810 0 : static void nwrap_endhostent(void) {
5811 0 : nwrap_files_endhostent();
5812 0 : }
5813 :
5814 : #ifdef HAVE_SOLARIS_ENDHOSTENT
5815 : int endhostent(void)
5816 : {
5817 : if (!nss_wrapper_hosts_enabled()) {
5818 : libc_endhostent();
5819 : return 0;
5820 : }
5821 :
5822 : nwrap_endhostent();
5823 :
5824 : return 0;
5825 : }
5826 : #else /* HAVE_SOLARIS_ENDHOSTENT */
5827 : void endhostent(void)
5828 : {
5829 0 : if (!nss_wrapper_hosts_enabled()) {
5830 0 : libc_endhostent();
5831 0 : return;
5832 : }
5833 :
5834 0 : nwrap_endhostent();
5835 : }
5836 : #endif /* HAVE_SOLARIS_ENDHOSTENT */
5837 :
5838 :
5839 : #ifdef BSD
5840 : /* BSD implementation stores data in thread local storage but GLIBC does not */
5841 : static __thread struct hostent user_he;
5842 : static __thread struct nwrap_vector user_addrlist;
5843 : #else
5844 : static struct hostent user_he;
5845 : static struct nwrap_vector user_addrlist;
5846 : #endif /* BSD */
5847 :
5848 0 : static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
5849 : const char *name)
5850 : {
5851 : int ret;
5852 :
5853 : (void) b; /* unused */
5854 :
5855 0 : ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he,
5856 : &user_addrlist);
5857 0 : if (ret == 0) {
5858 0 : return &user_he;
5859 : }
5860 :
5861 0 : return NULL;
5862 : }
5863 :
5864 0 : static struct hostent *nwrap_gethostbyname(const char *name)
5865 : {
5866 : size_t i;
5867 0 : struct hostent *he = NULL;
5868 :
5869 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5870 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5871 0 : he = b->ops->nw_gethostbyname(b, name);
5872 0 : if (he != NULL) {
5873 0 : return he;
5874 : }
5875 : }
5876 :
5877 0 : return NULL;
5878 : }
5879 :
5880 : struct hostent *gethostbyname(const char *name)
5881 : {
5882 0 : if (!nss_wrapper_hosts_enabled()) {
5883 0 : return libc_gethostbyname(name);
5884 : }
5885 :
5886 0 : return nwrap_gethostbyname(name);
5887 : }
5888 :
5889 : /* This is a GNU extension - Also can be found on BSD systems */
5890 : #ifdef HAVE_GETHOSTBYNAME2
5891 : #ifdef BSD
5892 : /* BSD implementation stores data in thread local storage but GLIBC not */
5893 : static __thread struct hostent user_he2;
5894 : static __thread struct nwrap_vector user_addrlist2;
5895 : #else
5896 : static struct hostent user_he2;
5897 : static struct nwrap_vector user_addrlist2;
5898 : #endif /* BSD */
5899 :
5900 0 : static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
5901 : const char *name, int af)
5902 : {
5903 : int ret;
5904 :
5905 : (void) b; /* unused */
5906 :
5907 0 : ret = nwrap_files_internal_gethostbyname(name, af, &user_he2,
5908 : &user_addrlist2);
5909 0 : if (ret == 0) {
5910 0 : return &user_he2;
5911 : }
5912 :
5913 0 : return NULL;
5914 : }
5915 :
5916 0 : static struct hostent *nwrap_gethostbyname2(const char *name, int af)
5917 : {
5918 : size_t i;
5919 0 : struct hostent *he = NULL;
5920 :
5921 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5922 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5923 0 : he = b->ops->nw_gethostbyname2(b, name, af);
5924 0 : if (he != NULL) {
5925 0 : return he;
5926 : }
5927 : }
5928 :
5929 0 : return NULL;
5930 : }
5931 :
5932 : struct hostent *gethostbyname2(const char *name, int af)
5933 : {
5934 0 : if (!nss_wrapper_hosts_enabled()) {
5935 0 : return libc_gethostbyname2(name, af);
5936 : }
5937 :
5938 0 : return nwrap_gethostbyname2(name, af);
5939 : }
5940 : #endif
5941 :
5942 0 : static struct hostent *nwrap_gethostbyaddr(const void *addr,
5943 : socklen_t len, int type)
5944 : {
5945 : size_t i;
5946 0 : struct hostent *he = NULL;
5947 :
5948 0 : for (i=0; i < nwrap_main_global->num_backends; i++) {
5949 0 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
5950 0 : he = b->ops->nw_gethostbyaddr(b, addr, len, type);
5951 0 : if (he != NULL) {
5952 0 : return he;
5953 : }
5954 : }
5955 :
5956 0 : return NULL;
5957 : }
5958 :
5959 : struct hostent *gethostbyaddr(const void *addr,
5960 : socklen_t len, int type)
5961 : {
5962 0 : if (!nss_wrapper_hosts_enabled()) {
5963 0 : return libc_gethostbyaddr(addr, len, type);
5964 : }
5965 :
5966 0 : return nwrap_gethostbyaddr(addr, len, type);
5967 : }
5968 :
5969 : static const struct addrinfo default_hints =
5970 : {
5971 : .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
5972 : .ai_family = AF_UNSPEC,
5973 : .ai_socktype = 0,
5974 : .ai_protocol = 0,
5975 : .ai_addrlen = 0,
5976 : .ai_addr = NULL,
5977 : .ai_canonname = NULL,
5978 : .ai_next = NULL
5979 : };
5980 :
5981 193425 : static int nwrap_convert_he_ai(const struct hostent *he,
5982 : unsigned short port,
5983 : const struct addrinfo *hints,
5984 : struct addrinfo **pai,
5985 : bool skip_canonname)
5986 : {
5987 : struct addrinfo *ai;
5988 : socklen_t socklen;
5989 :
5990 193425 : if (he == NULL) {
5991 0 : return EAI_MEMORY;
5992 : }
5993 :
5994 193425 : switch (he->h_addrtype) {
5995 141729 : case AF_INET:
5996 141729 : socklen = sizeof(struct sockaddr_in);
5997 141729 : break;
5998 : #ifdef HAVE_IPV6
5999 51696 : case AF_INET6:
6000 51696 : socklen = sizeof(struct sockaddr_in6);
6001 51696 : break;
6002 : #endif
6003 0 : default:
6004 0 : return EAI_FAMILY;
6005 : }
6006 :
6007 193425 : ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
6008 193425 : if (ai == NULL) {
6009 0 : return EAI_MEMORY;
6010 : }
6011 :
6012 193425 : ai->ai_flags = hints->ai_flags;
6013 193425 : ai->ai_family = he->h_addrtype;
6014 193425 : ai->ai_socktype = hints->ai_socktype;
6015 193425 : ai->ai_protocol = hints->ai_protocol;
6016 193425 : ai->ai_canonname = NULL;
6017 :
6018 193425 : if (ai->ai_socktype == 0) {
6019 284 : ai->ai_socktype = SOCK_DGRAM;
6020 : }
6021 193425 : if (ai->ai_protocol == 0) {
6022 181487 : if (ai->ai_socktype == SOCK_DGRAM) {
6023 18469 : ai->ai_protocol = IPPROTO_UDP;
6024 163018 : } else if (ai->ai_socktype == SOCK_STREAM) {
6025 163018 : ai->ai_protocol = IPPROTO_TCP;
6026 : }
6027 : }
6028 :
6029 193425 : ai->ai_addrlen = socklen;
6030 193425 : ai->ai_addr = (void *)(ai + 1);
6031 :
6032 : #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
6033 : ai->ai_addr->sa_len = socklen;
6034 : #endif
6035 193425 : ai->ai_addr->sa_family = he->h_addrtype;
6036 :
6037 193425 : switch (he->h_addrtype) {
6038 141729 : case AF_INET:
6039 : {
6040 : union {
6041 : struct sockaddr *sa;
6042 : struct sockaddr_in *in;
6043 : } addr;
6044 :
6045 141729 : addr.sa = ai->ai_addr;
6046 :
6047 141729 : memset(addr.in, 0, sizeof(struct sockaddr_in));
6048 :
6049 141729 : addr.in->sin_port = htons(port);
6050 141729 : addr.in->sin_family = AF_INET;
6051 :
6052 141729 : memset(addr.in->sin_zero,
6053 : '\0',
6054 : sizeof (addr.in->sin_zero));
6055 141729 : memcpy(&(addr.in->sin_addr),
6056 141729 : he->h_addr_list[0],
6057 141729 : he->h_length);
6058 :
6059 : }
6060 141729 : break;
6061 : #ifdef HAVE_IPV6
6062 51696 : case AF_INET6:
6063 : {
6064 : union {
6065 : struct sockaddr *sa;
6066 : struct sockaddr_in6 *in6;
6067 : } addr;
6068 :
6069 51696 : addr.sa = ai->ai_addr;
6070 :
6071 51696 : memset(addr.in6, 0, sizeof(struct sockaddr_in6));
6072 :
6073 51696 : addr.in6->sin6_port = htons(port);
6074 51696 : addr.in6->sin6_family = AF_INET6;
6075 :
6076 51696 : memcpy(&addr.in6->sin6_addr,
6077 51696 : he->h_addr_list[0],
6078 51696 : he->h_length);
6079 : }
6080 51696 : break;
6081 : #endif
6082 : }
6083 :
6084 193425 : ai->ai_next = NULL;
6085 :
6086 193425 : if (he->h_name && !skip_canonname) {
6087 184537 : ai->ai_canonname = strdup(he->h_name);
6088 184537 : if (ai->ai_canonname == NULL) {
6089 0 : freeaddrinfo(ai);
6090 0 : return EAI_MEMORY;
6091 : }
6092 : }
6093 :
6094 193425 : *pai = ai;
6095 193425 : return 0;
6096 : }
6097 :
6098 659257 : static int nwrap_getaddrinfo(const char *node,
6099 : const char *service,
6100 : const struct addrinfo *hints,
6101 : struct addrinfo **res)
6102 : {
6103 659257 : struct addrinfo *ai = NULL;
6104 659257 : unsigned short port = 0;
6105 : struct {
6106 : int family;
6107 : union {
6108 : struct in_addr v4;
6109 : #ifdef HAVE_IPV6
6110 : struct in6_addr v6;
6111 : } in;
6112 : #endif
6113 659257 : } addr = {
6114 : .family = AF_UNSPEC,
6115 : };
6116 : int rc;
6117 :
6118 659257 : if (node == NULL && service == NULL) {
6119 0 : return EAI_NONAME;
6120 : }
6121 :
6122 659257 : if (hints == NULL) {
6123 0 : hints = &default_hints;
6124 : }
6125 :
6126 : /* EAI_BADFLAGS
6127 : hints.ai_flags contains invalid flags; or, hints.ai_flags
6128 : included AI_CANONNAME and name was NULL.
6129 : */
6130 659257 : if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
6131 0 : return EAI_BADFLAGS;
6132 : }
6133 :
6134 : /* If no node has been specified, let glibc deal with it */
6135 659257 : if (node == NULL) {
6136 : int ret;
6137 0 : struct addrinfo *p = NULL;
6138 :
6139 0 : ret = libc_getaddrinfo(node, service, hints, &p);
6140 :
6141 0 : if (ret == 0) {
6142 0 : *res = p;
6143 : }
6144 0 : return ret;
6145 : }
6146 :
6147 659257 : if (service != NULL && service[0] != '\0') {
6148 106960 : const char *proto = NULL;
6149 : struct servent *s;
6150 : char *end_ptr;
6151 : long sl;
6152 :
6153 106960 : errno = 0;
6154 106960 : sl = strtol(service, &end_ptr, 10);
6155 :
6156 106960 : if (*end_ptr == '\0') {
6157 106960 : port = sl;
6158 106960 : goto valid_port;
6159 0 : } else if (hints->ai_flags & AI_NUMERICSERV) {
6160 0 : return EAI_NONAME;
6161 : }
6162 :
6163 0 : if (hints->ai_protocol != 0) {
6164 : struct protoent *pent;
6165 :
6166 0 : pent = getprotobynumber(hints->ai_protocol);
6167 0 : if (pent != NULL) {
6168 0 : proto = pent->p_name;
6169 : }
6170 : }
6171 :
6172 0 : s = getservbyname(service, proto);
6173 0 : if (s == NULL) {
6174 0 : return EAI_NONAME;
6175 : }
6176 0 : port = ntohs(s->s_port);
6177 : }
6178 :
6179 552297 : valid_port:
6180 :
6181 659257 : rc = inet_pton(AF_INET, node, &addr.in.v4);
6182 659257 : if (rc == 1) {
6183 518868 : addr.family = AF_INET;
6184 : }
6185 : #ifdef HAVE_IPV6
6186 659257 : if (addr.family == AF_UNSPEC) {
6187 140389 : rc = inet_pton(AF_INET6, node, &addr.in.v6);
6188 140389 : if (rc == 1) {
6189 128926 : addr.family = AF_INET6;
6190 : }
6191 : }
6192 : #endif
6193 :
6194 659257 : if (addr.family == AF_UNSPEC) {
6195 11463 : if (hints->ai_flags & AI_NUMERICHOST) {
6196 2535 : return EAI_NONAME;
6197 : }
6198 647794 : } else if ((hints->ai_family != AF_UNSPEC) &&
6199 10409 : (hints->ai_family != addr.family))
6200 : {
6201 0 : return EAI_ADDRFAMILY;
6202 : }
6203 :
6204 656722 : rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
6205 656722 : if (rc != 0) {
6206 : int ret;
6207 472185 : struct addrinfo *p = NULL;
6208 :
6209 472185 : ret = libc_getaddrinfo(node, service, hints, &p);
6210 :
6211 472185 : if (ret == 0) {
6212 : /*
6213 : * nwrap_files_getaddrinfo failed, but libc was
6214 : * successful -- use the result from libc.
6215 : */
6216 472165 : *res = p;
6217 472165 : return 0;
6218 : }
6219 :
6220 20 : return rc;
6221 : }
6222 :
6223 : /*
6224 : * If the socktype was not specified, duplicate
6225 : * each ai returned, so that we have variants for
6226 : * both UDP and TCP.
6227 : */
6228 184537 : if (hints->ai_socktype == 0) {
6229 : struct addrinfo *ai_cur;
6230 :
6231 : /* freeaddrinfo() frees ai_canonname and ai so allocate them */
6232 426 : for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
6233 : struct addrinfo *ai_new;
6234 :
6235 : /* duplicate the current entry */
6236 :
6237 284 : ai_new = malloc(sizeof(struct addrinfo));
6238 284 : if (ai_new == NULL) {
6239 0 : freeaddrinfo(ai);
6240 0 : return EAI_MEMORY;
6241 : }
6242 :
6243 284 : memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
6244 284 : ai_new->ai_next = NULL;
6245 :
6246 : /* We need a deep copy or freeaddrinfo() will blow up */
6247 284 : if (ai_cur->ai_canonname != NULL) {
6248 142 : ai_new->ai_canonname =
6249 142 : strdup(ai_cur->ai_canonname);
6250 : }
6251 :
6252 284 : if (ai_cur->ai_socktype == SOCK_DGRAM) {
6253 284 : ai_new->ai_socktype = SOCK_STREAM;
6254 0 : } else if (ai_cur->ai_socktype == SOCK_STREAM) {
6255 0 : ai_new->ai_socktype = SOCK_DGRAM;
6256 : }
6257 284 : if (ai_cur->ai_protocol == IPPROTO_TCP) {
6258 0 : ai_new->ai_protocol = IPPROTO_UDP;
6259 284 : } else if (ai_cur->ai_protocol == IPPROTO_UDP) {
6260 284 : ai_new->ai_protocol = IPPROTO_TCP;
6261 : }
6262 :
6263 : /* now insert the new entry */
6264 :
6265 284 : ai_new->ai_next = ai_cur->ai_next;
6266 284 : ai_cur->ai_next = ai_new;
6267 :
6268 : /* and move on (don't duplicate the new entry) */
6269 :
6270 284 : ai_cur = ai_new;
6271 : }
6272 : }
6273 :
6274 184537 : *res = ai;
6275 :
6276 184537 : return 0;
6277 : }
6278 :
6279 : int getaddrinfo(const char *node, const char *service,
6280 : const struct addrinfo *hints,
6281 : struct addrinfo **res)
6282 : {
6283 671890 : if (!nss_wrapper_hosts_enabled()) {
6284 12633 : return libc_getaddrinfo(node, service, hints, res);
6285 : }
6286 :
6287 659257 : return nwrap_getaddrinfo(node, service, hints, res);
6288 : }
6289 :
6290 1501399 : static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
6291 : char *host, size_t hostlen,
6292 : char *serv, size_t servlen,
6293 : int flags)
6294 : {
6295 : struct hostent *he;
6296 : struct servent *service;
6297 : const char *proto;
6298 : const void *addr;
6299 : socklen_t addrlen;
6300 : uint16_t port;
6301 : sa_family_t type;
6302 : size_t i;
6303 :
6304 1501399 : if (sa == NULL || salen < sizeof(sa_family_t)) {
6305 0 : return EAI_FAMILY;
6306 : }
6307 :
6308 1501399 : if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
6309 0 : return EAI_NONAME;
6310 : }
6311 :
6312 1501399 : type = sa->sa_family;
6313 1501399 : switch (type) {
6314 1202351 : case AF_INET: {
6315 : union {
6316 : const struct sockaddr *sa;
6317 : const struct sockaddr_in *in;
6318 : } a;
6319 :
6320 1202351 : if (salen < sizeof(struct sockaddr_in)) {
6321 0 : return EAI_FAMILY;
6322 : }
6323 :
6324 1202351 : a.sa = sa;
6325 :
6326 1202351 : addr = &(a.in->sin_addr);
6327 1202351 : addrlen = sizeof(a.in->sin_addr);
6328 1202351 : port = ntohs(a.in->sin_port);
6329 1202351 : break;
6330 : }
6331 : #ifdef HAVE_IPV6
6332 299042 : case AF_INET6: {
6333 : union {
6334 : const struct sockaddr *sa;
6335 : const struct sockaddr_in6 *in6;
6336 : } a;
6337 :
6338 299042 : if (salen < sizeof(struct sockaddr_in6)) {
6339 0 : return EAI_FAMILY;
6340 : }
6341 :
6342 299042 : a.sa = sa;
6343 :
6344 299042 : addr = &(a.in6->sin6_addr);
6345 299042 : addrlen = sizeof(a.in6->sin6_addr);
6346 299042 : port = ntohs(a.in6->sin6_port);
6347 299042 : break;
6348 : }
6349 : #endif
6350 6 : default:
6351 6 : return EAI_FAMILY;
6352 : }
6353 :
6354 1501393 : if (host != NULL) {
6355 1501393 : he = NULL;
6356 1501393 : if ((flags & NI_NUMERICHOST) == 0) {
6357 97 : for (i=0; i < nwrap_main_global->num_backends; i++) {
6358 97 : struct nwrap_backend *b = &nwrap_main_global->backends[i];
6359 97 : he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type);
6360 97 : if (he != NULL) {
6361 97 : break;
6362 : }
6363 : }
6364 97 : if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
6365 0 : return EAI_NONAME;
6366 : }
6367 1501393 : if (he != NULL && he->h_name != NULL) {
6368 97 : if (strlen(he->h_name) >= hostlen)
6369 0 : return EAI_OVERFLOW;
6370 97 : snprintf(host, hostlen, "%s", he->h_name);
6371 97 : if (flags & NI_NOFQDN)
6372 0 : host[strcspn(host, ".")] = '\0';
6373 : } else {
6374 1501296 : if (inet_ntop(type, addr, host, hostlen) == NULL)
6375 0 : return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
6376 : }
6377 : }
6378 :
6379 1501393 : if (serv != NULL) {
6380 4558 : service = NULL;
6381 4558 : if ((flags & NI_NUMERICSERV) == 0) {
6382 16 : proto = (flags & NI_DGRAM) ? "udp" : "tcp";
6383 16 : service = getservbyport(htons(port), proto);
6384 : }
6385 4558 : if (service != NULL) {
6386 16 : if (strlen(service->s_name) >= servlen)
6387 0 : return EAI_OVERFLOW;
6388 16 : snprintf(serv, servlen, "%s", service->s_name);
6389 : } else {
6390 4542 : if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
6391 0 : return EAI_OVERFLOW;
6392 : }
6393 : }
6394 :
6395 1501393 : return 0;
6396 : }
6397 :
6398 : #ifdef HAVE_LINUX_GETNAMEINFO
6399 : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
6400 : char *host, socklen_t hostlen,
6401 : char *serv, socklen_t servlen,
6402 : int flags)
6403 : #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
6404 : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
6405 : char *host, socklen_t hostlen,
6406 : char *serv, socklen_t servlen,
6407 : unsigned int flags)
6408 : #else
6409 : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
6410 : char *host, size_t hostlen,
6411 : char *serv, size_t servlen,
6412 : int flags)
6413 : #endif
6414 : {
6415 1506983 : if (!nss_wrapper_hosts_enabled()) {
6416 5584 : return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
6417 : }
6418 :
6419 1501399 : return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
6420 : }
6421 :
6422 17222 : static int nwrap_gethostname(char *name, size_t len)
6423 : {
6424 17222 : const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
6425 :
6426 17222 : if (strlen(hostname) >= len) {
6427 0 : errno = ENAMETOOLONG;
6428 0 : return -1;
6429 : }
6430 17222 : snprintf(name, len, "%s", hostname);
6431 :
6432 17222 : return 0;
6433 : }
6434 :
6435 : #ifdef HAVE_SOLARIS_GETHOSTNAME
6436 : int gethostname(char *name, int len)
6437 : #else /* HAVE_SOLARIS_GETHOSTNAME */
6438 : int gethostname(char *name, size_t len)
6439 : #endif /* HAVE_SOLARIS_GETHOSTNAME */
6440 : {
6441 24471 : if (!nwrap_hostname_enabled()) {
6442 7249 : return libc_gethostname(name, len);
6443 : }
6444 :
6445 17222 : return nwrap_gethostname(name, len);
6446 : }
6447 :
6448 404916 : static void nwrap_thread_prepare(void)
6449 : {
6450 404916 : nwrap_init();
6451 404916 : NWRAP_LOCK_ALL;
6452 404916 : }
6453 :
6454 401275 : static void nwrap_thread_parent(void)
6455 : {
6456 401275 : NWRAP_UNLOCK_ALL;
6457 401275 : }
6458 :
6459 3641 : static void nwrap_thread_child(void)
6460 : {
6461 3641 : NWRAP_REINIT_ALL;
6462 3641 : }
6463 :
6464 : /****************************
6465 : * CONSTRUCTOR
6466 : ***************************/
6467 58692 : void nwrap_constructor(void)
6468 : {
6469 58692 : NWRAP_REINIT_ALL;
6470 :
6471 : /*
6472 : * If we hold a lock and the application forks, then the child
6473 : * is not able to unlock the mutex and we are in a deadlock.
6474 : *
6475 : * Setting these handlers should prevent such deadlocks.
6476 : */
6477 58692 : pthread_atfork(&nwrap_thread_prepare,
6478 : &nwrap_thread_parent,
6479 : &nwrap_thread_child);
6480 :
6481 : /* Do not call nwrap_init() here. */
6482 58692 : }
6483 :
6484 : /****************************
6485 : * DESTRUCTOR
6486 : ***************************/
6487 :
6488 : /*
6489 : * This function is called when the library is unloaded and makes sure that
6490 : * sockets get closed and the unix file for the socket are unlinked.
6491 : */
6492 80051 : void nwrap_destructor(void)
6493 : {
6494 : size_t i;
6495 :
6496 80051 : NWRAP_LOCK_ALL;
6497 80051 : if (nwrap_main_global != NULL) {
6498 40848 : struct nwrap_main *m = nwrap_main_global;
6499 :
6500 : /* libc */
6501 40848 : if (m->libc != NULL) {
6502 40848 : if (m->libc->handle != NULL) {
6503 30370 : dlclose(m->libc->handle);
6504 : }
6505 40848 : if (m->libc->nsl_handle != NULL) {
6506 21490 : dlclose(m->libc->nsl_handle);
6507 : }
6508 40848 : if (m->libc->sock_handle != NULL) {
6509 0 : dlclose(m->libc->sock_handle);
6510 : }
6511 40848 : SAFE_FREE(m->libc);
6512 : }
6513 :
6514 : /* backends */
6515 40848 : if (m->backends != NULL) {
6516 114667 : for (i = 0; i < m->num_backends; i++) {
6517 73819 : struct nwrap_backend *b = &(m->backends[i]);
6518 :
6519 73819 : if (b->so_handle != NULL) {
6520 32971 : dlclose(b->so_handle);
6521 : }
6522 73819 : SAFE_FREE(b->symbols);
6523 : }
6524 40848 : SAFE_FREE(m->backends);
6525 : }
6526 : }
6527 :
6528 80051 : if (nwrap_pw_global.cache != NULL) {
6529 40848 : struct nwrap_cache *c = nwrap_pw_global.cache;
6530 :
6531 40848 : nwrap_files_cache_unload(c);
6532 40848 : if (c->fd >= 0) {
6533 15339 : fclose(c->fp);
6534 15339 : c->fd = -1;
6535 : }
6536 :
6537 40848 : SAFE_FREE(nwrap_pw_global.list);
6538 40848 : nwrap_pw_global.num = 0;
6539 : }
6540 :
6541 80051 : if (nwrap_gr_global.cache != NULL) {
6542 40848 : struct nwrap_cache *c = nwrap_gr_global.cache;
6543 :
6544 40848 : nwrap_files_cache_unload(c);
6545 40848 : if (c->fd >= 0) {
6546 5697 : fclose(c->fp);
6547 5697 : c->fd = -1;
6548 : }
6549 :
6550 40848 : SAFE_FREE(nwrap_gr_global.list);
6551 40848 : nwrap_pw_global.num = 0;
6552 : }
6553 :
6554 : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
6555 80051 : if (nwrap_sp_global.cache != NULL) {
6556 40848 : struct nwrap_cache *c = nwrap_sp_global.cache;
6557 :
6558 40848 : nwrap_files_cache_unload(c);
6559 40848 : if (c->fd >= 0) {
6560 0 : fclose(c->fp);
6561 0 : c->fd = -1;
6562 : }
6563 :
6564 40848 : nwrap_sp_global.num = 0;
6565 : }
6566 : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
6567 :
6568 80051 : if (nwrap_he_global.cache != NULL) {
6569 40848 : struct nwrap_cache *c = nwrap_he_global.cache;
6570 :
6571 40848 : nwrap_files_cache_unload(c);
6572 40848 : if (c->fd >= 0) {
6573 27420 : fclose(c->fp);
6574 27420 : c->fd = -1;
6575 : }
6576 :
6577 40848 : nwrap_he_global.num = 0;
6578 : }
6579 :
6580 80051 : free(user_addrlist.items);
6581 : #ifdef HAVE_GETHOSTBYNAME2
6582 80051 : free(user_addrlist2.items);
6583 : #endif
6584 :
6585 80051 : hdestroy();
6586 80051 : NWRAP_UNLOCK_ALL;
6587 80051 : }
|