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