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