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