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>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
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.
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.
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
43 #include <sys/types.h>
45 #include <sys/socket.h>
58 #include <netinet/in.h>
64 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
65 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
68 #ifndef _POSIX_PTHREAD_SEMANTICS
69 #define _POSIX_PTHREAD_SEMANTICS
76 #endif /* HAVE_SHADOW_H */
79 #include <arpa/inet.h>
80 #include <netinet/in.h>
84 #if defined(HAVE_NSS_H)
88 typedef enum nss_status NSS_STATUS;
89 #elif defined(HAVE_NSS_COMMON_H)
91 #include <nss_common.h>
92 #include <nss_dbdefs.h>
95 typedef nss_status_t NSS_STATUS;
97 # define NSS_STATUS_SUCCESS NSS_SUCCESS
98 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
99 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
100 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
102 # error "No nsswitch support detected"
106 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
114 #define EAI_NODATA EAI_NONAME
117 #ifndef EAI_ADDRFAMILY
118 #define EAI_ADDRFAMILY EAI_FAMILY
122 #define __STRING(x) #x
125 #ifndef __STRINGSTRING
126 #define __STRINGSTRING(x) __STRING(x)
130 #define __LINESTR__ __STRINGSTRING(__LINE__)
134 #define __location__ __FILE__ ":" __LINESTR__
138 #define DNS_NAME_MAX 255
141 /* GCC have printf type attribute check. */
142 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
143 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
145 #define PRINTF_ATTRIBUTE(a,b)
146 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
148 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
149 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
151 #define CONSTRUCTOR_ATTRIBUTE
152 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
154 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
155 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
157 #define DESTRUCTOR_ATTRIBUTE
158 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
160 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
163 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
166 #ifndef discard_const
167 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
170 #ifndef discard_const_p
171 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
175 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
177 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
180 #define NWRAP_LOCK(m) do { \
181 pthread_mutex_lock(&( m ## _mutex)); \
184 #define NWRAP_UNLOCK(m) do { \
185 pthread_mutex_unlock(&( m ## _mutex)); \
189 static bool nwrap_initialized = false;
190 static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
192 /* The mutex or accessing the id */
193 static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER;
194 static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
195 static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER;
196 static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER;
197 static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
199 /* Add new global locks here please */
200 /* Also don't forget to add locks to
201 * nwrap_init() function.
203 # define NWRAP_LOCK_ALL do { \
204 NWRAP_LOCK(nwrap_initialized); \
205 NWRAP_LOCK(nwrap_global); \
206 NWRAP_LOCK(nwrap_gr_global); \
207 NWRAP_LOCK(nwrap_he_global); \
208 NWRAP_LOCK(nwrap_pw_global); \
209 NWRAP_LOCK(nwrap_sp_global); \
212 # define NWRAP_UNLOCK_ALL do {\
213 NWRAP_UNLOCK(nwrap_sp_global); \
214 NWRAP_UNLOCK(nwrap_pw_global); \
215 NWRAP_UNLOCK(nwrap_he_global); \
216 NWRAP_UNLOCK(nwrap_gr_global); \
217 NWRAP_UNLOCK(nwrap_global); \
218 NWRAP_UNLOCK(nwrap_initialized); \
221 static void nwrap_thread_prepare(void)
226 static void nwrap_thread_parent(void)
231 static void nwrap_thread_child(void)
236 enum nwrap_dbglvl_e {
244 # define NWRAP_LOG(...)
247 static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
248 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
250 static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
252 const char *format, ...)
257 unsigned int lvl = 0;
260 d = getenv("NSS_WRAPPER_DEBUGLEVEL");
265 va_start(va, format);
266 vsnprintf(buffer, sizeof(buffer), format, va);
271 case NWRAP_LOG_ERROR:
273 "NWRAP_ERROR(%d) - %s: %s\n",
278 "NWRAP_WARN(%d) - %s: %s\n",
281 case NWRAP_LOG_DEBUG:
283 "NWRAP_DEBUG(%d) - %s: %s\n",
286 case NWRAP_LOG_TRACE:
288 "NWRAP_TRACE(%d) - %s: %s\n",
294 #endif /* NDEBUG NWRAP_LOG */
296 struct nwrap_libc_fns {
297 struct passwd *(*_libc_getpwnam)(const char *name);
298 int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
299 char *buf, size_t buflen, struct passwd **result);
300 struct passwd *(*_libc_getpwuid)(uid_t uid);
301 int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
302 void (*_libc_setpwent)(void);
303 struct passwd *(*_libc_getpwent)(void);
304 #ifdef HAVE_GETPWENT_R
305 # ifdef HAVE_SOLARIS_GETPWENT_R
306 struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
307 # else /* HAVE_SOLARIS_GETPWENT_R */
308 int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
309 # endif /* HAVE_SOLARIS_GETPWENT_R */
310 #endif /* HAVE_GETPWENT_R */
311 void (*_libc_endpwent)(void);
312 int (*_libc_initgroups)(const char *user, gid_t gid);
313 struct group *(*_libc_getgrnam)(const char *name);
314 int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
315 struct group *(*_libc_getgrgid)(gid_t gid);
316 int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
317 void (*_libc_setgrent)(void);
318 struct group *(*_libc_getgrent)(void);
319 #ifdef HAVE_GETGRENT_R
320 # ifdef HAVE_SOLARIS_GETGRENT_R
321 struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
322 # else /* HAVE_SOLARIS_GETGRENT_R */
323 int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
324 # endif /* HAVE_SOLARIS_GETGRENT_R */
325 #endif /* HAVE_GETGRENT_R */
326 void (*_libc_endgrent)(void);
327 int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
329 void (*_libc_sethostent)(int stayopen);
330 struct hostent *(*_libc_gethostent)(void);
331 void (*_libc_endhostent)(void);
333 struct hostent *(*_libc_gethostbyname)(const char *name);
334 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
335 struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
337 struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
339 int (*_libc_getaddrinfo)(const char *node, const char *service,
340 const struct addrinfo *hints,
341 struct addrinfo **res);
342 int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
343 char *host, size_t hostlen,
344 char *serv, size_t servlen,
346 int (*_libc_gethostname)(char *name, size_t len);
347 #ifdef HAVE_GETHOSTBYNAME_R
348 int (*_libc_gethostbyname_r)(const char *name,
350 char *buf, size_t buflen,
351 struct hostent **result, int *h_errnop);
353 #ifdef HAVE_GETHOSTBYADDR_R
354 int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
356 char *buf, size_t buflen,
357 struct hostent **result, int *h_errnop);
361 struct nwrap_module_nss_fns {
362 NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer,
363 size_t buflen, int *errnop);
364 NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer,
365 size_t buflen, int *errnop);
366 NSS_STATUS (*_nss_setpwent)(void);
367 NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer,
368 size_t buflen, int *errnop);
369 NSS_STATUS (*_nss_endpwent)(void);
370 NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start,
371 long int *size, gid_t **groups, long int limit, int *errnop);
372 NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer,
373 size_t buflen, int *errnop);
374 NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer,
375 size_t buflen, int *errnop);
376 NSS_STATUS (*_nss_setgrent)(void);
377 NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer,
378 size_t buflen, int *errnop);
379 NSS_STATUS (*_nss_endgrent)(void);
382 struct nwrap_backend {
386 struct nwrap_ops *ops;
387 struct nwrap_module_nss_fns *fns;
391 struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
393 int (*nw_getpwnam_r)(struct nwrap_backend *b,
394 const char *name, struct passwd *pwdst,
395 char *buf, size_t buflen, struct passwd **pwdstp);
396 struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
398 int (*nw_getpwuid_r)(struct nwrap_backend *b,
399 uid_t uid, struct passwd *pwdst,
400 char *buf, size_t buflen, struct passwd **pwdstp);
401 void (*nw_setpwent)(struct nwrap_backend *b);
402 struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
403 int (*nw_getpwent_r)(struct nwrap_backend *b,
404 struct passwd *pwdst, char *buf,
405 size_t buflen, struct passwd **pwdstp);
406 void (*nw_endpwent)(struct nwrap_backend *b);
407 int (*nw_initgroups)(struct nwrap_backend *b,
408 const char *user, gid_t group);
409 struct group * (*nw_getgrnam)(struct nwrap_backend *b,
411 int (*nw_getgrnam_r)(struct nwrap_backend *b,
412 const char *name, struct group *grdst,
413 char *buf, size_t buflen, struct group **grdstp);
414 struct group * (*nw_getgrgid)(struct nwrap_backend *b,
416 int (*nw_getgrgid_r)(struct nwrap_backend *b,
417 gid_t gid, struct group *grdst,
418 char *buf, size_t buflen, struct group **grdstp);
419 void (*nw_setgrent)(struct nwrap_backend *b);
420 struct group * (*nw_getgrent)(struct nwrap_backend *b);
421 int (*nw_getgrent_r)(struct nwrap_backend *b,
422 struct group *grdst, char *buf,
423 size_t buflen, struct group **grdstp);
424 void (*nw_endgrent)(struct nwrap_backend *b);
427 /* Public prototypes */
429 bool nss_wrapper_enabled(void);
430 bool nss_wrapper_shadow_enabled(void);
431 bool nss_wrapper_hosts_enabled(void);
433 /* prototypes for files backend */
436 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
438 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
439 const char *name, struct passwd *pwdst,
440 char *buf, size_t buflen, struct passwd **pwdstp);
441 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
443 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
444 uid_t uid, struct passwd *pwdst,
445 char *buf, size_t buflen, struct passwd **pwdstp);
446 static void nwrap_files_setpwent(struct nwrap_backend *b);
447 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
448 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
449 struct passwd *pwdst, char *buf,
450 size_t buflen, struct passwd **pwdstp);
451 static void nwrap_files_endpwent(struct nwrap_backend *b);
452 static int nwrap_files_initgroups(struct nwrap_backend *b,
453 const char *user, gid_t group);
454 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
456 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
457 const char *name, struct group *grdst,
458 char *buf, size_t buflen, struct group **grdstp);
459 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
461 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
462 gid_t gid, struct group *grdst,
463 char *buf, size_t buflen, struct group **grdstp);
464 static void nwrap_files_setgrent(struct nwrap_backend *b);
465 static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
466 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
467 struct group *grdst, char *buf,
468 size_t buflen, struct group **grdstp);
469 static void nwrap_files_endgrent(struct nwrap_backend *b);
471 /* prototypes for module backend */
473 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
474 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
475 struct passwd *pwdst, char *buf,
476 size_t buflen, struct passwd **pwdstp);
477 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
479 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
480 const char *name, struct passwd *pwdst,
481 char *buf, size_t buflen, struct passwd **pwdstp);
482 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
484 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
485 uid_t uid, struct passwd *pwdst,
486 char *buf, size_t buflen, struct passwd **pwdstp);
487 static void nwrap_module_setpwent(struct nwrap_backend *b);
488 static void nwrap_module_endpwent(struct nwrap_backend *b);
489 static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
490 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
491 struct group *grdst, char *buf,
492 size_t buflen, struct group **grdstp);
493 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
495 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
496 const char *name, struct group *grdst,
497 char *buf, size_t buflen, struct group **grdstp);
498 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
500 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
501 gid_t gid, struct group *grdst,
502 char *buf, size_t buflen, struct group **grdstp);
503 static void nwrap_module_setgrent(struct nwrap_backend *b);
504 static void nwrap_module_endgrent(struct nwrap_backend *b);
505 static int nwrap_module_initgroups(struct nwrap_backend *b,
506 const char *user, gid_t group);
508 struct nwrap_ops nwrap_files_ops = {
509 .nw_getpwnam = nwrap_files_getpwnam,
510 .nw_getpwnam_r = nwrap_files_getpwnam_r,
511 .nw_getpwuid = nwrap_files_getpwuid,
512 .nw_getpwuid_r = nwrap_files_getpwuid_r,
513 .nw_setpwent = nwrap_files_setpwent,
514 .nw_getpwent = nwrap_files_getpwent,
515 .nw_getpwent_r = nwrap_files_getpwent_r,
516 .nw_endpwent = nwrap_files_endpwent,
517 .nw_initgroups = nwrap_files_initgroups,
518 .nw_getgrnam = nwrap_files_getgrnam,
519 .nw_getgrnam_r = nwrap_files_getgrnam_r,
520 .nw_getgrgid = nwrap_files_getgrgid,
521 .nw_getgrgid_r = nwrap_files_getgrgid_r,
522 .nw_setgrent = nwrap_files_setgrent,
523 .nw_getgrent = nwrap_files_getgrent,
524 .nw_getgrent_r = nwrap_files_getgrent_r,
525 .nw_endgrent = nwrap_files_endgrent,
528 struct nwrap_ops nwrap_module_ops = {
529 .nw_getpwnam = nwrap_module_getpwnam,
530 .nw_getpwnam_r = nwrap_module_getpwnam_r,
531 .nw_getpwuid = nwrap_module_getpwuid,
532 .nw_getpwuid_r = nwrap_module_getpwuid_r,
533 .nw_setpwent = nwrap_module_setpwent,
534 .nw_getpwent = nwrap_module_getpwent,
535 .nw_getpwent_r = nwrap_module_getpwent_r,
536 .nw_endpwent = nwrap_module_endpwent,
537 .nw_initgroups = nwrap_module_initgroups,
538 .nw_getgrnam = nwrap_module_getgrnam,
539 .nw_getgrnam_r = nwrap_module_getgrnam_r,
540 .nw_getgrgid = nwrap_module_getgrgid,
541 .nw_getgrgid_r = nwrap_module_getgrgid_r,
542 .nw_setgrent = nwrap_module_setgrent,
543 .nw_getgrent = nwrap_module_getgrent,
544 .nw_getgrent_r = nwrap_module_getgrent_r,
545 .nw_endgrent = nwrap_module_endgrent,
552 struct nwrap_libc_fns *fns;
557 struct nwrap_backend *backends;
558 struct nwrap_libc *libc;
561 static struct nwrap_main *nwrap_main_global;
562 static struct nwrap_main __nwrap_main_global;
567 static int nwrap_convert_he_ai(const struct hostent *he,
569 const struct addrinfo *hints,
570 struct addrinfo **pai,
571 bool skip_canonname);
577 #define DEFAULT_VECTOR_CAPACITY 16
579 struct nwrap_vector {
585 /* Macro returns pointer to first element of vector->items array.
587 * nwrap_vector is used as a memory backend which take care of
588 * memory allocations and other stuff like memory growing.
589 * nwrap_vectors should not be considered as some abstract structures.
590 * On this level, vectors are more handy than direct realloc/malloc
593 * nwrap_vector->items is array inside nwrap_vector which can be
594 * directly pointed by libc structure assembled by cwrap itself.
598 * 1) struct hostent contains char **h_addr_list element.
599 * 2) nwrap_vector holds array of pointers to addresses.
600 * It's easier to use vector to store results of
603 * Now, pretend that cwrap assembled struct hostent and
604 * we need to set h_addr_list to point to nwrap_vector.
605 * Idea behind is to shield users from internal nwrap_vector
607 * (Yes, not fully - array terminated by NULL is needed because
608 * it's result expected by libc function caller.)
614 * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
615 * ... don't care about failed allocation now ...
617 * ... fill nwrap vector ...
620 * he.h_addr_list = nwrap_vector_head(vector);
623 #define nwrap_vector_head(vect) ((void *)((vect)->items))
625 #define nwrap_vector_foreach(item, vect, iter) \
626 for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
628 (item) = (vect).items[++iter])
630 #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
632 static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
634 if (vector == NULL) {
638 /* count is initialized by ZERO_STRUCTP */
639 ZERO_STRUCTP(vector);
640 vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
641 if (vector->items == NULL) {
644 vector->capacity = DEFAULT_VECTOR_CAPACITY;
645 memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
650 static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
652 assert (vector != NULL);
654 if (vector->items == NULL) {
655 nwrap_vector_init(vector);
658 if (vector->count == vector->capacity) {
659 /* Items array _MUST_ be NULL terminated because it's passed
660 * as result to caller which expect NULL terminated array from libc.
662 void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
666 vector->items = items;
668 /* Don't count ending NULL to capacity */
669 vector->capacity *= 2;
672 vector->items[vector->count] = item;
675 vector->items[vector->count] = NULL;
680 static bool nwrap_vector_merge(struct nwrap_vector *dst,
681 struct nwrap_vector *src)
683 void **dst_items = NULL;
686 if (src->count == 0) {
690 count = dst->count + src->count;
692 /* We don't need reallocation if we have enough capacity. */
693 if (src->count > (dst->capacity - dst->count)) {
694 dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
695 if (dst_items == NULL) {
698 dst->items = dst_items;
699 dst->capacity = count;
702 memcpy((void *)(((long *)dst->items) + dst->count),
704 src->count * sizeof(void *));
717 struct nwrap_vector lines;
719 bool (*parse_line)(struct nwrap_cache *, char *line);
720 void (*unload)(struct nwrap_cache *);
725 struct nwrap_cache *cache;
732 struct nwrap_cache __nwrap_cache_pw;
733 struct nwrap_pw nwrap_pw_global;
735 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
736 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
739 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
741 struct nwrap_cache *cache;
748 struct nwrap_cache __nwrap_cache_sp;
749 struct nwrap_sp nwrap_sp_global;
751 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
752 static void nwrap_sp_unload(struct nwrap_cache *nwrap);
753 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
757 struct nwrap_cache *cache;
764 struct nwrap_cache __nwrap_cache_gr;
765 struct nwrap_gr nwrap_gr_global;
768 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
769 static void nwrap_he_unload(struct nwrap_cache *nwrap);
771 struct nwrap_addrdata {
772 unsigned char host_addr[16]; /* IPv4 or IPv6 address */
775 static size_t max_hostents = 100;
777 struct nwrap_entdata {
778 struct nwrap_addrdata addr;
781 struct nwrap_vector nwrap_addrdata;
783 ssize_t aliases_count;
786 struct nwrap_entlist {
787 struct nwrap_entlist *next;
788 struct nwrap_entdata *ed;
792 struct nwrap_cache *cache;
794 struct nwrap_vector entries;
795 struct nwrap_vector lists;
801 static struct nwrap_cache __nwrap_cache_he;
802 static struct nwrap_he nwrap_he_global;
805 /*********************************************************
807 *********************************************************/
809 static void nwrap_init(void);
810 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
811 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
812 void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
813 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
815 /*********************************************************
816 * NWRAP LIBC LOADER FUNCTIONS
817 *********************************************************/
826 static const char *nwrap_str_lib(enum nwrap_lib lib)
833 case NWRAP_LIBSOCKET:
837 /* Compiler would warn us about unhandled enum value if we get here */
842 static void *nwrap_load_lib_handle(enum nwrap_lib lib)
844 int flags = RTLD_LAZY;
849 flags |= RTLD_DEEPBIND;
855 handle = nwrap_main_global->libc->nsl_handle;
856 if (handle == NULL) {
857 for (i = 10; i >= 0; i--) {
858 char soname[256] = {0};
860 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
861 handle = dlopen(soname, flags);
862 if (handle != NULL) {
867 nwrap_main_global->libc->nsl_handle = handle;
872 case NWRAP_LIBSOCKET:
873 #ifdef HAVE_LIBSOCKET
874 handle = nwrap_main_global->libc->sock_handle;
875 if (handle == NULL) {
876 for (i = 10; i >= 0; i--) {
877 char soname[256] = {0};
879 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
880 handle = dlopen(soname, flags);
881 if (handle != NULL) {
886 nwrap_main_global->libc->sock_handle = handle;
892 handle = nwrap_main_global->libc->handle;
893 if (handle == NULL) {
894 for (i = 10; i >= 0; i--) {
895 char soname[256] = {0};
897 snprintf(soname, sizeof(soname), "libc.so.%d", i);
898 handle = dlopen(soname, flags);
899 if (handle != NULL) {
904 nwrap_main_global->libc->handle = handle;
909 if (handle == NULL) {
911 handle = nwrap_main_global->libc->handle
912 = nwrap_main_global->libc->sock_handle
913 = nwrap_main_global->libc->nsl_handle
916 NWRAP_LOG(NWRAP_LOG_ERROR,
917 "Failed to dlopen library: %s\n",
926 static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
933 handle = nwrap_load_lib_handle(lib);
935 func = dlsym(handle, fn_name);
937 NWRAP_LOG(NWRAP_LOG_ERROR,
938 "Failed to find %s: %s\n",
943 NWRAP_LOG(NWRAP_LOG_TRACE,
945 fn_name, nwrap_str_lib(lib));
949 #define nwrap_load_lib_function(lib, fn_name) \
950 if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
951 *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
952 _nwrap_load_lib_function(lib, #fn_name); \
955 /* INTERNAL HELPER FUNCTIONS */
956 static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
960 nwrap_vector_foreach(item, nwrap->lines, p) {
961 /* Maybe some vectors were merged ... */
964 SAFE_FREE(nwrap->lines.items);
965 ZERO_STRUCTP(&nwrap->lines);
971 * Functions expeciall from libc need to be loaded individually, you can't load
972 * all at once or gdb will segfault at startup. The same applies to valgrind and
973 * has probably something todo with with the linker.
974 * So we need load each function at the point it is called the first time.
976 static struct passwd *libc_getpwnam(const char *name)
978 nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
980 return nwrap_main_global->libc->fns->_libc_getpwnam(name);
983 #ifdef HAVE_GETPWNAM_R
984 static int libc_getpwnam_r(const char *name,
988 struct passwd **result)
990 #ifdef HAVE___POSIX_GETPWNAM_R
991 if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
992 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
993 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
996 nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
999 return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
1007 static struct passwd *libc_getpwuid(uid_t uid)
1009 nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
1011 return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
1014 #ifdef HAVE_GETPWUID_R
1015 static int libc_getpwuid_r(uid_t uid,
1019 struct passwd **result)
1021 #ifdef HAVE___POSIX_GETPWUID_R
1022 if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
1023 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
1024 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
1027 nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
1030 return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
1038 static inline void str_tolower(char *dst, char *src)
1040 register char *src_tmp = src;
1041 register char *dst_tmp = dst;
1043 while (*src_tmp != '\0') {
1044 *dst_tmp = tolower(*src_tmp);
1050 static bool str_tolower_copy(char **dst_name, const char *const src_name)
1054 if ((dst_name == NULL) || (src_name == NULL)) {
1058 h_name_lower = strdup(src_name);
1059 if (h_name_lower == NULL) {
1060 NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
1064 str_tolower(h_name_lower, h_name_lower);
1065 *dst_name = h_name_lower;
1069 static void libc_setpwent(void)
1071 nwrap_load_lib_function(NWRAP_LIBC, setpwent);
1073 nwrap_main_global->libc->fns->_libc_setpwent();
1076 static struct passwd *libc_getpwent(void)
1078 nwrap_load_lib_function(NWRAP_LIBC, getpwent);
1080 return nwrap_main_global->libc->fns->_libc_getpwent();
1083 #ifdef HAVE_GETPWENT_R
1084 # ifdef HAVE_SOLARIS_GETPWENT_R
1085 static struct passwd *libc_getpwent_r(struct passwd *pwdst,
1089 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
1091 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
1095 # else /* HAVE_SOLARIS_GETPWENT_R */
1096 static int libc_getpwent_r(struct passwd *pwdst,
1099 struct passwd **pwdstp)
1101 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
1103 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
1108 # endif /* HAVE_SOLARIS_GETPWENT_R */
1109 #endif /* HAVE_GETPWENT_R */
1111 static void libc_endpwent(void)
1113 nwrap_load_lib_function(NWRAP_LIBC, endpwent);
1115 nwrap_main_global->libc->fns->_libc_endpwent();
1118 static int libc_initgroups(const char *user, gid_t gid)
1120 nwrap_load_lib_function(NWRAP_LIBC, initgroups);
1122 return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
1125 static struct group *libc_getgrnam(const char *name)
1127 nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
1129 return nwrap_main_global->libc->fns->_libc_getgrnam(name);
1132 #ifdef HAVE_GETGRNAM_R
1133 static int libc_getgrnam_r(const char *name,
1137 struct group **result)
1139 #ifdef HAVE___POSIX_GETGRNAM_R
1140 if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
1141 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
1142 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
1145 nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
1148 return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
1156 static struct group *libc_getgrgid(gid_t gid)
1158 nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
1160 return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
1163 #ifdef HAVE_GETGRGID_R
1164 static int libc_getgrgid_r(gid_t gid,
1168 struct group **result)
1170 #ifdef HAVE___POSIX_GETGRGID_R
1171 if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
1172 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
1173 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
1176 nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
1179 return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
1187 static void libc_setgrent(void)
1189 nwrap_load_lib_function(NWRAP_LIBC, setgrent);
1191 nwrap_main_global->libc->fns->_libc_setgrent();
1194 static struct group *libc_getgrent(void)
1196 nwrap_load_lib_function(NWRAP_LIBC, getgrent);
1198 return nwrap_main_global->libc->fns->_libc_getgrent();
1201 #ifdef HAVE_GETGRENT_R
1202 # ifdef HAVE_SOLARIS_GETGRENT_R
1203 static struct group *libc_getgrent_r(struct group *group,
1207 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
1209 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
1213 # else /* HAVE_SOLARIS_GETGRENT_R */
1214 static int libc_getgrent_r(struct group *group,
1217 struct group **result)
1219 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
1221 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
1226 # endif /* HAVE_SOLARIS_GETGRENT_R */
1227 #endif /* HAVE_GETGRENT_R */
1229 static void libc_endgrent(void)
1231 nwrap_load_lib_function(NWRAP_LIBC, endgrent);
1233 nwrap_main_global->libc->fns->_libc_endgrent();
1236 #ifdef HAVE_GETGROUPLIST
1237 static int libc_getgrouplist(const char *user,
1242 nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
1244 return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
1251 static void libc_sethostent(int stayopen)
1253 nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
1255 nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
1258 static struct hostent *libc_gethostent(void)
1260 nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
1262 return nwrap_main_global->libc->fns->_libc_gethostent();
1265 static void libc_endhostent(void)
1267 nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
1269 nwrap_main_global->libc->fns->_libc_endhostent();
1272 static struct hostent *libc_gethostbyname(const char *name)
1274 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
1276 return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
1279 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1280 static struct hostent *libc_gethostbyname2(const char *name, int af)
1282 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
1284 return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
1288 static struct hostent *libc_gethostbyaddr(const void *addr,
1292 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
1294 return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
1299 static int libc_gethostname(char *name, size_t len)
1301 nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
1303 return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
1306 #ifdef HAVE_GETHOSTBYNAME_R
1307 static int libc_gethostbyname_r(const char *name,
1308 struct hostent *ret,
1311 struct hostent **result,
1314 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
1316 return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
1325 #ifdef HAVE_GETHOSTBYADDR_R
1326 static int libc_gethostbyaddr_r(const void *addr,
1329 struct hostent *ret,
1332 struct hostent **result,
1335 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
1337 return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
1348 static int libc_getaddrinfo(const char *node,
1349 const char *service,
1350 const struct addrinfo *hints,
1351 struct addrinfo **res)
1353 nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
1355 return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
1361 static int libc_getnameinfo(const struct sockaddr *sa,
1369 nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
1371 return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
1380 /*********************************************************
1381 * NWRAP NSS MODULE LOADER FUNCTIONS
1382 *********************************************************/
1384 static void *nwrap_load_module_fn(struct nwrap_backend *b,
1385 const char *fn_name)
1390 if (!b->so_handle) {
1391 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
1395 if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
1396 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1400 res = dlsym(b->so_handle, s);
1402 NWRAP_LOG(NWRAP_LOG_ERROR,
1403 "Cannot find function %s in %s",
1410 static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b)
1412 struct nwrap_module_nss_fns *fns;
1414 if (!b->so_handle) {
1418 fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns));
1423 *(void **)(&fns->_nss_getpwnam_r) =
1424 nwrap_load_module_fn(b, "getpwnam_r");
1425 *(void **)(&fns->_nss_getpwuid_r) =
1426 nwrap_load_module_fn(b, "getpwuid_r");
1427 *(void **)(&fns->_nss_setpwent) =
1428 nwrap_load_module_fn(b, "setpwent");
1429 *(void **)(&fns->_nss_getpwent_r) =
1430 nwrap_load_module_fn(b, "getpwent_r");
1431 *(void **)(&fns->_nss_endpwent) =
1432 nwrap_load_module_fn(b, "endpwent");
1433 *(void **)(&fns->_nss_initgroups) =
1434 nwrap_load_module_fn(b, "initgroups_dyn");
1435 *(void **)(&fns->_nss_getgrnam_r) =
1436 nwrap_load_module_fn(b, "getgrnam_r");
1437 *(void **)(&fns->_nss_getgrgid_r)=
1438 nwrap_load_module_fn(b, "getgrgid_r");
1439 *(void **)(&fns->_nss_setgrent) =
1440 nwrap_load_module_fn(b, "setgrent");
1441 *(void **)(&fns->_nss_getgrent_r) =
1442 nwrap_load_module_fn(b, "getgrent_r");
1443 *(void **)(&fns->_nss_endgrent) =
1444 nwrap_load_module_fn(b, "endgrent");
1449 static void *nwrap_load_module(const char *so_path)
1453 if (!so_path || !strlen(so_path)) {
1457 h = dlopen(so_path, RTLD_LAZY);
1459 NWRAP_LOG(NWRAP_LOG_ERROR,
1460 "Cannot open shared library %s",
1468 static bool nwrap_module_init(const char *name,
1469 struct nwrap_ops *ops,
1470 const char *so_path,
1472 struct nwrap_backend **backends)
1474 struct nwrap_backend *b;
1476 *backends = (struct nwrap_backend *)realloc(*backends,
1477 sizeof(struct nwrap_backend) * ((*num_backends) + 1));
1479 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1483 b = &((*backends)[*num_backends]);
1487 b->so_path = so_path;
1489 if (so_path != NULL) {
1490 b->so_handle = nwrap_load_module(so_path);
1491 b->fns = nwrap_load_module_fns(b);
1492 if (b->fns == NULL) {
1496 b->so_handle = NULL;
1505 static void nwrap_libc_init(struct nwrap_main *r)
1507 r->libc = malloc(sizeof(struct nwrap_libc));
1508 if (r->libc == NULL) {
1509 printf("Failed to allocate memory for libc");
1512 ZERO_STRUCTP(r->libc);
1514 r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
1515 if (r->libc->fns == NULL) {
1516 printf("Failed to allocate memory for libc functions");
1519 ZERO_STRUCTP(r->libc->fns);
1522 static void nwrap_backend_init(struct nwrap_main *r)
1524 const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
1525 const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1527 r->num_backends = 0;
1530 if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
1533 NWRAP_LOG(NWRAP_LOG_ERROR,
1534 "Failed to initialize 'files' backend");
1538 if (module_so_path != NULL &&
1539 module_so_path[0] != '\0' &&
1540 module_fn_name != NULL &&
1541 module_fn_name[0] != '\0') {
1542 if (!nwrap_module_init(module_fn_name,
1547 NWRAP_LOG(NWRAP_LOG_ERROR,
1548 "Failed to initialize '%s' backend",
1555 static void nwrap_init(void)
1559 size_t max_hostents_tmp;
1561 NWRAP_LOCK(nwrap_initialized);
1562 if (nwrap_initialized) {
1563 NWRAP_UNLOCK(nwrap_initialized);
1568 * Still holding nwrap_initialized lock here.
1569 * We don't use NWRAP_(UN)LOCK_ALL macros here because we
1570 * want to avoid overhead when other threads do their job.
1572 NWRAP_LOCK(nwrap_global);
1573 NWRAP_LOCK(nwrap_gr_global);
1574 NWRAP_LOCK(nwrap_he_global);
1575 NWRAP_LOCK(nwrap_pw_global);
1576 NWRAP_LOCK(nwrap_sp_global);
1578 nwrap_initialized = true;
1580 env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
1582 max_hostents_tmp = (size_t)strtoul(env, &endptr, 10);
1583 if ((*env == '\0') ||
1584 (*endptr != '\0') ||
1585 (max_hostents_tmp == 0)) {
1586 NWRAP_LOG(NWRAP_LOG_DEBUG,
1587 "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
1588 "value or value is too small. "
1589 "Using default value: %lu.",
1590 (unsigned long)max_hostents);
1592 max_hostents = max_hostents_tmp;
1595 /* Initialize hash table */
1596 NWRAP_LOG(NWRAP_LOG_DEBUG,
1597 "Initializing hash table of size %lu items.",
1598 (unsigned long)max_hostents);
1599 if (hcreate(max_hostents) == 0) {
1600 NWRAP_LOG(NWRAP_LOG_ERROR,
1601 "Failed to initialize hash table");
1605 nwrap_main_global = &__nwrap_main_global;
1607 nwrap_libc_init(nwrap_main_global);
1609 nwrap_backend_init(nwrap_main_global);
1612 nwrap_pw_global.cache = &__nwrap_cache_pw;
1614 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
1615 nwrap_pw_global.cache->fp = NULL;
1616 nwrap_pw_global.cache->fd = -1;
1617 nwrap_pw_global.cache->private_data = &nwrap_pw_global;
1618 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
1619 nwrap_pw_global.cache->unload = nwrap_pw_unload;
1622 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1623 nwrap_sp_global.cache = &__nwrap_cache_sp;
1625 nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
1626 nwrap_sp_global.cache->fp = NULL;
1627 nwrap_sp_global.cache->fd = -1;
1628 nwrap_sp_global.cache->private_data = &nwrap_sp_global;
1629 nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
1630 nwrap_sp_global.cache->unload = nwrap_sp_unload;
1631 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1634 nwrap_gr_global.cache = &__nwrap_cache_gr;
1636 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
1637 nwrap_gr_global.cache->fp = NULL;
1638 nwrap_gr_global.cache->fd = -1;
1639 nwrap_gr_global.cache->private_data = &nwrap_gr_global;
1640 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
1641 nwrap_gr_global.cache->unload = nwrap_gr_unload;
1644 nwrap_he_global.cache = &__nwrap_cache_he;
1646 nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
1647 nwrap_he_global.cache->fp = NULL;
1648 nwrap_he_global.cache->fd = -1;
1649 nwrap_he_global.cache->private_data = &nwrap_he_global;
1650 nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
1651 nwrap_he_global.cache->unload = nwrap_he_unload;
1654 /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
1658 bool nss_wrapper_enabled(void)
1662 if (nwrap_pw_global.cache->path == NULL ||
1663 nwrap_pw_global.cache->path[0] == '\0') {
1666 if (nwrap_gr_global.cache->path == NULL ||
1667 nwrap_gr_global.cache->path[0] == '\0') {
1674 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1675 bool nss_wrapper_shadow_enabled(void)
1679 if (nwrap_sp_global.cache->path == NULL ||
1680 nwrap_sp_global.cache->path[0] == '\0') {
1686 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1688 bool nss_wrapper_hosts_enabled(void)
1692 if (nwrap_he_global.cache->path == NULL ||
1693 nwrap_he_global.cache->path[0] == '\0') {
1700 static bool nwrap_hostname_enabled(void)
1704 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
1711 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
1715 /* Unused but getline needs it */
1719 if (nwrap->st.st_size == 0) {
1720 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
1724 /* Support for 32-bit system I guess */
1725 if (nwrap->st.st_size > INT32_MAX) {
1726 NWRAP_LOG(NWRAP_LOG_ERROR,
1727 "Size[%u] larger than INT32_MAX",
1728 (unsigned)nwrap->st.st_size);
1735 n = getline(&line, &len, nwrap->fp);
1738 if (feof(nwrap->fp)) {
1742 NWRAP_LOG(NWRAP_LOG_ERROR,
1743 "Unable to read line from file: %s",
1748 if (line[n - 1] == '\n') {
1752 if (line[0] == '\0') {
1757 ok = nwrap->parse_line(nwrap, line);
1759 NWRAP_LOG(NWRAP_LOG_ERROR,
1760 "Unable to parse line file: %s",
1766 /* Line is parsed without issues so add it to list */
1767 ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
1769 NWRAP_LOG(NWRAP_LOG_ERROR,
1770 "Unable to add line to vector");
1774 /* This forces getline to allocate new memory for line. */
1776 } while (!feof(nwrap->fp));
1781 static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
1783 nwrap->unload(nwrap);
1785 nwrap_lines_unload(nwrap);
1788 static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
1793 bool retried = false;
1795 assert(nwrap != NULL);
1798 if (nwrap->fd < 0) {
1799 nwrap->fp = fopen(nwrap->path, "re");
1800 if (nwrap->fp == NULL) {
1802 NWRAP_LOG(NWRAP_LOG_ERROR,
1803 "Unable to open '%s' readonly %d:%s",
1804 nwrap->path, nwrap->fd,
1809 nwrap->fd = fileno(nwrap->fp);
1810 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
1813 ret = fstat(nwrap->fd, &st);
1815 NWRAP_LOG(NWRAP_LOG_ERROR,
1816 "fstat(%s) - %d:%s",
1826 if (retried == false && st.st_nlink == 0) {
1827 /* maybe someone has replaced the file... */
1828 NWRAP_LOG(NWRAP_LOG_TRACE,
1829 "st_nlink == 0, reopen %s",
1832 memset(&nwrap->st, 0, sizeof(nwrap->st));
1839 if (st.st_mtime == nwrap->st.st_mtime) {
1840 NWRAP_LOG(NWRAP_LOG_TRACE,
1841 "st_mtime[%u] hasn't changed, skip reload",
1842 (unsigned)st.st_mtime);
1846 NWRAP_LOG(NWRAP_LOG_TRACE,
1847 "st_mtime has changed [%u] => [%u], start reload",
1848 (unsigned)st.st_mtime,
1849 (unsigned)nwrap->st.st_mtime);
1853 nwrap_files_cache_unload(nwrap);
1855 ok = nwrap_parse_file(nwrap);
1857 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
1858 nwrap_files_cache_unload(nwrap);
1862 NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
1867 * the caller has to call nwrap_unload() on failure
1869 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
1871 struct nwrap_pw *nwrap_pw;
1878 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1880 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
1881 pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
1883 NWRAP_LOG(NWRAP_LOG_ERROR,
1884 "realloc(%u) failed",
1885 (unsigned)list_size);
1888 nwrap_pw->list = pw;
1890 pw = &nwrap_pw->list[nwrap_pw->num];
1897 NWRAP_LOG(NWRAP_LOG_ERROR,
1898 "Invalid line[%s]: '%s'",
1908 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
1913 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1921 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
1926 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1932 pw->pw_uid = (uid_t)strtoul(c, &e, 10);
1934 NWRAP_LOG(NWRAP_LOG_ERROR,
1935 "Invalid line[%s]: '%s' - %s",
1936 line, c, strerror(errno));
1940 NWRAP_LOG(NWRAP_LOG_ERROR,
1941 "Invalid line[%s]: '%s' - %s",
1942 line, c, strerror(errno));
1946 NWRAP_LOG(NWRAP_LOG_ERROR,
1947 "Invalid line[%s]: '%s' - %s",
1948 line, c, strerror(errno));
1953 NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
1958 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1964 pw->pw_gid = (gid_t)strtoul(c, &e, 10);
1966 NWRAP_LOG(NWRAP_LOG_ERROR,
1967 "Invalid line[%s]: '%s' - %s",
1968 line, c, strerror(errno));
1972 NWRAP_LOG(NWRAP_LOG_ERROR,
1973 "Invalid line[%s]: '%s' - %s",
1974 line, c, strerror(errno));
1978 NWRAP_LOG(NWRAP_LOG_ERROR,
1979 "Invalid line[%s]: '%s' - %s",
1980 line, c, strerror(errno));
1985 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
1987 #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
1988 pw->pw_class = discard_const_p(char, "");
1990 NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class);
1991 #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
1993 #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
1996 NWRAP_LOG(NWRAP_LOG_TRACE,
1998 (unsigned long)pw->pw_change);
1999 #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
2001 #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
2004 NWRAP_LOG(NWRAP_LOG_TRACE,
2006 (unsigned long)pw->pw_expire);
2007 #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
2012 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
2020 NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
2025 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
2033 NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
2037 NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
2039 NWRAP_LOG(NWRAP_LOG_DEBUG,
2040 "Added user[%s:%s:%u:%u:%s:%s:%s]",
2041 pw->pw_name, pw->pw_passwd,
2042 pw->pw_uid, pw->pw_gid,
2043 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
2049 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
2051 struct nwrap_pw *nwrap_pw;
2052 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
2054 SAFE_FREE(nwrap_pw->list);
2059 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
2060 char *buf, size_t buflen, struct passwd **dstp)
2066 first = src->pw_name;
2068 last = src->pw_shell;
2069 while (*last) last++;
2071 ofs = PTR_DIFF(last + 1, first);
2073 if (ofs > (off_t) buflen) {
2077 memcpy(buf, first, ofs);
2079 ofs = PTR_DIFF(src->pw_name, first);
2080 dst->pw_name = buf + ofs;
2081 ofs = PTR_DIFF(src->pw_passwd, first);
2082 dst->pw_passwd = buf + ofs;
2083 dst->pw_uid = src->pw_uid;
2084 dst->pw_gid = src->pw_gid;
2085 ofs = PTR_DIFF(src->pw_gecos, first);
2086 dst->pw_gecos = buf + ofs;
2087 ofs = PTR_DIFF(src->pw_dir, first);
2088 dst->pw_dir = buf + ofs;
2089 ofs = PTR_DIFF(src->pw_shell, first);
2090 dst->pw_shell = buf + ofs;
2099 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2100 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
2102 struct nwrap_sp *nwrap_sp;
2109 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
2111 list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
2112 sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
2114 NWRAP_LOG(NWRAP_LOG_ERROR,
2115 "realloc(%u) failed",
2116 (unsigned)list_size);
2119 nwrap_sp->list = sp;
2121 sp = &nwrap_sp->list[nwrap_sp->num];
2128 NWRAP_LOG(NWRAP_LOG_ERROR,
2129 "name -- Invalid line[%s]: '%s'",
2139 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
2144 NWRAP_LOG(NWRAP_LOG_ERROR,
2145 "pwd -- Invalid line[%s]: '%s'",
2162 NWRAP_LOG(NWRAP_LOG_ERROR,
2163 "lstchg -- Invalid line[%s]: '%s'",
2170 sp->sp_lstchg = strtol(c, &e, 10);
2172 NWRAP_LOG(NWRAP_LOG_ERROR,
2173 "lstchg -- Invalid line[%s]: '%s' - %s",
2174 line, c, strerror(errno));
2178 NWRAP_LOG(NWRAP_LOG_ERROR,
2179 "lstchg -- Invalid line[%s]: '%s' - %s",
2180 line, c, strerror(errno));
2184 NWRAP_LOG(NWRAP_LOG_ERROR,
2185 "lstchg -- Invalid line[%s]: '%s' - %s",
2186 line, c, strerror(errno));
2199 NWRAP_LOG(NWRAP_LOG_ERROR,
2200 "min -- Invalid line[%s]: '%s'",
2207 sp->sp_min = strtol(c, &e, 10);
2209 NWRAP_LOG(NWRAP_LOG_ERROR,
2210 "min -- Invalid line[%s]: '%s' - %s",
2211 line, c, strerror(errno));
2215 NWRAP_LOG(NWRAP_LOG_ERROR,
2216 "min -- Invalid line[%s]: '%s' - %s",
2217 line, c, strerror(errno));
2221 NWRAP_LOG(NWRAP_LOG_ERROR,
2222 "min -- Invalid line[%s]: '%s' - %s",
2223 line, c, strerror(errno));
2236 NWRAP_LOG(NWRAP_LOG_ERROR,
2237 "max -- Invalid line[%s]: '%s'",
2244 sp->sp_max = strtol(c, &e, 10);
2246 NWRAP_LOG(NWRAP_LOG_ERROR,
2247 "max -- Invalid line[%s]: '%s' - %s",
2248 line, c, strerror(errno));
2252 NWRAP_LOG(NWRAP_LOG_ERROR,
2253 "max -- Invalid line[%s]: '%s' - %s",
2254 line, c, strerror(errno));
2258 NWRAP_LOG(NWRAP_LOG_ERROR,
2259 "max -- Invalid line[%s]: '%s' - %s",
2260 line, c, strerror(errno));
2273 NWRAP_LOG(NWRAP_LOG_ERROR,
2274 "warn -- Invalid line[%s]: '%s'",
2281 sp->sp_warn = strtol(c, &e, 10);
2283 NWRAP_LOG(NWRAP_LOG_ERROR,
2284 "warn -- Invalid line[%s]: '%s' - %s",
2285 line, c, strerror(errno));
2289 NWRAP_LOG(NWRAP_LOG_ERROR,
2290 "warn -- Invalid line[%s]: '%s' - %s",
2291 line, c, strerror(errno));
2295 NWRAP_LOG(NWRAP_LOG_ERROR,
2296 "warn -- Invalid line[%s]: '%s' - %s",
2297 line, c, strerror(errno));
2310 NWRAP_LOG(NWRAP_LOG_ERROR,
2311 "inact -- Invalid line[%s]: '%s'",
2318 sp->sp_inact = strtol(c, &e, 10);
2320 NWRAP_LOG(NWRAP_LOG_ERROR,
2321 "inact -- Invalid line[%s]: '%s' - %s",
2322 line, c, strerror(errno));
2326 NWRAP_LOG(NWRAP_LOG_ERROR,
2327 "inact -- Invalid line[%s]: '%s' - %s",
2328 line, c, strerror(errno));
2332 NWRAP_LOG(NWRAP_LOG_ERROR,
2333 "inact -- Invalid line[%s]: '%s' - %s",
2334 line, c, strerror(errno));
2347 NWRAP_LOG(NWRAP_LOG_ERROR,
2348 "expire -- Invalid line[%s]: '%s'",
2355 sp->sp_expire = strtol(c, &e, 10);
2357 NWRAP_LOG(NWRAP_LOG_ERROR,
2358 "expire -- Invalid line[%s]: '%s' - %s",
2359 line, c, strerror(errno));
2363 NWRAP_LOG(NWRAP_LOG_ERROR,
2364 "expire -- Invalid line[%s]: '%s' - %s",
2365 line, c, strerror(errno));
2369 NWRAP_LOG(NWRAP_LOG_ERROR,
2370 "expire -- Invalid line[%s]: '%s' - %s",
2371 line, c, strerror(errno));
2381 static void nwrap_sp_unload(struct nwrap_cache *nwrap)
2383 struct nwrap_sp *nwrap_sp;
2384 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
2386 SAFE_FREE(nwrap_sp->list);
2390 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2393 * the caller has to call nwrap_unload() on failure
2395 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
2397 struct nwrap_gr *nwrap_gr;
2405 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2407 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
2408 gr = (struct group *)realloc(nwrap_gr->list, list_size);
2410 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
2413 nwrap_gr->list = gr;
2415 gr = &nwrap_gr->list[nwrap_gr->num];
2422 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2430 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
2435 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2443 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
2448 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2454 gr->gr_gid = (gid_t)strtoul(c, &e, 10);
2456 NWRAP_LOG(NWRAP_LOG_ERROR,
2457 "Invalid line[%s]: '%s' - %s",
2458 line, c, strerror(errno));
2462 NWRAP_LOG(NWRAP_LOG_ERROR,
2463 "Invalid line[%s]: '%s' - %s",
2464 line, c, strerror(errno));
2468 NWRAP_LOG(NWRAP_LOG_ERROR,
2469 "Invalid line[%s]: '%s' - %s",
2470 line, c, strerror(errno));
2475 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
2478 gr->gr_mem = (char **)malloc(sizeof(char *));
2480 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
2483 gr->gr_mem[0] = NULL;
2485 for(nummem=0; p; nummem++) {
2495 if (strlen(c) == 0) {
2499 m_size = sizeof(char *) * (nummem+2);
2500 m = (char **)realloc(gr->gr_mem, m_size);
2502 NWRAP_LOG(NWRAP_LOG_ERROR,
2503 "realloc(%zd) failed",
2508 gr->gr_mem[nummem] = c;
2509 gr->gr_mem[nummem+1] = NULL;
2511 NWRAP_LOG(NWRAP_LOG_TRACE,
2513 nummem, gr->gr_mem[nummem]);
2516 NWRAP_LOG(NWRAP_LOG_DEBUG,
2517 "Added group[%s:%s:%u:] with %u members",
2518 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
2524 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
2527 struct nwrap_gr *nwrap_gr;
2528 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2530 if (nwrap_gr->list) {
2531 for (i=0; i < nwrap_gr->num; i++) {
2532 SAFE_FREE(nwrap_gr->list[i].gr_mem);
2534 SAFE_FREE(nwrap_gr->list);
2541 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
2542 char *buf, size_t buflen, struct group **dstp)
2552 first = src->gr_name;
2554 lastm = src->gr_mem;
2561 last = src->gr_passwd;
2563 while (*last) last++;
2565 ofsb = PTR_DIFF(last + 1, first);
2566 ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
2568 if ((ofsb + ofsm) > (off_t) buflen) {
2572 memcpy(buf, first, ofsb);
2573 memcpy(buf + ofsb, src->gr_mem, ofsm);
2575 ofs = PTR_DIFF(src->gr_name, first);
2576 dst->gr_name = buf + ofs;
2577 ofs = PTR_DIFF(src->gr_passwd, first);
2578 dst->gr_passwd = buf + ofs;
2579 dst->gr_gid = src->gr_gid;
2581 dst->gr_mem = (char **)(buf + ofsb);
2582 for (i=0; src->gr_mem[i]; i++) {
2583 ofs = PTR_DIFF(src->gr_mem[i], first);
2584 dst->gr_mem[i] = buf + ofs;
2594 static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
2596 struct nwrap_entlist *el;
2599 NWRAP_LOG(NWRAP_LOG_ERROR,
2600 "entry is NULL, can't create list item");
2604 el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
2606 NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
2616 static bool nwrap_ed_inventarize_add_new(char *const h_name,
2617 struct nwrap_entdata *const ed)
2621 struct nwrap_entlist *el;
2624 if (h_name == NULL) {
2625 NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
2629 el = nwrap_entlist_init(ed);
2635 e.data = (void *)el;
2637 p = hsearch(e, ENTER);
2639 NWRAP_LOG(NWRAP_LOG_ERROR,
2640 "Hash table is full (%s)!",
2645 ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
2647 NWRAP_LOG(NWRAP_LOG_ERROR,
2648 "Failed to add list entry to vector.");
2655 static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
2656 struct nwrap_entlist *const el)
2658 struct nwrap_entlist *cursor;
2659 struct nwrap_entlist *el_new;
2662 NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
2667 for (cursor = el; cursor->next != NULL; cursor = cursor->next)
2669 if (cursor->ed == ed) {
2670 /* The entry already exists in this list. */
2675 if (cursor->ed == ed) {
2676 /* The entry already exists in this list. */
2680 el_new = nwrap_entlist_init(ed);
2681 if (el_new == NULL) {
2685 cursor->next = el_new;
2689 static bool nwrap_ed_inventarize(char *const name,
2690 struct nwrap_entdata *const ed)
2699 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
2701 p = hsearch(e, FIND);
2703 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
2704 ok = nwrap_ed_inventarize_add_new(name, ed);
2706 struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
2708 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
2709 ok = nwrap_ed_inventarize_add_to_existing(ed, el);
2715 static bool nwrap_add_hname(struct nwrap_entdata *const ed)
2717 char *const h_name = (char *const)(ed->ht.h_name);
2721 ok = nwrap_ed_inventarize(h_name, ed);
2726 if (ed->ht.h_aliases == NULL) {
2730 /* Itemize aliases */
2731 for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
2734 h_name_alias = ed->ht.h_aliases[i];
2736 NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
2738 if (!nwrap_ed_inventarize(h_name_alias, ed)) {
2739 NWRAP_LOG(NWRAP_LOG_ERROR,
2740 "Unable to add alias: %s", h_name_alias);
2748 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
2750 struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
2751 bool do_aliases = true;
2752 ssize_t aliases_count = 0;
2760 struct nwrap_entdata *ed = (struct nwrap_entdata *)
2761 malloc(sizeof(struct nwrap_entdata));
2763 NWRAP_LOG(NWRAP_LOG_ERROR,
2764 "Unable to allocate memory for nwrap_entdata");
2775 /* Walk to first char */
2776 for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
2778 NWRAP_LOG(NWRAP_LOG_ERROR,
2779 "Invalid line[%s]: '%s'",
2786 for (i = p; !isspace((int)*p); p++) {
2788 NWRAP_LOG(NWRAP_LOG_ERROR,
2789 "Invalid line[%s]: '%s'",
2798 if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
2799 ed->ht.h_addrtype = AF_INET;
2800 ed->ht.h_length = 4;
2802 } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
2803 ed->ht.h_addrtype = AF_INET6;
2804 ed->ht.h_length = 16;
2807 NWRAP_LOG(NWRAP_LOG_ERROR,
2808 "Invalid line[%s]: '%s'",
2816 ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
2817 (void *const)ed->addr.host_addr);
2819 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
2823 ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
2831 /* Walk to first char */
2832 for (n = p; *p != '_' && !isalnum((int) *p); p++) {
2834 NWRAP_LOG(NWRAP_LOG_ERROR,
2835 "Invalid line[%s]: '%s'",
2843 for (n = p; !isspace((int)*p); p++) {
2852 /* Convert to lowercase. This operate on same memory region */
2856 /* glib's getent always dereferences he->h_aliases */
2857 ed->ht.h_aliases = malloc(sizeof(char *));
2858 if (ed->ht.h_aliases == NULL) {
2862 ed->ht.h_aliases[0] = NULL;
2867 while (do_aliases) {
2873 /* Walk to first char */
2874 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
2880 /* Only trailing spaces are left */
2885 for (a = p; !isspace((int)*p); p++) {
2894 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
2895 if (aliases == NULL) {
2899 ed->ht.h_aliases = aliases;
2902 aliases[aliases_count] = a;
2903 aliases[aliases_count + 1] = NULL;
2908 ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
2910 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
2915 ed->aliases_count = aliases_count;
2916 /* Inventarize item */
2917 ok = nwrap_add_hname(ed);
2922 ok = nwrap_ed_inventarize(ip, ed);
2931 static void nwrap_he_unload(struct nwrap_cache *nwrap)
2933 struct nwrap_he *nwrap_he =
2934 (struct nwrap_he *)nwrap->private_data;
2935 struct nwrap_entdata *ed;
2936 struct nwrap_entlist *el;
2940 nwrap_vector_foreach (ed, nwrap_he->entries, i)
2942 SAFE_FREE(ed->nwrap_addrdata.items);
2943 SAFE_FREE(ed->ht.h_aliases);
2946 SAFE_FREE(nwrap_he->entries.items);
2947 nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
2949 nwrap_vector_foreach(el, nwrap_he->lists, i)
2951 while (el != NULL) {
2952 struct nwrap_entlist *el_next;
2959 SAFE_FREE(nwrap_he->lists.items);
2960 nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
2966 * If we unload the file, the pointers in the hash table point to
2967 * invalid memory. So we need to destroy the hash table and recreate
2971 rc = hcreate(max_hostents);
2973 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
2979 /* user functions */
2980 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
2986 (void) b; /* unused */
2988 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
2990 ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
2992 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
2996 for (i=0; i<nwrap_pw_global.num; i++) {
2997 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
2998 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
2999 return &nwrap_pw_global.list[i];
3001 NWRAP_LOG(NWRAP_LOG_DEBUG,
3002 "user[%s] does not match [%s]",
3004 nwrap_pw_global.list[i].pw_name);
3007 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
3013 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
3014 const char *name, struct passwd *pwdst,
3015 char *buf, size_t buflen, struct passwd **pwdstp)
3019 pw = nwrap_files_getpwnam(b, name);
3027 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3030 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
3036 (void) b; /* unused */
3038 ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
3040 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
3044 for (i=0; i<nwrap_pw_global.num; i++) {
3045 if (nwrap_pw_global.list[i].pw_uid == uid) {
3046 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
3047 return &nwrap_pw_global.list[i];
3049 NWRAP_LOG(NWRAP_LOG_DEBUG,
3050 "uid[%u] does not match [%u]",
3052 nwrap_pw_global.list[i].pw_uid);
3055 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
3061 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
3062 uid_t uid, struct passwd *pwdst,
3063 char *buf, size_t buflen, struct passwd **pwdstp)
3067 pw = nwrap_files_getpwuid(b, uid);
3075 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3078 /* user enum functions */
3079 static void nwrap_files_setpwent(struct nwrap_backend *b)
3081 (void) b; /* unused */
3083 nwrap_pw_global.idx = 0;
3086 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
3090 (void) b; /* unused */
3092 if (nwrap_pw_global.idx == 0) {
3094 ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
3096 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
3101 if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
3106 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
3108 NWRAP_LOG(NWRAP_LOG_DEBUG,
3109 "return user[%s] uid[%u]",
3110 pw->pw_name, pw->pw_uid);
3115 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
3116 struct passwd *pwdst, char *buf,
3117 size_t buflen, struct passwd **pwdstp)
3121 pw = nwrap_files_getpwent(b);
3129 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
3132 static void nwrap_files_endpwent(struct nwrap_backend *b)
3134 (void) b; /* unused */
3136 nwrap_pw_global.idx = 0;
3141 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
3143 #ifdef HAVE_SETSPENT
3144 static void nwrap_files_setspent(void)
3146 nwrap_sp_global.idx = 0;
3149 static struct spwd *nwrap_files_getspent(void)
3153 if (nwrap_sp_global.idx == 0) {
3156 ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
3158 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
3163 if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
3168 sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
3170 NWRAP_LOG(NWRAP_LOG_DEBUG,
3177 static void nwrap_files_endspent(void)
3179 nwrap_sp_global.idx = 0;
3181 #endif /* HAVE_SETSPENT */
3183 static struct spwd *nwrap_files_getspnam(const char *name)
3188 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
3190 ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
3192 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
3196 for (i=0; i<nwrap_sp_global.num; i++) {
3197 if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
3198 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
3199 return &nwrap_sp_global.list[i];
3201 NWRAP_LOG(NWRAP_LOG_DEBUG,
3202 "user[%s] does not match [%s]",
3204 nwrap_sp_global.list[i].sp_namp);
3207 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
3212 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
3214 /* misc functions */
3215 static int nwrap_files_initgroups(struct nwrap_backend *b,
3224 groups = (gid_t *)malloc(size * sizeof(gid_t));
3225 if (groups == NULL) {
3226 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
3232 nwrap_files_setgrent(b);
3233 while ((grp = nwrap_files_getgrent(b)) != NULL) {
3236 NWRAP_LOG(NWRAP_LOG_DEBUG,
3237 "Inspecting %s for group membership",
3240 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
3241 if (group != grp->gr_gid &&
3242 (strcmp(user, grp->gr_mem[i]) == 0)) {
3243 NWRAP_LOG(NWRAP_LOG_DEBUG,
3244 "%s is member of %s",
3248 groups = (gid_t *)realloc(groups,
3249 (size + 1) * sizeof(gid_t));
3250 if (groups == NULL) {
3251 NWRAP_LOG(NWRAP_LOG_ERROR,
3257 groups[size] = grp->gr_gid;
3263 nwrap_files_endgrent(b);
3265 NWRAP_LOG(NWRAP_LOG_DEBUG,
3266 "%s is member of %d groups",
3269 /* This really only works if uid_wrapper is loaded */
3270 rc = setgroups(size, groups);
3277 /* group functions */
3278 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
3284 (void) b; /* unused */
3286 ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3288 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3292 for (i=0; i<nwrap_gr_global.num; i++) {
3293 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
3294 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
3295 return &nwrap_gr_global.list[i];
3297 NWRAP_LOG(NWRAP_LOG_DEBUG,
3298 "group[%s] does not match [%s]",
3300 nwrap_gr_global.list[i].gr_name);
3303 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
3309 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
3310 const char *name, struct group *grdst,
3311 char *buf, size_t buflen, struct group **grdstp)
3315 gr = nwrap_files_getgrnam(b, name);
3323 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3326 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
3332 (void) b; /* unused */
3334 ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3336 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3340 for (i=0; i<nwrap_gr_global.num; i++) {
3341 if (nwrap_gr_global.list[i].gr_gid == gid) {
3342 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
3343 return &nwrap_gr_global.list[i];
3345 NWRAP_LOG(NWRAP_LOG_DEBUG,
3346 "gid[%u] does not match [%u]",
3348 nwrap_gr_global.list[i].gr_gid);
3351 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
3357 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
3358 gid_t gid, struct group *grdst,
3359 char *buf, size_t buflen, struct group **grdstp)
3363 gr = nwrap_files_getgrgid(b, gid);
3371 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3374 /* group enum functions */
3375 static void nwrap_files_setgrent(struct nwrap_backend *b)
3377 (void) b; /* unused */
3379 nwrap_gr_global.idx = 0;
3382 static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
3386 (void) b; /* unused */
3388 if (nwrap_gr_global.idx == 0) {
3391 ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
3393 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
3398 if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
3403 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
3405 NWRAP_LOG(NWRAP_LOG_DEBUG,
3406 "return group[%s] gid[%u]",
3407 gr->gr_name, gr->gr_gid);
3412 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
3413 struct group *grdst, char *buf,
3414 size_t buflen, struct group **grdstp)
3418 gr = nwrap_files_getgrent(b);
3426 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3429 static void nwrap_files_endgrent(struct nwrap_backend *b)
3431 (void) b; /* unused */
3433 nwrap_gr_global.idx = 0;
3436 /* hosts functions */
3437 static int nwrap_files_gethostbyname(const char *name, int af,
3438 struct hostent *result,
3439 struct nwrap_vector *addr_list)
3441 struct nwrap_entlist *el;
3446 char canon_name[DNS_NAME_MAX] = { 0 };
3448 bool he_found = false;
3451 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
3453 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
3457 name_len = strlen(name);
3458 if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
3459 strncpy(canon_name, name, name_len - 1);
3463 if (!str_tolower_copy(&h_name_lower, name)) {
3464 NWRAP_LOG(NWRAP_LOG_DEBUG,
3465 "Out of memory while converting to lower case");
3469 /* Look at hash table for element */
3470 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
3471 e.key = h_name_lower;
3473 e_p = hsearch(e, FIND);
3475 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
3476 SAFE_FREE(h_name_lower);
3479 SAFE_FREE(h_name_lower);
3481 /* Always cleanup vector and results */
3482 if (!nwrap_vector_is_initialized(addr_list)) {
3483 if (!nwrap_vector_init(addr_list)) {
3484 NWRAP_LOG(NWRAP_LOG_DEBUG,
3485 "Unable to initialize memory for addr_list vector");
3489 /* When vector is initialized data are valid no more.
3490 * Quick way how to free vector is: */
3491 addr_list->count = 0;
3494 /* Iterate through results */
3495 for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
3499 /* Filter by address familiy if provided */
3500 if (af != AF_UNSPEC && he->h_addrtype != af) {
3506 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
3508 if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
3513 memcpy(result, he, sizeof(struct hostent));
3514 NWRAP_LOG(NWRAP_LOG_DEBUG,
3515 "Name found. Returning record for %s",
3519 nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
3520 result->h_addr_list = nwrap_vector_head(addr_list);
3526 NWRAP_LOG(NWRAP_LOG_DEBUG,
3527 "Name found in database. No records matches type.");
3534 #ifdef HAVE_GETHOSTBYNAME_R
3535 static int nwrap_gethostbyname_r(const char *name,
3536 struct hostent *ret,
3537 char *buf, size_t buflen,
3538 struct hostent **result, int *h_errnop)
3540 struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector));
3543 if (addr_list == NULL) {
3544 NWRAP_LOG(NWRAP_LOG_ERROR,
3545 "Unable to allocate memory for address list");
3550 ZERO_STRUCTP(addr_list);
3552 rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list);
3554 *h_errnop = h_errno;
3555 if (addr_list->items != NULL) {
3556 free(addr_list->items);
3558 SAFE_FREE(addr_list);
3563 if (buflen < (addr_list->count * sizeof(void *))) {
3564 SAFE_FREE(addr_list->items);
3565 SAFE_FREE(addr_list);
3569 /* Copy all to user provided buffer and change
3570 * pointers in returned structure.
3571 * +1 is for ending NULL pointer. */
3572 memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
3574 free(addr_list->items);
3577 ret->h_addr_list = (char **)buf;
3582 int gethostbyname_r(const char *name,
3583 struct hostent *ret,
3584 char *buf, size_t buflen,
3585 struct hostent **result, int *h_errnop)
3587 if (!nss_wrapper_hosts_enabled()) {
3588 return libc_gethostbyname_r(name,
3596 return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
3600 static int nwrap_files_getaddrinfo(const char *name,
3601 unsigned short port,
3602 const struct addrinfo *hints,
3603 struct addrinfo **ai)
3605 struct nwrap_entlist *el;
3607 struct addrinfo *ai_head = NULL;
3608 struct addrinfo *ai_cur = NULL;
3611 char canon_name[DNS_NAME_MAX] = { 0 };
3612 bool skip_canonname = false;
3620 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
3622 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
3626 name_len = strlen(name);
3627 if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
3628 strncpy(canon_name, name, name_len - 1);
3632 if (!str_tolower_copy(&h_name_lower, name)) {
3633 NWRAP_LOG(NWRAP_LOG_DEBUG,
3634 "Out of memory while converting to lower case");
3638 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
3639 e.key = h_name_lower;
3641 e_p = hsearch(e, FIND);
3643 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
3644 SAFE_FREE(h_name_lower);
3648 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
3649 SAFE_FREE(h_name_lower);
3652 for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
3655 struct addrinfo *ai_new = NULL;
3659 if (hints->ai_family != AF_UNSPEC &&
3660 he->h_addrtype != hints->ai_family)
3662 NWRAP_LOG(NWRAP_LOG_DEBUG,
3663 "Entry found but with wrong AF - "
3664 "remembering EAI_ADDRINFO.");
3665 rc = EAI_ADDRFAMILY;
3669 /* Function allocates memory and returns it in ai. */
3670 rc2 = nwrap_convert_he_ai(he,
3676 NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
3677 if (ai_head != NULL) {
3678 freeaddrinfo(ai_head);
3682 skip_canonname = true;
3684 if (ai_head == NULL) {
3687 if (ai_cur != NULL) {
3688 ai_cur->ai_next = ai_new;
3693 if (ai_head != NULL) {
3702 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
3703 socklen_t len, int type)
3706 char ip[NWRAP_INET_ADDRSTRLEN] = {0};
3707 struct nwrap_entdata *ed;
3712 (void) len; /* unused */
3714 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
3716 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
3720 a = inet_ntop(type, addr, ip, sizeof(ip));
3726 nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
3729 if (he->h_addrtype != type) {
3733 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
3742 #ifdef HAVE_GETHOSTBYADDR_R
3743 static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
3744 struct hostent *ret,
3745 char *buf, size_t buflen,
3746 struct hostent **result, int *h_errnop)
3748 *result = nwrap_files_gethostbyaddr(addr, len, type);
3749 if (*result != NULL) {
3750 memset(buf, '\0', buflen);
3754 *h_errnop = h_errno;
3759 int gethostbyaddr_r(const void *addr, socklen_t len, int type,
3760 struct hostent *ret,
3761 char *buf, size_t buflen,
3762 struct hostent **result, int *h_errnop)
3764 if (!nss_wrapper_hosts_enabled()) {
3765 return libc_gethostbyaddr_r(addr,
3775 return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
3779 /* hosts enum functions */
3780 static void nwrap_files_sethostent(void)
3782 nwrap_he_global.idx = 0;
3785 static struct hostent *nwrap_files_gethostent(void)
3789 if (nwrap_he_global.idx == 0) {
3792 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
3794 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
3799 if (nwrap_he_global.idx >= nwrap_he_global.num) {
3804 he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
3806 NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
3811 static void nwrap_files_endhostent(void)
3813 nwrap_he_global.idx = 0;
3821 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
3824 static struct passwd pwd;
3825 static char buf[1000];
3828 if (!b->fns->_nss_getpwnam_r) {
3832 status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno);
3833 if (status == NSS_STATUS_NOTFOUND) {
3836 if (status != NSS_STATUS_SUCCESS) {
3843 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
3844 const char *name, struct passwd *pwdst,
3845 char *buf, size_t buflen, struct passwd **pwdstp)
3851 if (!b->fns->_nss_getpwnam_r) {
3852 return NSS_STATUS_NOTFOUND;
3855 ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno);
3857 case NSS_STATUS_SUCCESS:
3860 case NSS_STATUS_NOTFOUND:
3865 case NSS_STATUS_TRYAGAIN:
3878 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
3881 static struct passwd pwd;
3882 static char buf[1000];
3885 if (!b->fns->_nss_getpwuid_r) {
3889 status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno);
3890 if (status == NSS_STATUS_NOTFOUND) {
3893 if (status != NSS_STATUS_SUCCESS) {
3899 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
3900 uid_t uid, struct passwd *pwdst,
3901 char *buf, size_t buflen, struct passwd **pwdstp)
3907 if (!b->fns->_nss_getpwuid_r) {
3911 ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno);
3913 case NSS_STATUS_SUCCESS:
3916 case NSS_STATUS_NOTFOUND:
3921 case NSS_STATUS_TRYAGAIN:
3934 static void nwrap_module_setpwent(struct nwrap_backend *b)
3936 if (!b->fns->_nss_setpwent) {
3940 b->fns->_nss_setpwent();
3943 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
3945 static struct passwd pwd;
3946 static char buf[1000];
3949 if (!b->fns->_nss_getpwent_r) {
3953 status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno);
3954 if (status == NSS_STATUS_NOTFOUND) {
3957 if (status != NSS_STATUS_SUCCESS) {
3963 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
3964 struct passwd *pwdst, char *buf,
3965 size_t buflen, struct passwd **pwdstp)
3971 if (!b->fns->_nss_getpwent_r) {
3975 ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno);
3977 case NSS_STATUS_SUCCESS:
3980 case NSS_STATUS_NOTFOUND:
3985 case NSS_STATUS_TRYAGAIN:
3998 static void nwrap_module_endpwent(struct nwrap_backend *b)
4000 if (!b->fns->_nss_endpwent) {
4004 b->fns->_nss_endpwent();
4007 static int nwrap_module_initgroups(struct nwrap_backend *b,
4008 const char *user, gid_t group)
4014 if (!b->fns->_nss_initgroups) {
4015 return NSS_STATUS_UNAVAIL;
4018 return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno);
4021 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
4024 static struct group grp;
4026 static int buflen = 1000;
4029 if (!b->fns->_nss_getgrnam_r) {
4034 buf = (char *)malloc(buflen);
4037 status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno);
4038 if (status == NSS_STATUS_TRYAGAIN) {
4040 buf = (char *)realloc(buf, buflen);
4046 if (status == NSS_STATUS_NOTFOUND) {
4050 if (status != NSS_STATUS_SUCCESS) {
4057 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
4058 const char *name, struct group *grdst,
4059 char *buf, size_t buflen, struct group **grdstp)
4065 if (!b->fns->_nss_getgrnam_r) {
4069 ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno);
4071 case NSS_STATUS_SUCCESS:
4074 case NSS_STATUS_NOTFOUND:
4079 case NSS_STATUS_TRYAGAIN:
4092 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
4095 static struct group grp;
4097 static int buflen = 1000;
4100 if (!b->fns->_nss_getgrgid_r) {
4105 buf = (char *)malloc(buflen);
4109 status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno);
4110 if (status == NSS_STATUS_TRYAGAIN) {
4112 buf = (char *)realloc(buf, buflen);
4118 if (status == NSS_STATUS_NOTFOUND) {
4122 if (status != NSS_STATUS_SUCCESS) {
4129 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
4130 gid_t gid, struct group *grdst,
4131 char *buf, size_t buflen, struct group **grdstp)
4137 if (!b->fns->_nss_getgrgid_r) {
4141 ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno);
4143 case NSS_STATUS_SUCCESS:
4146 case NSS_STATUS_NOTFOUND:
4151 case NSS_STATUS_TRYAGAIN:
4164 static void nwrap_module_setgrent(struct nwrap_backend *b)
4166 if (!b->fns->_nss_setgrent) {
4170 b->fns->_nss_setgrent();
4173 static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
4175 static struct group grp;
4177 static int buflen = 1024;
4180 if (!b->fns->_nss_getgrent_r) {
4185 buf = (char *)malloc(buflen);
4189 status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno);
4190 if (status == NSS_STATUS_TRYAGAIN) {
4192 buf = (char *)realloc(buf, buflen);
4198 if (status == NSS_STATUS_NOTFOUND) {
4202 if (status != NSS_STATUS_SUCCESS) {
4209 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
4210 struct group *grdst, char *buf,
4211 size_t buflen, struct group **grdstp)
4215 (void) grdstp; /* unused */
4217 if (!b->fns->_nss_getgrent_r) {
4221 ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno);
4223 case NSS_STATUS_SUCCESS:
4225 case NSS_STATUS_NOTFOUND:
4230 case NSS_STATUS_TRYAGAIN:
4243 static void nwrap_module_endgrent(struct nwrap_backend *b)
4245 if (!b->fns->_nss_endgrent) {
4249 b->fns->_nss_endgrent();
4252 /****************************************************************************
4254 ***************************************************************************/
4256 static struct passwd *nwrap_getpwnam(const char *name)
4261 for (i=0; i < nwrap_main_global->num_backends; i++) {
4262 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4263 pwd = b->ops->nw_getpwnam(b, name);
4272 struct passwd *getpwnam(const char *name)
4274 if (!nss_wrapper_enabled()) {
4275 return libc_getpwnam(name);
4278 return nwrap_getpwnam(name);
4281 /****************************************************************************
4283 ***************************************************************************/
4285 static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
4286 char *buf, size_t buflen, struct passwd **pwdstp)
4290 for (i=0; i < nwrap_main_global->num_backends; i++) {
4291 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4292 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
4293 if (ret == ENOENT) {
4302 #ifdef HAVE_GETPWNAM_R
4303 # ifdef HAVE_SOLARIS_GETPWNAM_R
4304 int getpwnam_r(const char *name, struct passwd *pwdst,
4305 char *buf, int buflen, struct passwd **pwdstp)
4306 # else /* HAVE_SOLARIS_GETPWNAM_R */
4307 int getpwnam_r(const char *name, struct passwd *pwdst,
4308 char *buf, size_t buflen, struct passwd **pwdstp)
4309 # endif /* HAVE_SOLARIS_GETPWNAM_R */
4311 if (!nss_wrapper_enabled()) {
4312 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
4315 return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
4319 /****************************************************************************
4321 ***************************************************************************/
4323 static struct passwd *nwrap_getpwuid(uid_t uid)
4328 for (i=0; i < nwrap_main_global->num_backends; i++) {
4329 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4330 pwd = b->ops->nw_getpwuid(b, uid);
4339 struct passwd *getpwuid(uid_t uid)
4341 if (!nss_wrapper_enabled()) {
4342 return libc_getpwuid(uid);
4345 return nwrap_getpwuid(uid);
4348 /****************************************************************************
4350 ***************************************************************************/
4352 static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
4353 char *buf, size_t buflen, struct passwd **pwdstp)
4357 for (i=0; i < nwrap_main_global->num_backends; i++) {
4358 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4359 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
4360 if (ret == ENOENT) {
4369 #ifdef HAVE_SOLARIS_GETPWUID_R
4370 int getpwuid_r(uid_t uid, struct passwd *pwdst,
4371 char *buf, int buflen, struct passwd **pwdstp)
4373 int getpwuid_r(uid_t uid, struct passwd *pwdst,
4374 char *buf, size_t buflen, struct passwd **pwdstp)
4377 if (!nss_wrapper_enabled()) {
4378 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
4381 return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
4384 /****************************************************************************
4386 ***************************************************************************/
4388 static void nwrap_setpwent(void)
4392 for (i=0; i < nwrap_main_global->num_backends; i++) {
4393 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4394 b->ops->nw_setpwent(b);
4400 if (!nss_wrapper_enabled()) {
4408 /****************************************************************************
4410 ***************************************************************************/
4412 static struct passwd *nwrap_getpwent(void)
4417 for (i=0; i < nwrap_main_global->num_backends; i++) {
4418 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4419 pwd = b->ops->nw_getpwent(b);
4428 struct passwd *getpwent(void)
4430 if (!nss_wrapper_enabled()) {
4431 return libc_getpwent();
4434 return nwrap_getpwent();
4437 /****************************************************************************
4439 ***************************************************************************/
4441 #ifdef HAVE_GETPWENT_R
4442 static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
4443 size_t buflen, struct passwd **pwdstp)
4447 for (i=0; i < nwrap_main_global->num_backends; i++) {
4448 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4449 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
4450 if (ret == ENOENT) {
4459 # ifdef HAVE_SOLARIS_GETPWENT_R
4460 struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
4462 struct passwd *pwdstp = NULL;
4465 if (!nss_wrapper_enabled()) {
4466 return libc_getpwent_r(pwdst, buf, buflen);
4468 rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
4475 # else /* HAVE_SOLARIS_GETPWENT_R */
4476 int getpwent_r(struct passwd *pwdst, char *buf,
4477 size_t buflen, struct passwd **pwdstp)
4479 if (!nss_wrapper_enabled()) {
4480 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
4483 return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
4485 # endif /* HAVE_SOLARIS_GETPWENT_R */
4486 #endif /* HAVE_GETPWENT_R */
4488 /****************************************************************************
4490 ***************************************************************************/
4492 static void nwrap_endpwent(void)
4496 for (i=0; i < nwrap_main_global->num_backends; i++) {
4497 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4498 b->ops->nw_endpwent(b);
4504 if (!nss_wrapper_enabled()) {
4512 /****************************************************************************
4514 ***************************************************************************/
4516 static int nwrap_initgroups(const char *user, gid_t group)
4520 for (i=0; i < nwrap_main_global->num_backends; i++) {
4521 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4524 rc = b->ops->nw_initgroups(b, user, group);
4534 int initgroups(const char *user, gid_t group)
4536 if (!nss_wrapper_enabled()) {
4537 return libc_initgroups(user, group);
4540 return nwrap_initgroups(user, group);
4543 /****************************************************************************
4545 ***************************************************************************/
4547 static struct group *nwrap_getgrnam(const char *name)
4552 for (i=0; i < nwrap_main_global->num_backends; i++) {
4553 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4554 grp = b->ops->nw_getgrnam(b, name);
4563 struct group *getgrnam(const char *name)
4565 if (!nss_wrapper_enabled()) {
4566 return libc_getgrnam(name);
4569 return nwrap_getgrnam(name);
4572 /****************************************************************************
4574 ***************************************************************************/
4576 static int nwrap_getgrnam_r(const char *name, struct group *grdst,
4577 char *buf, size_t buflen, struct group **grdstp)
4581 for (i=0; i < nwrap_main_global->num_backends; i++) {
4582 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4583 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
4584 if (ret == ENOENT) {
4593 #ifdef HAVE_GETGRNAM_R
4594 # ifdef HAVE_SOLARIS_GETGRNAM_R
4595 int getgrnam_r(const char *name, struct group *grp,
4596 char *buf, int buflen, struct group **pgrp)
4597 # else /* HAVE_SOLARIS_GETGRNAM_R */
4598 int getgrnam_r(const char *name, struct group *grp,
4599 char *buf, size_t buflen, struct group **pgrp)
4600 # endif /* HAVE_SOLARIS_GETGRNAM_R */
4602 if (!nss_wrapper_enabled()) {
4603 return libc_getgrnam_r(name,
4610 return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
4612 #endif /* HAVE_GETGRNAM_R */
4614 /****************************************************************************
4616 ***************************************************************************/
4618 static struct group *nwrap_getgrgid(gid_t gid)
4623 for (i=0; i < nwrap_main_global->num_backends; i++) {
4624 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4625 grp = b->ops->nw_getgrgid(b, gid);
4634 struct group *getgrgid(gid_t gid)
4636 if (!nss_wrapper_enabled()) {
4637 return libc_getgrgid(gid);
4640 return nwrap_getgrgid(gid);
4643 /****************************************************************************
4645 ***************************************************************************/
4647 static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
4648 char *buf, size_t buflen, struct group **grdstp)
4652 for (i=0; i < nwrap_main_global->num_backends; i++) {
4653 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4654 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
4655 if (ret == ENOENT) {
4664 #ifdef HAVE_GETGRGID_R
4665 # ifdef HAVE_SOLARIS_GETGRGID_R
4666 int getgrgid_r(gid_t gid, struct group *grdst,
4667 char *buf, int buflen, struct group **grdstp)
4668 # else /* HAVE_SOLARIS_GETGRGID_R */
4669 int getgrgid_r(gid_t gid, struct group *grdst,
4670 char *buf, size_t buflen, struct group **grdstp)
4671 # endif /* HAVE_SOLARIS_GETGRGID_R */
4673 if (!nss_wrapper_enabled()) {
4674 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
4677 return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
4681 /****************************************************************************
4683 ***************************************************************************/
4685 static void nwrap_setgrent(void)
4689 for (i=0; i < nwrap_main_global->num_backends; i++) {
4690 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4691 b->ops->nw_setgrent(b);
4695 #ifdef HAVE_BSD_SETGRENT
4701 if (!nss_wrapper_enabled()) {
4709 #ifdef HAVE_BSD_SETGRENT
4716 /****************************************************************************
4718 ***************************************************************************/
4720 static struct group *nwrap_getgrent(void)
4725 for (i=0; i < nwrap_main_global->num_backends; i++) {
4726 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4727 grp = b->ops->nw_getgrent(b);
4736 struct group *getgrent(void)
4738 if (!nss_wrapper_enabled()) {
4739 return libc_getgrent();
4742 return nwrap_getgrent();
4745 /****************************************************************************
4747 ***************************************************************************/
4749 #ifdef HAVE_GETGRENT_R
4750 static int nwrap_getgrent_r(struct group *grdst, char *buf,
4751 size_t buflen, struct group **grdstp)
4755 for (i=0; i < nwrap_main_global->num_backends; i++) {
4756 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4757 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
4758 if (ret == ENOENT) {
4767 # ifdef HAVE_SOLARIS_GETGRENT_R
4768 struct group *getgrent_r(struct group *src, char *buf, int buflen)
4770 struct group *grdstp = NULL;
4773 if (!nss_wrapper_enabled()) {
4774 return libc_getgrent_r(src, buf, buflen);
4777 rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
4784 # else /* HAVE_SOLARIS_GETGRENT_R */
4785 int getgrent_r(struct group *src, char *buf,
4786 size_t buflen, struct group **grdstp)
4788 if (!nss_wrapper_enabled()) {
4789 return libc_getgrent_r(src, buf, buflen, grdstp);
4792 return nwrap_getgrent_r(src, buf, buflen, grdstp);
4794 # endif /* HAVE_SOLARIS_GETGRENT_R */
4795 #endif /* HAVE_GETGRENT_R */
4797 /****************************************************************************
4799 ***************************************************************************/
4801 static void nwrap_endgrent(void)
4805 for (i=0; i < nwrap_main_global->num_backends; i++) {
4806 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4807 b->ops->nw_endgrent(b);
4813 if (!nss_wrapper_enabled()) {
4821 /****************************************************************************
4823 ***************************************************************************/
4825 #ifdef HAVE_GETGROUPLIST
4826 static int nwrap_getgrouplist(const char *user, gid_t group,
4827 gid_t *groups, int *ngroups)
4833 NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
4835 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
4837 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
4841 groups_tmp[0] = group;
4844 while ((grp = nwrap_getgrent()) != NULL) {
4847 NWRAP_LOG(NWRAP_LOG_DEBUG,
4848 "Inspecting %s for group membership",
4851 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
4853 if (group != grp->gr_gid &&
4854 (strcmp(user, grp->gr_mem[i]) == 0)) {
4856 NWRAP_LOG(NWRAP_LOG_DEBUG,
4857 "%s is member of %s",
4861 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
4863 NWRAP_LOG(NWRAP_LOG_ERROR,
4868 groups_tmp[count] = grp->gr_gid;
4877 NWRAP_LOG(NWRAP_LOG_DEBUG,
4878 "%s is member of %d groups",
4881 if (*ngroups < count) {
4888 memcpy(groups, groups_tmp, count * sizeof(gid_t));
4894 int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
4896 if (!nss_wrapper_enabled()) {
4897 return libc_getgrouplist(user, group, groups, ngroups);
4900 return nwrap_getgrouplist(user, group, groups, ngroups);
4904 /**********************************************************
4906 **********************************************************/
4908 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
4910 #ifdef HAVE_SETSPENT
4911 static void nwrap_setspent(void)
4913 nwrap_files_setspent();
4918 if (!nss_wrapper_shadow_enabled()) {
4925 static struct spwd *nwrap_getspent(void)
4927 return nwrap_files_getspent();
4930 struct spwd *getspent(void)
4932 if (!nss_wrapper_shadow_enabled()) {
4936 return nwrap_getspent();
4939 static void nwrap_endspent(void)
4941 nwrap_files_endspent();
4946 if (!nss_wrapper_shadow_enabled()) {
4952 #endif /* HAVE_SETSPENT */
4954 static struct spwd *nwrap_getspnam(const char *name)
4956 return nwrap_files_getspnam(name);
4959 struct spwd *getspnam(const char *name)
4961 if (!nss_wrapper_shadow_enabled()) {
4965 return nwrap_getspnam(name);
4968 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
4970 /**********************************************************
4972 **********************************************************/
4974 static void nwrap_sethostent(int stayopen) {
4975 (void) stayopen; /* ignored */
4977 nwrap_files_sethostent();
4980 #ifdef HAVE_SOLARIS_SETHOSTENT
4981 int sethostent(int stayopen)
4983 if (!nss_wrapper_hosts_enabled()) {
4984 libc_sethostent(stayopen);
4988 nwrap_sethostent(stayopen);
4992 #else /* HAVE_SOLARIS_SETHOSTENT */
4993 void sethostent(int stayopen)
4995 if (!nss_wrapper_hosts_enabled()) {
4996 libc_sethostent(stayopen);
5000 nwrap_sethostent(stayopen);
5002 #endif /* HAVE_SOLARIS_SETHOSTENT */
5004 static struct hostent *nwrap_gethostent(void)
5006 return nwrap_files_gethostent();
5009 struct hostent *gethostent(void) {
5010 if (!nss_wrapper_hosts_enabled()) {
5011 return libc_gethostent();
5014 return nwrap_gethostent();
5017 static void nwrap_endhostent(void) {
5018 nwrap_files_endhostent();
5021 #ifdef HAVE_SOLARIS_ENDHOSTENT
5022 int endhostent(void)
5024 if (!nss_wrapper_hosts_enabled()) {
5033 #else /* HAVE_SOLARIS_ENDHOSTENT */
5034 void endhostent(void)
5036 if (!nss_wrapper_hosts_enabled()) {
5043 #endif /* HAVE_SOLARIS_ENDHOSTENT */
5046 /* BSD implementation stores data in thread local storage but GLIBC does not */
5047 static __thread struct hostent user_he;
5048 static __thread struct nwrap_vector user_addrlist;
5050 static struct hostent user_he;
5051 static struct nwrap_vector user_addrlist;
5053 static struct hostent *nwrap_gethostbyname(const char *name)
5055 if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
5061 struct hostent *gethostbyname(const char *name)
5063 if (!nss_wrapper_hosts_enabled()) {
5064 return libc_gethostbyname(name);
5067 return nwrap_gethostbyname(name);
5070 /* This is a GNU extension - Also can be found on BSD systems */
5071 #ifdef HAVE_GETHOSTBYNAME2
5073 /* BSD implementation stores data in thread local storage but GLIBC not */
5074 static __thread struct hostent user_he2;
5075 static __thread struct nwrap_vector user_addrlist2;
5077 static struct hostent user_he2;
5078 static struct nwrap_vector user_addrlist2;
5080 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
5082 if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
5088 struct hostent *gethostbyname2(const char *name, int af)
5090 if (!nss_wrapper_hosts_enabled()) {
5091 return libc_gethostbyname2(name, af);
5094 return nwrap_gethostbyname2(name, af);
5098 static struct hostent *nwrap_gethostbyaddr(const void *addr,
5099 socklen_t len, int type)
5101 return nwrap_files_gethostbyaddr(addr, len, type);
5104 struct hostent *gethostbyaddr(const void *addr,
5105 socklen_t len, int type)
5107 if (!nss_wrapper_hosts_enabled()) {
5108 return libc_gethostbyaddr(addr, len, type);
5111 return nwrap_gethostbyaddr(addr, len, type);
5114 static const struct addrinfo default_hints =
5116 .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
5117 .ai_family = AF_UNSPEC,
5122 .ai_canonname = NULL,
5126 static int nwrap_convert_he_ai(const struct hostent *he,
5127 unsigned short port,
5128 const struct addrinfo *hints,
5129 struct addrinfo **pai,
5130 bool skip_canonname)
5132 struct addrinfo *ai;
5139 switch (he->h_addrtype) {
5141 socklen = sizeof(struct sockaddr_in);
5145 socklen = sizeof(struct sockaddr_in6);
5152 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
5157 ai->ai_flags = hints->ai_flags;
5158 ai->ai_family = he->h_addrtype;
5159 ai->ai_socktype = hints->ai_socktype;
5160 ai->ai_protocol = hints->ai_protocol;
5161 ai->ai_canonname = NULL;
5163 if (ai->ai_socktype == 0) {
5164 ai->ai_socktype = SOCK_DGRAM;
5166 if (ai->ai_protocol == 0) {
5167 if (ai->ai_socktype == SOCK_DGRAM) {
5168 ai->ai_protocol = IPPROTO_UDP;
5169 } else if (ai->ai_socktype == SOCK_STREAM) {
5170 ai->ai_protocol = IPPROTO_TCP;
5174 ai->ai_addrlen = socklen;
5175 ai->ai_addr = (void *)(ai + 1);
5177 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
5178 ai->ai_addr->sa_len = socklen;
5180 ai->ai_addr->sa_family = he->h_addrtype;
5182 switch (he->h_addrtype) {
5185 struct sockaddr_in *sinp =
5186 (struct sockaddr_in *) ai->ai_addr;
5188 memset(sinp, 0, sizeof(struct sockaddr_in));
5190 sinp->sin_port = htons(port);
5191 sinp->sin_family = AF_INET;
5193 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
5194 memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
5201 struct sockaddr_in6 *sin6p =
5202 (struct sockaddr_in6 *) ai->ai_addr;
5204 memset(sin6p, 0, sizeof(struct sockaddr_in6));
5206 sin6p->sin6_port = htons(port);
5207 sin6p->sin6_family = AF_INET6;
5209 memcpy(&sin6p->sin6_addr,
5219 if (he->h_name && !skip_canonname) {
5220 ai->ai_canonname = strdup(he->h_name);
5221 if (ai->ai_canonname == NULL) {
5231 static int nwrap_getaddrinfo(const char *node,
5232 const char *service,
5233 const struct addrinfo *hints,
5234 struct addrinfo **res)
5236 struct addrinfo *ai = NULL;
5237 unsigned short port = 0;
5247 .family = AF_UNSPEC,
5251 if (node == NULL && service == NULL) {
5255 if (hints == NULL) {
5256 hints = &default_hints;
5260 hints.ai_flags contains invalid flags; or, hints.ai_flags
5261 included AI_CANONNAME and name was NULL.
5263 if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
5264 return EAI_BADFLAGS;
5267 /* If no node has been specified, let glibc deal with it */
5270 struct addrinfo *p = NULL;
5272 ret = libc_getaddrinfo(node, service, hints, &p);
5280 if (service != NULL && service[0] != '\0') {
5281 const char *proto = NULL;
5287 sl = strtol(service, &end_ptr, 10);
5289 if (*end_ptr == '\0') {
5292 } else if (hints->ai_flags & AI_NUMERICSERV) {
5296 if (hints->ai_protocol != 0) {
5297 struct protoent *pent;
5299 pent = getprotobynumber(hints->ai_protocol);
5301 proto = pent->p_name;
5305 s = getservbyname(service, proto);
5309 port = ntohs(s->s_port);
5314 rc = inet_pton(AF_INET, node, &addr.in.v4);
5316 addr.family = AF_INET;
5319 if (addr.family == AF_UNSPEC) {
5320 rc = inet_pton(AF_INET6, node, &addr.in.v6);
5322 addr.family = AF_INET6;
5327 if (addr.family == AF_UNSPEC) {
5328 if (hints->ai_flags & AI_NUMERICHOST) {
5331 } else if ((hints->ai_family != AF_UNSPEC) &&
5332 (hints->ai_family != addr.family))
5334 return EAI_ADDRFAMILY;
5337 rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
5340 struct addrinfo *p = NULL;
5342 ret = libc_getaddrinfo(node, service, hints, &p);
5346 * nwrap_files_getaddrinfo failed, but libc was
5347 * successful -- use the result from libc.
5357 * If the socktype was not specified, duplicate
5358 * each ai returned, so that we have variants for
5361 if (hints->ai_socktype == 0) {
5362 struct addrinfo *ai_cur;
5364 /* freeaddrinfo() frees ai_canonname and ai so allocate them */
5365 for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
5366 struct addrinfo *ai_new;
5368 /* duplicate the current entry */
5370 ai_new = malloc(sizeof(struct addrinfo));
5371 if (ai_new == NULL) {
5376 memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
5377 ai_new->ai_next = NULL;
5379 /* We need a deep copy or freeaddrinfo() will blow up */
5380 if (ai_cur->ai_canonname != NULL) {
5381 ai_new->ai_canonname =
5382 strdup(ai_cur->ai_canonname);
5385 if (ai_cur->ai_socktype == SOCK_DGRAM) {
5386 ai_new->ai_socktype = SOCK_STREAM;
5387 } else if (ai_cur->ai_socktype == SOCK_STREAM) {
5388 ai_new->ai_socktype = SOCK_DGRAM;
5390 if (ai_cur->ai_protocol == IPPROTO_TCP) {
5391 ai_new->ai_protocol = IPPROTO_UDP;
5392 } else if (ai_cur->ai_protocol == IPPROTO_UDP) {
5393 ai_new->ai_protocol = IPPROTO_TCP;
5396 /* now insert the new entry */
5398 ai_new->ai_next = ai_cur->ai_next;
5399 ai_cur->ai_next = ai_new;
5401 /* and move on (don't duplicate the new entry) */
5412 int getaddrinfo(const char *node, const char *service,
5413 const struct addrinfo *hints,
5414 struct addrinfo **res)
5416 if (!nss_wrapper_hosts_enabled()) {
5417 return libc_getaddrinfo(node, service, hints, res);
5420 return nwrap_getaddrinfo(node, service, hints, res);
5423 static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
5424 char *host, size_t hostlen,
5425 char *serv, size_t servlen,
5429 struct servent *service;
5436 if (sa == NULL || salen < sizeof(sa_family_t)) {
5440 if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
5444 type = sa->sa_family;
5447 if (salen < sizeof(struct sockaddr_in))
5449 addr = &((const struct sockaddr_in *)sa)->sin_addr;
5450 addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
5451 port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
5455 if (salen < sizeof(struct sockaddr_in6))
5457 addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
5458 addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
5459 port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
5468 if ((flags & NI_NUMERICHOST) == 0) {
5469 he = nwrap_files_gethostbyaddr(addr, addrlen, type);
5470 if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
5473 if (he != NULL && he->h_name != NULL) {
5474 if (strlen(he->h_name) >= hostlen)
5475 return EAI_OVERFLOW;
5476 snprintf(host, hostlen, "%s", he->h_name);
5477 if (flags & NI_NOFQDN)
5478 host[strcspn(host, ".")] = '\0';
5480 if (inet_ntop(type, addr, host, hostlen) == NULL)
5481 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
5487 if ((flags & NI_NUMERICSERV) == 0) {
5488 proto = (flags & NI_DGRAM) ? "udp" : "tcp";
5489 service = getservbyport(htons(port), proto);
5491 if (service != NULL) {
5492 if (strlen(service->s_name) >= servlen)
5493 return EAI_OVERFLOW;
5494 snprintf(serv, servlen, "%s", service->s_name);
5496 if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
5497 return EAI_OVERFLOW;
5504 #ifdef HAVE_LINUX_GETNAMEINFO
5505 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5506 char *host, socklen_t hostlen,
5507 char *serv, socklen_t servlen,
5509 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
5510 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5511 char *host, socklen_t hostlen,
5512 char *serv, socklen_t servlen,
5515 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5516 char *host, size_t hostlen,
5517 char *serv, size_t servlen,
5521 if (!nss_wrapper_hosts_enabled()) {
5522 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
5525 return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
5528 static int nwrap_gethostname(char *name, size_t len)
5530 const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
5532 if (strlen(hostname) >= len) {
5533 errno = ENAMETOOLONG;
5536 snprintf(name, len, "%s", hostname);
5541 #ifdef HAVE_SOLARIS_GETHOSTNAME
5542 int gethostname(char *name, int len)
5543 #else /* HAVE_SOLARIS_GETHOSTNAME */
5544 int gethostname(char *name, size_t len)
5545 #endif /* HAVE_SOLARIS_GETHOSTNAME */
5547 if (!nwrap_hostname_enabled()) {
5548 return libc_gethostname(name, len);
5551 return nwrap_gethostname(name, len);
5554 /****************************
5556 ***************************/
5557 void nwrap_constructor(void)
5560 * If we hold a lock and the application forks, then the child
5561 * is not able to unlock the mutex and we are in a deadlock.
5563 * Setting these handlers should prevent such deadlocks.
5565 pthread_atfork(&nwrap_thread_prepare,
5566 &nwrap_thread_parent,
5567 &nwrap_thread_child);
5570 * Here is safe place to call nwrap_init() and initialize data
5571 * for the main process.
5576 /****************************
5578 ***************************/
5581 * This function is called when the library is unloaded and makes sure that
5582 * sockets get closed and the unix file for the socket are unlinked.
5584 void nwrap_destructor(void)
5589 if (nwrap_main_global != NULL) {
5590 struct nwrap_main *m = nwrap_main_global;
5593 if (m->libc != NULL) {
5594 SAFE_FREE(m->libc->fns);
5595 if (m->libc->handle != NULL) {
5596 dlclose(m->libc->handle);
5598 if (m->libc->nsl_handle != NULL) {
5599 dlclose(m->libc->nsl_handle);
5601 if (m->libc->sock_handle != NULL) {
5602 dlclose(m->libc->sock_handle);
5608 if (m->backends != NULL) {
5609 for (i = 0; i < m->num_backends; i++) {
5610 struct nwrap_backend *b = &(m->backends[i]);
5612 if (b->so_handle != NULL) {
5613 dlclose(b->so_handle);
5617 SAFE_FREE(m->backends);
5621 if (nwrap_pw_global.cache != NULL) {
5622 struct nwrap_cache *c = nwrap_pw_global.cache;
5624 nwrap_files_cache_unload(c);
5630 SAFE_FREE(nwrap_pw_global.list);
5631 nwrap_pw_global.num = 0;
5634 if (nwrap_gr_global.cache != NULL) {
5635 struct nwrap_cache *c = nwrap_gr_global.cache;
5637 nwrap_files_cache_unload(c);
5643 SAFE_FREE(nwrap_gr_global.list);
5644 nwrap_pw_global.num = 0;
5647 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
5648 if (nwrap_sp_global.cache != NULL) {
5649 struct nwrap_cache *c = nwrap_sp_global.cache;
5651 nwrap_files_cache_unload(c);
5657 nwrap_sp_global.num = 0;
5659 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
5661 if (nwrap_he_global.cache != NULL) {
5662 struct nwrap_cache *c = nwrap_he_global.cache;
5664 nwrap_files_cache_unload(c);
5670 nwrap_he_global.num = 0;
5673 free(user_addrlist.items);
5674 #ifdef HAVE_GETHOSTBYNAME2
5675 free(user_addrlist2.items);