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>
59 #include <netinet/in.h>
64 #include "nss_utils.h"
66 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
67 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
70 #ifndef _POSIX_PTHREAD_SEMANTICS
71 #define _POSIX_PTHREAD_SEMANTICS
78 #endif /* HAVE_SHADOW_H */
81 #include <arpa/inet.h>
82 #include <netinet/in.h>
86 #if defined(HAVE_NSS_H)
90 typedef enum nss_status NSS_STATUS
;
91 #elif defined(HAVE_NSS_COMMON_H)
93 #include <nss_common.h>
94 #include <nss_dbdefs.h>
97 typedef nss_status_t NSS_STATUS
;
99 # define NSS_STATUS_SUCCESS NSS_SUCCESS
100 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
101 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
102 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
104 # error "No nsswitch support detected"
108 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
116 #define EAI_NODATA EAI_NONAME
119 #ifndef EAI_ADDRFAMILY
120 #define EAI_ADDRFAMILY EAI_FAMILY
124 #define __STRING(x) #x
127 #ifndef __STRINGSTRING
128 #define __STRINGSTRING(x) __STRING(x)
132 #define __LINESTR__ __STRINGSTRING(__LINE__)
136 #define __location__ __FILE__ ":" __LINESTR__
140 #define DNS_NAME_MAX 255
143 /* GCC have printf type attribute check. */
144 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
145 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
147 #define PRINTF_ATTRIBUTE(a,b)
148 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
150 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
151 #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
153 #define CONSTRUCTOR_ATTRIBUTE
154 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
156 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
157 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
159 #define DESTRUCTOR_ATTRIBUTE
160 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
162 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
165 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
168 #ifndef discard_const
169 #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
172 #ifndef discard_const_p
173 #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
177 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
179 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
182 #define MAX(a,b) ((a) < (b) ? (b) : (a))
183 #define MIN(a,b) ((a) > (b) ? (b) : (a))
185 static bool nwrap_initialized
= false;
186 static pthread_mutex_t nwrap_initialized_mutex
= PTHREAD_MUTEX_INITIALIZER
;
188 /* The mutex or accessing the id */
189 static pthread_mutex_t nwrap_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
190 static pthread_mutex_t nwrap_gr_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
191 static pthread_mutex_t nwrap_he_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
192 static pthread_mutex_t nwrap_pw_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
193 static pthread_mutex_t nwrap_sp_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
195 #define nss_wrapper_init_mutex(m) \
196 _nss_wrapper_init_mutex(m, #m)
198 /* Add new global locks here please */
199 /* Also don't forget to add locks to
200 * nwrap_init() function.
202 # define NWRAP_REINIT_ALL do { \
204 ret = nss_wrapper_init_mutex(&nwrap_initialized_mutex); \
205 if (ret != 0) exit(-1); \
206 ret = nss_wrapper_init_mutex(&nwrap_global_mutex); \
207 if (ret != 0) exit(-1); \
208 ret = nss_wrapper_init_mutex(&nwrap_gr_global_mutex); \
209 if (ret != 0) exit(-1); \
210 ret = nss_wrapper_init_mutex(&nwrap_he_global_mutex); \
211 if (ret != 0) exit(-1); \
212 ret = nss_wrapper_init_mutex(&nwrap_pw_global_mutex); \
213 if (ret != 0) exit(-1); \
214 ret = nss_wrapper_init_mutex(&nwrap_sp_global_mutex); \
215 if (ret != 0) exit(-1); \
218 # define NWRAP_LOCK_ALL do { \
219 nwrap_mutex_lock(&nwrap_initialized_mutex); \
220 nwrap_mutex_lock(&nwrap_global_mutex); \
221 nwrap_mutex_lock(&nwrap_gr_global_mutex); \
222 nwrap_mutex_lock(&nwrap_he_global_mutex); \
223 nwrap_mutex_lock(&nwrap_pw_global_mutex); \
224 nwrap_mutex_lock(&nwrap_sp_global_mutex); \
227 # define NWRAP_UNLOCK_ALL do {\
228 nwrap_mutex_unlock(&nwrap_sp_global_mutex); \
229 nwrap_mutex_unlock(&nwrap_pw_global_mutex); \
230 nwrap_mutex_unlock(&nwrap_he_global_mutex); \
231 nwrap_mutex_unlock(&nwrap_gr_global_mutex); \
232 nwrap_mutex_unlock(&nwrap_global_mutex); \
233 nwrap_mutex_unlock(&nwrap_initialized_mutex); \
236 static void nwrap_init(void);
238 enum nwrap_dbglvl_e
{
245 #ifndef HAVE_GETPROGNAME
246 static const char *getprogname(void)
248 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
249 return program_invocation_short_name
;
250 #elif defined(HAVE_GETEXECNAME)
251 return getexecname();
254 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
256 #endif /* HAVE_GETPROGNAME */
258 static void nwrap_log(enum nwrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
259 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
261 static void nwrap_log(enum nwrap_dbglvl_e dbglvl
,
263 const char *format
, ...)
268 unsigned int lvl
= 0;
269 const char *prefix
= "NWRAP";
270 const char *progname
= getprogname();
272 d
= getenv("NSS_WRAPPER_DEBUGLEVEL");
281 va_start(va
, format
);
282 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
286 case NWRAP_LOG_ERROR
:
287 prefix
= "NWRAP_ERROR";
290 prefix
= "NWRAP_WARN";
292 case NWRAP_LOG_DEBUG
:
293 prefix
= "NWRAP_DEBUG";
295 case NWRAP_LOG_TRACE
:
296 prefix
= "NWRAP_TRACE";
300 if (progname
== NULL
) {
301 progname
= "<unknown>";
305 "%s[%s (%u)] - %s: %s\n",
308 (unsigned int)getpid(),
317 #define LIBC_NAME "libc.so"
319 typedef struct passwd
*(*__libc_getpwnam
)(const char *name
);
321 typedef int (*__libc_getpwnam_r
)(const char *name
,
325 struct passwd
**result
);
327 typedef struct passwd
*(*__libc_getpwuid
)(uid_t uid
);
329 typedef int (*__libc_getpwuid_r
)(uid_t uid
,
333 struct passwd
**result
);
335 typedef void (*__libc_setpwent
)(void);
337 typedef struct passwd
*(*__libc_getpwent
)(void);
339 #ifdef HAVE_GETPWENT_R
340 # ifdef HAVE_SOLARIS_GETPWENT_R
341 typedef struct passwd
*(*__libc_getpwent_r
)(struct passwd
*pwbuf
,
344 # else /* HAVE_SOLARIS_GETPWENT_R */
345 typedef int (*__libc_getpwent_r
)(struct passwd
*pwbuf
,
348 struct passwd
**pwbufp
);
349 # endif /* HAVE_SOLARIS_GETPWENT_R */
350 #endif /* HAVE_GETPWENT_R */
352 typedef void (*__libc_endpwent
)(void);
354 typedef int (*__libc_initgroups
)(const char *user
, gid_t gid
);
356 typedef struct group
*(*__libc_getgrnam
)(const char *name
);
358 typedef int (*__libc_getgrnam_r
)(const char *name
,
362 struct group
**result
);
364 typedef struct group
*(*__libc_getgrgid
)(gid_t gid
);
366 typedef int (*__libc_getgrgid_r
)(gid_t gid
,
370 struct group
**result
);
372 typedef void (*__libc_setgrent
)(void);
374 typedef struct group
*(*__libc_getgrent
)(void);
376 #ifdef HAVE_GETGRENT_R
377 # ifdef HAVE_SOLARIS_GETGRENT_R
378 typedef struct group
*(*__libc_getgrent_r
)(struct group
*group
,
381 # else /* HAVE_SOLARIS_GETGRENT_R */
382 typedef int (*__libc_getgrent_r
)(struct group
*group
,
385 struct group
**result
);
386 # endif /* HAVE_SOLARIS_GETGRENT_R */
387 #endif /* HAVE_GETGRENT_R */
389 typedef void (*__libc_endgrent
)(void);
391 typedef int (*__libc_getgrouplist
)(const char *user
,
396 typedef void (*__libc_sethostent
)(int stayopen
);
398 typedef struct hostent
*(*__libc_gethostent
)(void);
400 typedef void (*__libc_endhostent
)(void);
402 typedef struct hostent
*(*__libc_gethostbyname
)(const char *name
);
404 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
405 typedef struct hostent
*(*__libc_gethostbyname2
)(const char *name
, int af
);
408 #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
409 typedef int (*__libc_gethostbyname2_r
)(const char *name
,
414 struct hostent
**result
,
418 typedef struct hostent
*(*__libc_gethostbyaddr
)(const void *addr
,
422 typedef int (*__libc_getaddrinfo
)(const char *node
,
424 const struct addrinfo
*hints
,
425 struct addrinfo
**res
);
426 typedef int (*__libc_getnameinfo
)(const struct sockaddr
*sa
,
434 typedef int (*__libc_gethostname
)(char *name
, size_t len
);
436 #ifdef HAVE_GETHOSTBYNAME_R
437 typedef int (*__libc_gethostbyname_r
)(const char *name
,
439 char *buf
, size_t buflen
,
440 struct hostent
**result
, int *h_errnop
);
443 #ifdef HAVE_GETHOSTBYADDR_R
444 typedef int (*__libc_gethostbyaddr_r
)(const void *addr
,
450 struct hostent
**result
,
454 #define NWRAP_SYMBOL_ENTRY(i) \
460 struct nwrap_libc_symbols
{
461 NWRAP_SYMBOL_ENTRY(getpwnam
);
462 NWRAP_SYMBOL_ENTRY(getpwnam_r
);
463 NWRAP_SYMBOL_ENTRY(getpwuid
);
464 NWRAP_SYMBOL_ENTRY(getpwuid_r
);
465 NWRAP_SYMBOL_ENTRY(setpwent
);
466 NWRAP_SYMBOL_ENTRY(getpwent
);
467 #ifdef HAVE_GETPWENT_R
468 NWRAP_SYMBOL_ENTRY(getpwent_r
);
470 NWRAP_SYMBOL_ENTRY(endpwent
);
472 NWRAP_SYMBOL_ENTRY(initgroups
);
473 NWRAP_SYMBOL_ENTRY(getgrnam
);
474 NWRAP_SYMBOL_ENTRY(getgrnam_r
);
475 NWRAP_SYMBOL_ENTRY(getgrgid
);
476 NWRAP_SYMBOL_ENTRY(getgrgid_r
);
477 NWRAP_SYMBOL_ENTRY(setgrent
);
478 NWRAP_SYMBOL_ENTRY(getgrent
);
479 #ifdef HAVE_GETGRENT_R
480 NWRAP_SYMBOL_ENTRY(getgrent_r
);
482 NWRAP_SYMBOL_ENTRY(endgrent
);
483 NWRAP_SYMBOL_ENTRY(getgrouplist
);
485 NWRAP_SYMBOL_ENTRY(sethostent
);
486 NWRAP_SYMBOL_ENTRY(gethostent
);
487 NWRAP_SYMBOL_ENTRY(endhostent
);
488 NWRAP_SYMBOL_ENTRY(gethostbyname
);
489 #ifdef HAVE_GETHOSTBYNAME_R
490 NWRAP_SYMBOL_ENTRY(gethostbyname_r
);
492 #ifdef HAVE_GETHOSTBYNAME2
493 NWRAP_SYMBOL_ENTRY(gethostbyname2
);
495 #ifdef HAVE_GETHOSTBYNAME2_R
496 NWRAP_SYMBOL_ENTRY(gethostbyname2_r
);
498 NWRAP_SYMBOL_ENTRY(gethostbyaddr
);
499 #ifdef HAVE_GETHOSTBYADDR_R
500 NWRAP_SYMBOL_ENTRY(gethostbyaddr_r
);
502 NWRAP_SYMBOL_ENTRY(getaddrinfo
);
503 NWRAP_SYMBOL_ENTRY(getnameinfo
);
504 NWRAP_SYMBOL_ENTRY(gethostname
);
506 #undef NWRAP_SYMBOL_ENTRY
508 typedef NSS_STATUS (*__nss_getpwnam_r
)(const char *name
,
509 struct passwd
*result
,
513 typedef NSS_STATUS (*__nss_getpwuid_r
)(uid_t uid
,
514 struct passwd
*result
,
518 typedef NSS_STATUS (*__nss_setpwent
)(void);
519 typedef NSS_STATUS (*__nss_getpwent_r
)(struct passwd
*result
,
523 typedef NSS_STATUS (*__nss_endpwent
)(void);
524 typedef NSS_STATUS (*__nss_initgroups_dyn
)(const char *user
,
531 typedef NSS_STATUS (*__nss_getgrnam_r
)(const char *name
,
532 struct group
*result
,
536 typedef NSS_STATUS (*__nss_getgrgid_r
)(gid_t gid
,
537 struct group
*result
,
541 typedef NSS_STATUS (*__nss_setgrent
)(void);
542 typedef NSS_STATUS (*__nss_getgrent_r
)(struct group
*result
,
546 typedef NSS_STATUS (*__nss_endgrent
)(void);
547 typedef NSS_STATUS (*__nss_gethostbyaddr_r
)(const void *addr
,
550 struct hostent
*result
,
555 typedef NSS_STATUS (*__nss_gethostbyname2_r
)(const char *name
,
557 struct hostent
*result
,
563 #define NWRAP_NSS_MODULE_SYMBOL_ENTRY(i) \
569 struct nwrap_nss_module_symbols
{
570 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwnam_r
);
571 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwuid_r
);
572 NWRAP_NSS_MODULE_SYMBOL_ENTRY(setpwent
);
573 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwent_r
);
574 NWRAP_NSS_MODULE_SYMBOL_ENTRY(endpwent
);
576 NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups_dyn
);
577 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrnam_r
);
578 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrgid_r
);
579 NWRAP_NSS_MODULE_SYMBOL_ENTRY(setgrent
);
580 NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrent_r
);
581 NWRAP_NSS_MODULE_SYMBOL_ENTRY(endgrent
);
583 NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyaddr_r
);
584 NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyname2_r
);
587 struct nwrap_backend
{
591 struct nwrap_ops
*ops
;
592 struct nwrap_nss_module_symbols
*symbols
;
598 struct passwd
* (*nw_getpwnam
)(struct nwrap_backend
*b
,
600 int (*nw_getpwnam_r
)(struct nwrap_backend
*b
,
601 const char *name
, struct passwd
*pwdst
,
602 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
603 struct passwd
* (*nw_getpwuid
)(struct nwrap_backend
*b
,
605 int (*nw_getpwuid_r
)(struct nwrap_backend
*b
,
606 uid_t uid
, struct passwd
*pwdst
,
607 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
608 void (*nw_setpwent
)(struct nwrap_backend
*b
);
609 struct passwd
* (*nw_getpwent
)(struct nwrap_backend
*b
);
610 int (*nw_getpwent_r
)(struct nwrap_backend
*b
,
611 struct passwd
*pwdst
, char *buf
,
612 size_t buflen
, struct passwd
**pwdstp
);
613 void (*nw_endpwent
)(struct nwrap_backend
*b
);
614 int (*nw_initgroups_dyn
)(struct nwrap_backend
*b
,
622 struct group
* (*nw_getgrnam
)(struct nwrap_backend
*b
,
624 int (*nw_getgrnam_r
)(struct nwrap_backend
*b
,
625 const char *name
, struct group
*grdst
,
626 char *buf
, size_t buflen
, struct group
**grdstp
);
627 struct group
* (*nw_getgrgid
)(struct nwrap_backend
*b
,
629 int (*nw_getgrgid_r
)(struct nwrap_backend
*b
,
630 gid_t gid
, struct group
*grdst
,
631 char *buf
, size_t buflen
, struct group
**grdstp
);
632 void (*nw_setgrent
)(struct nwrap_backend
*b
);
633 struct group
* (*nw_getgrent
)(struct nwrap_backend
*b
);
634 int (*nw_getgrent_r
)(struct nwrap_backend
*b
,
635 struct group
*grdst
, char *buf
,
636 size_t buflen
, struct group
**grdstp
);
637 void (*nw_endgrent
)(struct nwrap_backend
*b
);
638 struct hostent
*(*nw_gethostbyaddr
)(struct nwrap_backend
*b
,
640 socklen_t len
, int type
);
641 struct hostent
*(*nw_gethostbyname
)(struct nwrap_backend
*b
,
643 struct hostent
*(*nw_gethostbyname2
)(struct nwrap_backend
*b
,
644 const char *name
, int af
);
645 int (*nw_gethostbyname2_r
)(struct nwrap_backend
*b
,
646 const char *name
, int af
,
647 struct hostent
*hedst
,
648 char *buf
, size_t buflen
,
649 struct hostent
**hedstp
);
652 /* Public prototypes */
654 bool nss_wrapper_enabled(void);
655 bool nss_wrapper_shadow_enabled(void);
656 bool nss_wrapper_hosts_enabled(void);
658 /* prototypes for files backend */
661 static struct passwd
*nwrap_files_getpwnam(struct nwrap_backend
*b
,
663 static int nwrap_files_getpwnam_r(struct nwrap_backend
*b
,
664 const char *name
, struct passwd
*pwdst
,
665 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
666 static struct passwd
*nwrap_files_getpwuid(struct nwrap_backend
*b
,
668 static int nwrap_files_getpwuid_r(struct nwrap_backend
*b
,
669 uid_t uid
, struct passwd
*pwdst
,
670 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
671 static void nwrap_files_setpwent(struct nwrap_backend
*b
);
672 static struct passwd
*nwrap_files_getpwent(struct nwrap_backend
*b
);
673 static int nwrap_files_getpwent_r(struct nwrap_backend
*b
,
674 struct passwd
*pwdst
, char *buf
,
675 size_t buflen
, struct passwd
**pwdstp
);
676 static void nwrap_files_endpwent(struct nwrap_backend
*b
);
677 static int nwrap_files_initgroups_dyn(struct nwrap_backend
*b
,
685 static struct group
*nwrap_files_getgrnam(struct nwrap_backend
*b
,
687 static int nwrap_files_getgrnam_r(struct nwrap_backend
*b
,
688 const char *name
, struct group
*grdst
,
689 char *buf
, size_t buflen
, struct group
**grdstp
);
690 static struct group
*nwrap_files_getgrgid(struct nwrap_backend
*b
,
692 static int nwrap_files_getgrgid_r(struct nwrap_backend
*b
,
693 gid_t gid
, struct group
*grdst
,
694 char *buf
, size_t buflen
, struct group
**grdstp
);
695 static void nwrap_files_setgrent(struct nwrap_backend
*b
);
696 static struct group
*nwrap_files_getgrent(struct nwrap_backend
*b
);
697 static int nwrap_files_getgrent_r(struct nwrap_backend
*b
,
698 struct group
*grdst
, char *buf
,
699 size_t buflen
, struct group
**grdstp
);
700 static void nwrap_files_endgrent(struct nwrap_backend
*b
);
701 static struct hostent
*nwrap_files_gethostbyaddr(struct nwrap_backend
*b
,
703 socklen_t len
, int type
);
704 static struct hostent
*nwrap_files_gethostbyname(struct nwrap_backend
*b
,
706 #ifdef HAVE_GETHOSTBYNAME2
707 static struct hostent
*nwrap_files_gethostbyname2(struct nwrap_backend
*b
,
708 const char *name
, int af
);
709 #endif /* HAVE_GETHOSTBYNAME2 */
710 static int nwrap_files_gethostbyname2_r(struct nwrap_backend
*b
,
711 const char *name
, int af
,
712 struct hostent
*hedst
,
713 char *buf
, size_t buflen
,
714 struct hostent
**hedstp
);
716 /* prototypes for module backend */
718 static struct passwd
*nwrap_module_getpwent(struct nwrap_backend
*b
);
719 static int nwrap_module_getpwent_r(struct nwrap_backend
*b
,
720 struct passwd
*pwdst
, char *buf
,
721 size_t buflen
, struct passwd
**pwdstp
);
722 static struct passwd
*nwrap_module_getpwnam(struct nwrap_backend
*b
,
724 static int nwrap_module_getpwnam_r(struct nwrap_backend
*b
,
725 const char *name
, struct passwd
*pwdst
,
726 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
727 static struct passwd
*nwrap_module_getpwuid(struct nwrap_backend
*b
,
729 static int nwrap_module_getpwuid_r(struct nwrap_backend
*b
,
730 uid_t uid
, struct passwd
*pwdst
,
731 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
732 static void nwrap_module_setpwent(struct nwrap_backend
*b
);
733 static void nwrap_module_endpwent(struct nwrap_backend
*b
);
734 static struct group
*nwrap_module_getgrent(struct nwrap_backend
*b
);
735 static int nwrap_module_getgrent_r(struct nwrap_backend
*b
,
736 struct group
*grdst
, char *buf
,
737 size_t buflen
, struct group
**grdstp
);
738 static struct group
*nwrap_module_getgrnam(struct nwrap_backend
*b
,
740 static int nwrap_module_getgrnam_r(struct nwrap_backend
*b
,
741 const char *name
, struct group
*grdst
,
742 char *buf
, size_t buflen
, struct group
**grdstp
);
743 static struct group
*nwrap_module_getgrgid(struct nwrap_backend
*b
,
745 static int nwrap_module_getgrgid_r(struct nwrap_backend
*b
,
746 gid_t gid
, struct group
*grdst
,
747 char *buf
, size_t buflen
, struct group
**grdstp
);
748 static void nwrap_module_setgrent(struct nwrap_backend
*b
);
749 static void nwrap_module_endgrent(struct nwrap_backend
*b
);
750 static int nwrap_module_initgroups_dyn(struct nwrap_backend
*b
,
758 static struct hostent
*nwrap_module_gethostbyaddr(struct nwrap_backend
*b
,
760 socklen_t len
, int type
);
761 static struct hostent
*nwrap_module_gethostbyname(struct nwrap_backend
*b
,
763 static struct hostent
*nwrap_module_gethostbyname2(struct nwrap_backend
*b
,
764 const char *name
, int af
);
765 static int nwrap_module_gethostbyname2_r(struct nwrap_backend
*b
,
766 const char *name
, int af
,
767 struct hostent
*hedst
,
768 char *buf
, size_t buflen
,
769 struct hostent
**hedstp
);
771 struct nwrap_ops nwrap_files_ops
= {
772 .nw_getpwnam
= nwrap_files_getpwnam
,
773 .nw_getpwnam_r
= nwrap_files_getpwnam_r
,
774 .nw_getpwuid
= nwrap_files_getpwuid
,
775 .nw_getpwuid_r
= nwrap_files_getpwuid_r
,
776 .nw_setpwent
= nwrap_files_setpwent
,
777 .nw_getpwent
= nwrap_files_getpwent
,
778 .nw_getpwent_r
= nwrap_files_getpwent_r
,
779 .nw_endpwent
= nwrap_files_endpwent
,
780 .nw_initgroups_dyn
= nwrap_files_initgroups_dyn
,
781 .nw_getgrnam
= nwrap_files_getgrnam
,
782 .nw_getgrnam_r
= nwrap_files_getgrnam_r
,
783 .nw_getgrgid
= nwrap_files_getgrgid
,
784 .nw_getgrgid_r
= nwrap_files_getgrgid_r
,
785 .nw_setgrent
= nwrap_files_setgrent
,
786 .nw_getgrent
= nwrap_files_getgrent
,
787 .nw_getgrent_r
= nwrap_files_getgrent_r
,
788 .nw_endgrent
= nwrap_files_endgrent
,
789 .nw_gethostbyaddr
= nwrap_files_gethostbyaddr
,
790 .nw_gethostbyname
= nwrap_files_gethostbyname
,
791 #ifdef HAVE_GETHOSTBYNAME2
792 .nw_gethostbyname2
= nwrap_files_gethostbyname2
,
793 #endif /* HAVE_GETHOSTBYNAME2 */
794 .nw_gethostbyname2_r
= nwrap_files_gethostbyname2_r
,
797 struct nwrap_ops nwrap_module_ops
= {
798 .nw_getpwnam
= nwrap_module_getpwnam
,
799 .nw_getpwnam_r
= nwrap_module_getpwnam_r
,
800 .nw_getpwuid
= nwrap_module_getpwuid
,
801 .nw_getpwuid_r
= nwrap_module_getpwuid_r
,
802 .nw_setpwent
= nwrap_module_setpwent
,
803 .nw_getpwent
= nwrap_module_getpwent
,
804 .nw_getpwent_r
= nwrap_module_getpwent_r
,
805 .nw_endpwent
= nwrap_module_endpwent
,
806 .nw_initgroups_dyn
= nwrap_module_initgroups_dyn
,
807 .nw_getgrnam
= nwrap_module_getgrnam
,
808 .nw_getgrnam_r
= nwrap_module_getgrnam_r
,
809 .nw_getgrgid
= nwrap_module_getgrgid
,
810 .nw_getgrgid_r
= nwrap_module_getgrgid_r
,
811 .nw_setgrent
= nwrap_module_setgrent
,
812 .nw_getgrent
= nwrap_module_getgrent
,
813 .nw_getgrent_r
= nwrap_module_getgrent_r
,
814 .nw_endgrent
= nwrap_module_endgrent
,
815 .nw_gethostbyaddr
= nwrap_module_gethostbyaddr
,
816 .nw_gethostbyname
= nwrap_module_gethostbyname
,
817 .nw_gethostbyname2
= nwrap_module_gethostbyname2
,
818 .nw_gethostbyname2_r
= nwrap_module_gethostbyname2_r
,
825 struct nwrap_libc_symbols symbols
;
830 struct nwrap_backend
*backends
;
831 struct nwrap_libc
*libc
;
834 static struct nwrap_main
*nwrap_main_global
;
835 static struct nwrap_main __nwrap_main_global
;
840 static int nwrap_convert_he_ai(const struct hostent
*he
,
842 const struct addrinfo
*hints
,
843 struct addrinfo
**pai
,
844 bool skip_canonname
);
846 #ifdef HAVE_GETGROUPLIST
847 static int nwrap_getgrouplist(const char *user
,
858 #define DEFAULT_VECTOR_CAPACITY 16
860 struct nwrap_vector
{
866 /* Macro returns pointer to first element of vector->items array.
868 * nwrap_vector is used as a memory backend which take care of
869 * memory allocations and other stuff like memory growing.
870 * nwrap_vectors should not be considered as some abstract structures.
871 * On this level, vectors are more handy than direct realloc/malloc
874 * nwrap_vector->items is array inside nwrap_vector which can be
875 * directly pointed by libc structure assembled by cwrap itself.
879 * 1) struct hostent contains char **h_addr_list element.
880 * 2) nwrap_vector holds array of pointers to addresses.
881 * It's easier to use vector to store results of
884 * Now, pretend that cwrap assembled struct hostent and
885 * we need to set h_addr_list to point to nwrap_vector.
886 * Idea behind is to shield users from internal nwrap_vector
888 * (Yes, not fully - array terminated by NULL is needed because
889 * it's result expected by libc function caller.)
895 * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
896 * ... don't care about failed allocation now ...
898 * ... fill nwrap vector ...
901 * he.h_addr_list = nwrap_vector_head(vector);
904 #define nwrap_vector_head(vect) ((void *)((vect)->items))
906 #define nwrap_vector_foreach(item, vect, iter) \
907 for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
909 (item) = (vect).items[++iter])
911 #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
913 static inline bool nwrap_vector_init(struct nwrap_vector
*const vector
)
915 if (vector
== NULL
) {
919 /* count is initialized by ZERO_STRUCTP */
920 ZERO_STRUCTP(vector
);
921 vector
->items
= malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY
+ 1));
922 if (vector
->items
== NULL
) {
925 vector
->capacity
= DEFAULT_VECTOR_CAPACITY
;
926 memset(vector
->items
, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY
+ 1));
931 static bool nwrap_vector_add_item(struct nwrap_vector
*vector
, void *const item
)
933 assert (vector
!= NULL
);
935 if (vector
->items
== NULL
) {
936 nwrap_vector_init(vector
);
939 if (vector
->count
== vector
->capacity
) {
940 /* Items array _MUST_ be NULL terminated because it's passed
941 * as result to caller which expect NULL terminated array from libc.
943 void **items
= realloc(vector
->items
, sizeof(void *) * ((vector
->capacity
* 2) + 1));
947 vector
->items
= items
;
949 /* Don't count ending NULL to capacity */
950 vector
->capacity
*= 2;
953 vector
->items
[vector
->count
] = item
;
956 vector
->items
[vector
->count
] = NULL
;
961 static bool nwrap_vector_merge(struct nwrap_vector
*dst
,
962 struct nwrap_vector
*src
)
964 void **dst_items
= NULL
;
967 if (src
->count
== 0) {
971 count
= dst
->count
+ src
->count
;
973 /* We don't need reallocation if we have enough capacity. */
974 if (src
->count
> (dst
->capacity
- dst
->count
)) {
975 dst_items
= (void **)realloc(dst
->items
, (count
+ 1) * sizeof(void *));
976 if (dst_items
== NULL
) {
979 dst
->items
= dst_items
;
980 dst
->capacity
= count
;
983 memcpy((void *)(((long *)dst
->items
) + dst
->count
),
985 src
->count
* sizeof(void *));
998 struct nwrap_vector lines
;
1000 bool (*parse_line
)(struct nwrap_cache
*, char *line
);
1001 void (*unload
)(struct nwrap_cache
*);
1006 struct nwrap_cache
*cache
;
1008 struct passwd
*list
;
1013 struct nwrap_cache __nwrap_cache_pw
;
1014 struct nwrap_pw nwrap_pw_global
;
1016 static bool nwrap_pw_parse_line(struct nwrap_cache
*nwrap
, char *line
);
1017 static void nwrap_pw_unload(struct nwrap_cache
*nwrap
);
1020 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1022 struct nwrap_cache
*cache
;
1029 struct nwrap_cache __nwrap_cache_sp
;
1030 struct nwrap_sp nwrap_sp_global
;
1032 static bool nwrap_sp_parse_line(struct nwrap_cache
*nwrap
, char *line
);
1033 static void nwrap_sp_unload(struct nwrap_cache
*nwrap
);
1034 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1038 struct nwrap_cache
*cache
;
1045 struct nwrap_cache __nwrap_cache_gr
;
1046 struct nwrap_gr nwrap_gr_global
;
1049 static bool nwrap_he_parse_line(struct nwrap_cache
*nwrap
, char *line
);
1050 static void nwrap_he_unload(struct nwrap_cache
*nwrap
);
1052 struct nwrap_addrdata
{
1053 unsigned char host_addr
[16]; /* IPv4 or IPv6 address */
1056 static size_t max_hostents
= 100;
1058 struct nwrap_entdata
{
1059 struct nwrap_addrdata addr
;
1062 struct nwrap_vector nwrap_addrdata
;
1064 ssize_t aliases_count
;
1067 struct nwrap_entlist
{
1068 struct nwrap_entlist
*next
;
1069 struct nwrap_entdata
*ed
;
1073 struct nwrap_cache
*cache
;
1075 struct nwrap_vector entries
;
1076 struct nwrap_vector lists
;
1082 static struct nwrap_cache __nwrap_cache_he
;
1083 static struct nwrap_he nwrap_he_global
;
1086 /*********************************************************
1088 *********************************************************/
1090 static bool nwrap_gr_parse_line(struct nwrap_cache
*nwrap
, char *line
);
1091 static void nwrap_gr_unload(struct nwrap_cache
*nwrap
);
1092 #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
1093 /* xlC and other oldschool compilers support (only) this */
1094 #pragma init (nwrap_constructor)
1096 void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE
;
1097 #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
1098 #pragma fini (nwrap_destructor)
1100 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
1102 /*********************************************************
1103 * NWRAP LIBC LOADER FUNCTIONS
1104 *********************************************************/
1112 static const char *nwrap_str_lib(enum nwrap_lib lib
)
1119 case NWRAP_LIBSOCKET
:
1123 /* Compiler would warn us about unhandled enum value if we get here */
1127 static void *nwrap_load_lib_handle(enum nwrap_lib lib
)
1129 int flags
= RTLD_LAZY
;
1130 void *handle
= NULL
;
1133 #ifdef RTLD_DEEPBIND
1134 const char *env_preload
= getenv("LD_PRELOAD");
1135 const char *env_deepbind
= getenv("NSS_WRAPPER_DISABLE_DEEPBIND");
1136 bool enable_deepbind
= true;
1138 /* Don't do a deepbind if we run with libasan */
1139 if (env_preload
!= NULL
&& strlen(env_preload
) < 1024) {
1140 const char *p
= strstr(env_preload
, "libasan.so");
1142 enable_deepbind
= false;
1146 if (env_deepbind
!= NULL
&& strlen(env_deepbind
) >= 1) {
1147 enable_deepbind
= false;
1150 if (enable_deepbind
) {
1151 flags
|= RTLD_DEEPBIND
;
1158 handle
= nwrap_main_global
->libc
->nsl_handle
;
1159 if (handle
== NULL
) {
1160 for (i
= 10; i
>= 0; i
--) {
1161 char soname
[256] = {0};
1163 snprintf(soname
, sizeof(soname
), "libnsl.so.%d", i
);
1164 handle
= dlopen(soname
, flags
);
1165 if (handle
!= NULL
) {
1170 nwrap_main_global
->libc
->nsl_handle
= handle
;
1175 case NWRAP_LIBSOCKET
:
1176 #ifdef HAVE_LIBSOCKET
1177 handle
= nwrap_main_global
->libc
->sock_handle
;
1178 if (handle
== NULL
) {
1179 for (i
= 10; i
>= 0; i
--) {
1180 char soname
[256] = {0};
1182 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
1183 handle
= dlopen(soname
, flags
);
1184 if (handle
!= NULL
) {
1189 nwrap_main_global
->libc
->sock_handle
= handle
;
1195 handle
= nwrap_main_global
->libc
->handle
;
1196 if (handle
== NULL
) {
1197 for (i
= 10; i
>= 0; i
--) {
1198 char soname
[256] = {0};
1200 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
1201 handle
= dlopen(soname
, flags
);
1202 if (handle
!= NULL
) {
1207 nwrap_main_global
->libc
->handle
= handle
;
1212 if (handle
== NULL
) {
1214 handle
= nwrap_main_global
->libc
->handle
1215 = nwrap_main_global
->libc
->sock_handle
1216 = nwrap_main_global
->libc
->nsl_handle
1219 NWRAP_LOG(NWRAP_LOG_ERROR
,
1220 "Failed to dlopen library: %s\n",
1229 static void *_nwrap_bind_symbol(enum nwrap_lib lib
, const char *fn_name
)
1236 handle
= nwrap_load_lib_handle(lib
);
1238 func
= dlsym(handle
, fn_name
);
1240 NWRAP_LOG(NWRAP_LOG_ERROR
,
1241 "Failed to find %s: %s\n",
1242 fn_name
, dlerror());
1246 NWRAP_LOG(NWRAP_LOG_TRACE
,
1247 "Loaded %s from %s",
1248 fn_name
, nwrap_str_lib(lib
));
1252 #define nwrap_mutex_lock(m) _nwrap_mutex_lock(m, #m, __func__, __LINE__)
1253 static void _nwrap_mutex_lock(pthread_mutex_t
*mutex
, const char *name
, const char *caller
, unsigned line
)
1257 ret
= pthread_mutex_lock(mutex
);
1259 NWRAP_LOG(NWRAP_LOG_ERROR
, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s",
1260 getpid(), getppid(), caller
, line
, name
, strerror(ret
));
1265 #define nwrap_mutex_unlock(m) _nwrap_mutex_unlock(m, #m, __func__, __LINE__)
1266 static void _nwrap_mutex_unlock(pthread_mutex_t
*mutex
, const char *name
, const char *caller
, unsigned line
)
1270 ret
= pthread_mutex_unlock(mutex
);
1272 NWRAP_LOG(NWRAP_LOG_ERROR
, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s",
1273 getpid(), getppid(), caller
, line
, name
, strerror(ret
));
1278 #define nwrap_bind_symbol_libc(sym_name) \
1279 if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1280 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1281 _nwrap_bind_symbol(NWRAP_LIBC, #sym_name); \
1284 #define nwrap_bind_symbol_libc_posix(sym_name) \
1285 if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1286 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1287 _nwrap_bind_symbol(NWRAP_LIBC, "__posix_" #sym_name); \
1290 #define nwrap_bind_symbol_libnsl(sym_name) \
1291 if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1292 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1293 _nwrap_bind_symbol(NWRAP_LIBNSL, #sym_name); \
1296 #define nwrap_bind_symbol_libsocket(sym_name) \
1297 if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
1298 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
1299 _nwrap_bind_symbol(NWRAP_LIBSOCKET, #sym_name); \
1302 static void nwrap_bind_symbol_all(void);
1304 /* INTERNAL HELPER FUNCTIONS */
1305 static void nwrap_lines_unload(struct nwrap_cache
*const nwrap
)
1309 nwrap_vector_foreach(item
, nwrap
->lines
, p
) {
1310 /* Maybe some vectors were merged ... */
1313 SAFE_FREE(nwrap
->lines
.items
);
1314 ZERO_STRUCTP(&nwrap
->lines
);
1320 * Functions expeciall from libc need to be loaded individually, you can't load
1321 * all at once or gdb will segfault at startup. The same applies to valgrind and
1322 * has probably something todo with with the linker.
1323 * So we need load each function at the point it is called the first time.
1325 static struct passwd
*libc_getpwnam(const char *name
)
1327 nwrap_bind_symbol_all();
1329 return nwrap_main_global
->libc
->symbols
._libc_getpwnam
.f(name
);
1332 #ifdef HAVE_GETPWNAM_R
1333 static int libc_getpwnam_r(const char *name
,
1337 struct passwd
**result
)
1339 nwrap_bind_symbol_all();
1341 return nwrap_main_global
->libc
->symbols
._libc_getpwnam_r
.f(name
,
1349 static struct passwd
*libc_getpwuid(uid_t uid
)
1351 nwrap_bind_symbol_all();
1353 return nwrap_main_global
->libc
->symbols
._libc_getpwuid
.f(uid
);
1356 #ifdef HAVE_GETPWUID_R
1357 static int libc_getpwuid_r(uid_t uid
,
1361 struct passwd
**result
)
1363 nwrap_bind_symbol_all();
1365 return nwrap_main_global
->libc
->symbols
._libc_getpwuid_r
.f(uid
,
1373 static inline void str_tolower(char *dst
, char *src
)
1375 register char *src_tmp
= src
;
1376 register char *dst_tmp
= dst
;
1378 while (*src_tmp
!= '\0') {
1379 *dst_tmp
= tolower(*src_tmp
);
1385 static bool str_tolower_copy(char **dst_name
, const char *const src_name
)
1389 if ((dst_name
== NULL
) || (src_name
== NULL
)) {
1393 h_name_lower
= strdup(src_name
);
1394 if (h_name_lower
== NULL
) {
1395 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Out of memory while strdup");
1399 str_tolower(h_name_lower
, h_name_lower
);
1400 *dst_name
= h_name_lower
;
1404 static void libc_setpwent(void)
1406 nwrap_bind_symbol_all();
1408 nwrap_main_global
->libc
->symbols
._libc_setpwent
.f();
1411 static struct passwd
*libc_getpwent(void)
1413 nwrap_bind_symbol_all();
1415 return nwrap_main_global
->libc
->symbols
._libc_getpwent
.f();
1418 #ifdef HAVE_GETPWENT_R
1419 # ifdef HAVE_SOLARIS_GETPWENT_R
1420 static struct passwd
*libc_getpwent_r(struct passwd
*pwdst
,
1424 nwrap_bind_symbol_all();
1426 return nwrap_main_global
->libc
->symbols
._libc_getpwent_r
.f(pwdst
,
1430 # else /* HAVE_SOLARIS_GETPWENT_R */
1431 static int libc_getpwent_r(struct passwd
*pwdst
,
1434 struct passwd
**pwdstp
)
1436 nwrap_bind_symbol_all();
1438 return nwrap_main_global
->libc
->symbols
._libc_getpwent_r
.f(pwdst
,
1443 # endif /* HAVE_SOLARIS_GETPWENT_R */
1444 #endif /* HAVE_GETPWENT_R */
1446 static void libc_endpwent(void)
1448 nwrap_bind_symbol_all();
1450 nwrap_main_global
->libc
->symbols
._libc_endpwent
.f();
1453 static int libc_initgroups(const char *user
, gid_t gid
)
1455 nwrap_bind_symbol_all();
1457 return nwrap_main_global
->libc
->symbols
._libc_initgroups
.f(user
, gid
);
1460 static struct group
*libc_getgrnam(const char *name
)
1462 nwrap_bind_symbol_all();
1464 return nwrap_main_global
->libc
->symbols
._libc_getgrnam
.f(name
);
1467 #ifdef HAVE_GETGRNAM_R
1468 static int libc_getgrnam_r(const char *name
,
1472 struct group
**result
)
1474 nwrap_bind_symbol_all();
1476 return nwrap_main_global
->libc
->symbols
._libc_getgrnam_r
.f(name
,
1484 static struct group
*libc_getgrgid(gid_t gid
)
1486 nwrap_bind_symbol_all();
1488 return nwrap_main_global
->libc
->symbols
._libc_getgrgid
.f(gid
);
1491 #ifdef HAVE_GETGRGID_R
1492 static int libc_getgrgid_r(gid_t gid
,
1496 struct group
**result
)
1498 nwrap_bind_symbol_all();
1500 return nwrap_main_global
->libc
->symbols
._libc_getgrgid_r
.f(gid
,
1508 static void libc_setgrent(void)
1510 nwrap_bind_symbol_all();
1512 nwrap_main_global
->libc
->symbols
._libc_setgrent
.f();
1515 static struct group
*libc_getgrent(void)
1517 nwrap_bind_symbol_all();
1519 return nwrap_main_global
->libc
->symbols
._libc_getgrent
.f();
1522 #ifdef HAVE_GETGRENT_R
1523 # ifdef HAVE_SOLARIS_GETGRENT_R
1524 static struct group
*libc_getgrent_r(struct group
*group
,
1528 nwrap_bind_symbol_all();
1530 return nwrap_main_global
->libc
->symbols
._libc_getgrent_r
.f(group
,
1534 # else /* HAVE_SOLARIS_GETGRENT_R */
1535 static int libc_getgrent_r(struct group
*group
,
1538 struct group
**result
)
1540 nwrap_bind_symbol_all();
1542 return nwrap_main_global
->libc
->symbols
._libc_getgrent_r
.f(group
,
1547 # endif /* HAVE_SOLARIS_GETGRENT_R */
1548 #endif /* HAVE_GETGRENT_R */
1550 static void libc_endgrent(void)
1552 nwrap_bind_symbol_all();
1554 nwrap_main_global
->libc
->symbols
._libc_endgrent
.f();
1557 #ifdef HAVE_GETGROUPLIST
1558 static int libc_getgrouplist(const char *user
,
1563 nwrap_bind_symbol_all();
1565 return nwrap_main_global
->libc
->symbols
._libc_getgrouplist
.f(user
,
1572 static void libc_sethostent(int stayopen
)
1574 nwrap_bind_symbol_all();
1576 nwrap_main_global
->libc
->symbols
._libc_sethostent
.f(stayopen
);
1579 static struct hostent
*libc_gethostent(void)
1581 nwrap_bind_symbol_all();
1583 return nwrap_main_global
->libc
->symbols
._libc_gethostent
.f();
1586 static void libc_endhostent(void)
1588 nwrap_bind_symbol_all();
1590 nwrap_main_global
->libc
->symbols
._libc_endhostent
.f();
1593 static struct hostent
*libc_gethostbyname(const char *name
)
1595 nwrap_bind_symbol_all();
1597 return nwrap_main_global
->libc
->symbols
._libc_gethostbyname
.f(name
);
1600 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1601 static struct hostent
*libc_gethostbyname2(const char *name
, int af
)
1603 nwrap_bind_symbol_all();
1605 return nwrap_main_global
->libc
->symbols
._libc_gethostbyname2
.f(name
, af
);
1609 #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
1610 static int libc_gethostbyname2_r(const char *name
,
1612 struct hostent
*ret
,
1615 struct hostent
**result
,
1618 nwrap_bind_symbol_all();
1620 return nwrap_main_global
->libc
->symbols
._libc_gethostbyname2_r
.f(name
,
1630 static struct hostent
*libc_gethostbyaddr(const void *addr
,
1634 nwrap_bind_symbol_all();
1636 return nwrap_main_global
->libc
->symbols
._libc_gethostbyaddr
.f(addr
,
1641 static int libc_gethostname(char *name
, size_t len
)
1643 nwrap_bind_symbol_all();
1645 return nwrap_main_global
->libc
->symbols
._libc_gethostname
.f(name
, len
);
1648 #ifdef HAVE_GETHOSTBYNAME_R
1649 static int libc_gethostbyname_r(const char *name
,
1650 struct hostent
*ret
,
1653 struct hostent
**result
,
1656 nwrap_bind_symbol_all();
1658 return nwrap_main_global
->libc
->symbols
._libc_gethostbyname_r
.f(name
,
1667 #ifdef HAVE_GETHOSTBYADDR_R
1668 static int libc_gethostbyaddr_r(const void *addr
,
1671 struct hostent
*ret
,
1674 struct hostent
**result
,
1677 nwrap_bind_symbol_all();
1679 return nwrap_main_global
->libc
->symbols
._libc_gethostbyaddr_r
.f(addr
,
1690 static int libc_getaddrinfo(const char *node
,
1691 const char *service
,
1692 const struct addrinfo
*hints
,
1693 struct addrinfo
**res
)
1695 nwrap_bind_symbol_all();
1697 return nwrap_main_global
->libc
->symbols
._libc_getaddrinfo
.f(node
,
1703 static int libc_getnameinfo(const struct sockaddr
*sa
,
1711 nwrap_bind_symbol_all();
1713 return nwrap_main_global
->libc
->symbols
._libc_getnameinfo
.f(sa
,
1722 static void __nwrap_bind_symbol_all_once(void)
1724 nwrap_bind_symbol_libc(getpwnam
);
1725 #ifdef HAVE_GETPWNAM_R
1726 # ifdef HAVE___POSIX_GETPWNAM_R
1727 nwrap_bind_symbol_libc_posix(getpwnam_r
);
1729 nwrap_bind_symbol_libc(getpwnam_r
);
1732 nwrap_bind_symbol_libc(getpwuid
);
1733 #ifdef HAVE_GETPWUID_R
1734 # ifdef HAVE___POSIX_GETPWUID_R
1735 nwrap_bind_symbol_libc_posix(getpwuid_r
);
1737 nwrap_bind_symbol_libc(getpwuid_r
);
1740 nwrap_bind_symbol_libc(setpwent
);
1741 nwrap_bind_symbol_libc(getpwent
);
1742 #ifdef HAVE_GETPWENT_R
1743 nwrap_bind_symbol_libc(getpwent_r
);
1745 nwrap_bind_symbol_libc(endpwent
);
1746 nwrap_bind_symbol_libc(initgroups
);
1747 nwrap_bind_symbol_libc(getgrnam
);
1748 #ifdef HAVE_GETGRNAM_R
1749 # ifdef HAVE___POSIX_GETGRNAM_R
1750 nwrap_bind_symbol_libc_posix(getgrnam_r
);
1752 nwrap_bind_symbol_libc(getgrnam_r
);
1755 nwrap_bind_symbol_libc(getgrgid
);
1756 #ifdef HAVE_GETGRGID_R
1757 # ifdef HAVE___POSIX_GETGRGID_R
1758 nwrap_bind_symbol_libc_posix(getgrgid_r
);
1760 nwrap_bind_symbol_libc(getgrgid_r
);
1763 nwrap_bind_symbol_libc(setgrent
);
1764 nwrap_bind_symbol_libc(getgrent
);
1765 nwrap_bind_symbol_libc(getgrent_r
);
1766 nwrap_bind_symbol_libc(endgrent
);
1767 nwrap_bind_symbol_libc(getgrouplist
);
1768 nwrap_bind_symbol_libnsl(sethostent
);
1769 nwrap_bind_symbol_libnsl(gethostent
);
1770 nwrap_bind_symbol_libnsl(endhostent
);
1771 nwrap_bind_symbol_libnsl(gethostbyname
);
1772 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1773 nwrap_bind_symbol_libnsl(gethostbyname2
);
1775 #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
1776 nwrap_bind_symbol_libnsl(gethostbyname2_r
);
1778 nwrap_bind_symbol_libnsl(gethostbyaddr
);
1779 nwrap_bind_symbol_libnsl(gethostname
);
1780 #ifdef HAVE_GETHOSTBYNAME_R
1781 nwrap_bind_symbol_libnsl(gethostbyname_r
);
1783 #ifdef HAVE_GETHOSTBYADDR_R
1784 nwrap_bind_symbol_libnsl(gethostbyaddr_r
);
1786 nwrap_bind_symbol_libsocket(getaddrinfo
);
1787 nwrap_bind_symbol_libsocket(getnameinfo
);
1790 static void nwrap_bind_symbol_all(void)
1792 static pthread_once_t all_symbol_binding_once
= PTHREAD_ONCE_INIT
;
1794 pthread_once(&all_symbol_binding_once
, __nwrap_bind_symbol_all_once
);
1797 /*********************************************************
1798 * NWRAP NSS MODULE LOADER FUNCTIONS
1799 *********************************************************/
1801 static void *_nwrap_bind_nss_module_symbol(struct nwrap_backend
*b
,
1802 const char *fn_name
)
1808 if (b
->so_handle
== NULL
) {
1809 NWRAP_LOG(NWRAP_LOG_ERROR
, "No handle");
1813 rc
= asprintf(&s
, "_nss_%s_%s", b
->name
, fn_name
);
1815 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
1819 res
= dlsym(b
->so_handle
, s
);
1821 NWRAP_LOG(NWRAP_LOG_WARN
,
1822 "Cannot find function %s in %s",
1829 #define nwrap_nss_module_bind_symbol(sym_name) \
1830 if (symbols->_nss_##sym_name.obj == NULL) { \
1831 symbols->_nss_##sym_name.obj = \
1832 _nwrap_bind_nss_module_symbol(b, #sym_name); \
1835 #define nwrap_nss_module_bind_symbol2(sym_name, alt_name) \
1836 if (symbols->_nss_##sym_name.obj == NULL) { \
1837 symbols->_nss_##sym_name.obj = \
1838 _nwrap_bind_nss_module_symbol(b, #alt_name); \
1841 static struct nwrap_nss_module_symbols
*
1842 nwrap_bind_nss_module_symbols(struct nwrap_backend
*b
)
1844 struct nwrap_nss_module_symbols
*symbols
;
1846 if (!b
->so_handle
) {
1850 symbols
= calloc(1, sizeof(struct nwrap_nss_module_symbols
));
1851 if (symbols
== NULL
) {
1855 nwrap_nss_module_bind_symbol(getpwnam_r
);
1856 nwrap_nss_module_bind_symbol(getpwuid_r
);
1857 nwrap_nss_module_bind_symbol(setpwent
);
1858 nwrap_nss_module_bind_symbol(getpwent_r
);
1859 nwrap_nss_module_bind_symbol(endpwent
);
1860 nwrap_nss_module_bind_symbol(initgroups_dyn
);
1861 nwrap_nss_module_bind_symbol(getgrnam_r
);
1862 nwrap_nss_module_bind_symbol(getgrgid_r
);
1863 nwrap_nss_module_bind_symbol(setgrent
);
1864 nwrap_nss_module_bind_symbol(getgrent_r
);
1865 nwrap_nss_module_bind_symbol(endgrent
);
1866 nwrap_nss_module_bind_symbol(gethostbyaddr_r
);
1867 nwrap_nss_module_bind_symbol(gethostbyname2_r
);
1872 static void *nwrap_load_module(const char *so_path
)
1876 if (!so_path
|| !strlen(so_path
)) {
1880 h
= dlopen(so_path
, RTLD_LAZY
);
1882 NWRAP_LOG(NWRAP_LOG_ERROR
,
1883 "Cannot open shared library %s",
1891 static bool nwrap_module_init(const char *name
,
1892 struct nwrap_ops
*ops
,
1893 const char *so_path
,
1894 size_t *num_backends
,
1895 struct nwrap_backend
**backends
)
1897 struct nwrap_backend
*b
= NULL
;
1898 size_t n
= *num_backends
+ 1;
1900 b
= realloc(*backends
, sizeof(struct nwrap_backend
) * n
);
1902 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
1907 b
= &((*backends
)[*num_backends
]);
1909 *b
= (struct nwrap_backend
) {
1915 if (so_path
!= NULL
) {
1916 b
->so_handle
= nwrap_load_module(so_path
);
1917 b
->symbols
= nwrap_bind_nss_module_symbols(b
);
1918 if (b
->symbols
== NULL
) {
1928 static void nwrap_libc_init(struct nwrap_main
*r
)
1930 r
->libc
= calloc(1, sizeof(struct nwrap_libc
));
1931 if (r
->libc
== NULL
) {
1932 printf("Failed to allocate memory for libc");
1937 static void nwrap_backend_init(struct nwrap_main
*r
)
1939 const char *module_so_path
= getenv("NSS_WRAPPER_MODULE_SO_PATH");
1940 const char *module_fn_name
= getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1942 r
->num_backends
= 0;
1945 if (!nwrap_module_init("files", &nwrap_files_ops
, NULL
,
1948 NWRAP_LOG(NWRAP_LOG_ERROR
,
1949 "Failed to initialize 'files' backend");
1953 if (module_so_path
!= NULL
&&
1954 module_so_path
[0] != '\0' &&
1955 module_fn_name
!= NULL
&&
1956 module_fn_name
[0] != '\0') {
1957 if (!nwrap_module_init(module_fn_name
,
1962 NWRAP_LOG(NWRAP_LOG_ERROR
,
1963 "Failed to initialize '%s' backend",
1970 static int _nss_wrapper_init_mutex(pthread_mutex_t
*m
, const char *name
)
1972 pthread_mutexattr_t ma
;
1973 bool need_destroy
= false;
1976 #define __CHECK(cmd) do { \
1979 NWRAP_LOG(NWRAP_LOG_ERROR, \
1980 "%s: %s - failed %d", \
1986 *m
= (pthread_mutex_t
)PTHREAD_MUTEX_INITIALIZER
;
1987 __CHECK(pthread_mutexattr_init(&ma
));
1988 need_destroy
= true;
1989 __CHECK(pthread_mutexattr_settype(&ma
, PTHREAD_MUTEX_ERRORCHECK
));
1990 __CHECK(pthread_mutex_init(m
, &ma
));
1993 pthread_mutexattr_destroy(&ma
);
1998 static void nwrap_init(void)
2002 size_t max_hostents_tmp
;
2005 nwrap_mutex_lock(&nwrap_initialized_mutex
);
2006 if (nwrap_initialized
) {
2007 nwrap_mutex_unlock(&nwrap_initialized_mutex
);
2012 * Still holding nwrap_initialized lock here.
2013 * We don't use NWRAP_(UN)LOCK_ALL macros here because we
2014 * want to avoid overhead when other threads do their job.
2016 nwrap_mutex_lock(&nwrap_global_mutex
);
2017 nwrap_mutex_lock(&nwrap_gr_global_mutex
);
2018 nwrap_mutex_lock(&nwrap_he_global_mutex
);
2019 nwrap_mutex_lock(&nwrap_pw_global_mutex
);
2020 nwrap_mutex_lock(&nwrap_sp_global_mutex
);
2022 nwrap_initialized
= true;
2024 env
= getenv("NSS_WRAPPER_MAX_HOSTENTS");
2026 max_hostents_tmp
= (size_t)strtoul(env
, &endptr
, 10);
2027 if ((*env
== '\0') ||
2028 (*endptr
!= '\0') ||
2029 (max_hostents_tmp
== 0)) {
2030 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2031 "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
2032 "value or value is too small. "
2033 "Using default value: %lu.",
2034 (unsigned long)max_hostents
);
2036 max_hostents
= max_hostents_tmp
;
2039 /* Initialize hash table */
2040 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2041 "Initializing hash table of size %lu items.",
2042 (unsigned long)max_hostents
);
2043 ok
= hcreate(max_hostents
);
2045 NWRAP_LOG(NWRAP_LOG_ERROR
,
2046 "Failed to initialize hash table");
2050 nwrap_main_global
= &__nwrap_main_global
;
2052 nwrap_libc_init(nwrap_main_global
);
2054 nwrap_backend_init(nwrap_main_global
);
2057 nwrap_pw_global
.cache
= &__nwrap_cache_pw
;
2059 nwrap_pw_global
.cache
->path
= getenv("NSS_WRAPPER_PASSWD");
2060 nwrap_pw_global
.cache
->fp
= NULL
;
2061 nwrap_pw_global
.cache
->fd
= -1;
2062 nwrap_pw_global
.cache
->private_data
= &nwrap_pw_global
;
2063 nwrap_pw_global
.cache
->parse_line
= nwrap_pw_parse_line
;
2064 nwrap_pw_global
.cache
->unload
= nwrap_pw_unload
;
2067 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2068 nwrap_sp_global
.cache
= &__nwrap_cache_sp
;
2070 nwrap_sp_global
.cache
->path
= getenv("NSS_WRAPPER_SHADOW");
2071 nwrap_sp_global
.cache
->fp
= NULL
;
2072 nwrap_sp_global
.cache
->fd
= -1;
2073 nwrap_sp_global
.cache
->private_data
= &nwrap_sp_global
;
2074 nwrap_sp_global
.cache
->parse_line
= nwrap_sp_parse_line
;
2075 nwrap_sp_global
.cache
->unload
= nwrap_sp_unload
;
2076 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2079 nwrap_gr_global
.cache
= &__nwrap_cache_gr
;
2081 nwrap_gr_global
.cache
->path
= getenv("NSS_WRAPPER_GROUP");
2082 nwrap_gr_global
.cache
->fp
= NULL
;
2083 nwrap_gr_global
.cache
->fd
= -1;
2084 nwrap_gr_global
.cache
->private_data
= &nwrap_gr_global
;
2085 nwrap_gr_global
.cache
->parse_line
= nwrap_gr_parse_line
;
2086 nwrap_gr_global
.cache
->unload
= nwrap_gr_unload
;
2089 nwrap_he_global
.cache
= &__nwrap_cache_he
;
2091 nwrap_he_global
.cache
->path
= getenv("NSS_WRAPPER_HOSTS");
2092 nwrap_he_global
.cache
->fp
= NULL
;
2093 nwrap_he_global
.cache
->fd
= -1;
2094 nwrap_he_global
.cache
->private_data
= &nwrap_he_global
;
2095 nwrap_he_global
.cache
->parse_line
= nwrap_he_parse_line
;
2096 nwrap_he_global
.cache
->unload
= nwrap_he_unload
;
2098 /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
2099 nwrap_mutex_unlock(&nwrap_sp_global_mutex
);
2100 nwrap_mutex_unlock(&nwrap_pw_global_mutex
);
2101 nwrap_mutex_unlock(&nwrap_he_global_mutex
);
2102 nwrap_mutex_unlock(&nwrap_gr_global_mutex
);
2103 nwrap_mutex_unlock(&nwrap_global_mutex
);
2104 nwrap_mutex_unlock(&nwrap_initialized_mutex
);
2107 bool nss_wrapper_enabled(void)
2111 if (nwrap_pw_global
.cache
->path
== NULL
||
2112 nwrap_pw_global
.cache
->path
[0] == '\0') {
2115 if (nwrap_gr_global
.cache
->path
== NULL
||
2116 nwrap_gr_global
.cache
->path
[0] == '\0') {
2123 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2124 bool nss_wrapper_shadow_enabled(void)
2128 if (nwrap_sp_global
.cache
->path
== NULL
||
2129 nwrap_sp_global
.cache
->path
[0] == '\0') {
2135 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2137 bool nss_wrapper_hosts_enabled(void)
2141 if (nwrap_he_global
.cache
->path
== NULL
||
2142 nwrap_he_global
.cache
->path
[0] == '\0') {
2149 static bool nwrap_hostname_enabled(void)
2153 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL
) {
2160 static bool nwrap_parse_file(struct nwrap_cache
*nwrap
)
2164 /* Unused but getline needs it */
2168 if (nwrap
->st
.st_size
== 0) {
2169 NWRAP_LOG(NWRAP_LOG_DEBUG
, "size == 0");
2173 /* Support for 32-bit system I guess */
2174 if (nwrap
->st
.st_size
> INT32_MAX
) {
2175 NWRAP_LOG(NWRAP_LOG_ERROR
,
2176 "Size[%u] larger than INT32_MAX",
2177 (unsigned)nwrap
->st
.st_size
);
2184 n
= getline(&line
, &len
, nwrap
->fp
);
2187 if (feof(nwrap
->fp
)) {
2191 NWRAP_LOG(NWRAP_LOG_ERROR
,
2192 "Unable to read line from file: %s",
2197 if (line
[n
- 1] == '\n') {
2201 if (line
[0] == '\0') {
2206 ok
= nwrap
->parse_line(nwrap
, line
);
2208 NWRAP_LOG(NWRAP_LOG_ERROR
,
2209 "Unable to parse line file: %s",
2215 /* Line is parsed without issues so add it to list */
2216 ok
= nwrap_vector_add_item(&(nwrap
->lines
), (void *const) line
);
2218 NWRAP_LOG(NWRAP_LOG_ERROR
,
2219 "Unable to add line to vector");
2223 /* This forces getline to allocate new memory for line. */
2225 } while (!feof(nwrap
->fp
));
2230 static void nwrap_files_cache_unload(struct nwrap_cache
*nwrap
)
2232 nwrap
->unload(nwrap
);
2234 nwrap_lines_unload(nwrap
);
2237 static bool nwrap_files_cache_reload(struct nwrap_cache
*nwrap
)
2242 bool retried
= false;
2244 assert(nwrap
!= NULL
);
2247 if (nwrap
->fd
< 0) {
2248 nwrap
->fp
= fopen(nwrap
->path
, "re");
2249 if (nwrap
->fp
== NULL
) {
2251 NWRAP_LOG(NWRAP_LOG_ERROR
,
2252 "Unable to open '%s' readonly %d:%s",
2253 nwrap
->path
, nwrap
->fd
,
2258 nwrap
->fd
= fileno(nwrap
->fp
);
2259 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Open '%s'", nwrap
->path
);
2262 ret
= fstat(nwrap
->fd
, &st
);
2263 if (ret
!= 0 && errno
== EBADF
&& retried
== false) {
2264 /* maybe something closed the fd on our behalf */
2265 NWRAP_LOG(NWRAP_LOG_TRACE
,
2266 "fstat(%s) - %d:%s - reopen",
2271 memset(&nwrap
->st
, 0, sizeof(nwrap
->st
));
2277 else if (ret
!= 0) {
2278 NWRAP_LOG(NWRAP_LOG_ERROR
,
2279 "fstat(%s) - %d:%s",
2289 if (retried
== false && st
.st_nlink
== 0) {
2290 /* maybe someone has replaced the file... */
2291 NWRAP_LOG(NWRAP_LOG_TRACE
,
2292 "st_nlink == 0, reopen %s",
2295 memset(&nwrap
->st
, 0, sizeof(nwrap
->st
));
2302 if (st
.st_mtime
== nwrap
->st
.st_mtime
) {
2303 NWRAP_LOG(NWRAP_LOG_TRACE
,
2304 "st_mtime[%u] hasn't changed, skip reload",
2305 (unsigned)st
.st_mtime
);
2309 NWRAP_LOG(NWRAP_LOG_TRACE
,
2310 "st_mtime has changed [%u] => [%u], start reload",
2311 (unsigned)st
.st_mtime
,
2312 (unsigned)nwrap
->st
.st_mtime
);
2316 nwrap_files_cache_unload(nwrap
);
2318 ok
= nwrap_parse_file(nwrap
);
2320 NWRAP_LOG(NWRAP_LOG_ERROR
, "Failed to reload %s", nwrap
->path
);
2321 nwrap_files_cache_unload(nwrap
);
2325 NWRAP_LOG(NWRAP_LOG_TRACE
, "Reloaded %s", nwrap
->path
);
2330 * the caller has to call nwrap_unload() on failure
2332 static bool nwrap_pw_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2334 struct nwrap_pw
*nwrap_pw
;
2341 nwrap_pw
= (struct nwrap_pw
*)nwrap
->private_data
;
2343 list_size
= sizeof(*nwrap_pw
->list
) * (nwrap_pw
->num
+1);
2344 pw
= (struct passwd
*)realloc(nwrap_pw
->list
, list_size
);
2346 NWRAP_LOG(NWRAP_LOG_ERROR
,
2347 "realloc(%u) failed",
2348 (unsigned)list_size
);
2351 nwrap_pw
->list
= pw
;
2353 pw
= &nwrap_pw
->list
[nwrap_pw
->num
];
2360 NWRAP_LOG(NWRAP_LOG_ERROR
,
2361 "Invalid line[%s]: '%s'",
2371 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]\n", pw
->pw_name
);
2376 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2384 NWRAP_LOG(NWRAP_LOG_TRACE
, "password[%s]\n", pw
->pw_passwd
);
2389 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2395 pw
->pw_uid
= (uid_t
)strtoul(c
, &e
, 10);
2397 NWRAP_LOG(NWRAP_LOG_ERROR
,
2398 "Invalid line[%s]: '%s' - %s",
2399 line
, c
, strerror(errno
));
2403 NWRAP_LOG(NWRAP_LOG_ERROR
,
2404 "Invalid line[%s]: '%s' - %s",
2405 line
, c
, strerror(errno
));
2409 NWRAP_LOG(NWRAP_LOG_ERROR
,
2410 "Invalid line[%s]: '%s' - %s",
2411 line
, c
, strerror(errno
));
2416 NWRAP_LOG(NWRAP_LOG_TRACE
, "uid[%u]", pw
->pw_uid
);
2421 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2427 pw
->pw_gid
= (gid_t
)strtoul(c
, &e
, 10);
2429 NWRAP_LOG(NWRAP_LOG_ERROR
,
2430 "Invalid line[%s]: '%s' - %s",
2431 line
, c
, strerror(errno
));
2435 NWRAP_LOG(NWRAP_LOG_ERROR
,
2436 "Invalid line[%s]: '%s' - %s",
2437 line
, c
, strerror(errno
));
2441 NWRAP_LOG(NWRAP_LOG_ERROR
,
2442 "Invalid line[%s]: '%s' - %s",
2443 line
, c
, strerror(errno
));
2448 NWRAP_LOG(NWRAP_LOG_TRACE
, "gid[%u]\n", pw
->pw_gid
);
2450 #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
2451 pw
->pw_class
= discard_const_p(char, "");
2453 NWRAP_LOG(NWRAP_LOG_TRACE
, "class[%s]", pw
->pw_class
);
2454 #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
2456 #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
2459 NWRAP_LOG(NWRAP_LOG_TRACE
,
2461 (unsigned long)pw
->pw_change
);
2462 #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
2464 #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
2467 NWRAP_LOG(NWRAP_LOG_TRACE
,
2469 (unsigned long)pw
->pw_expire
);
2470 #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
2475 NWRAP_LOG(NWRAP_LOG_ERROR
, "invalid line[%s]: '%s'", line
, c
);
2483 NWRAP_LOG(NWRAP_LOG_TRACE
, "gecos[%s]", pw
->pw_gecos
);
2488 NWRAP_LOG(NWRAP_LOG_ERROR
, "'%s'", c
);
2496 NWRAP_LOG(NWRAP_LOG_TRACE
, "dir[%s]", pw
->pw_dir
);
2500 NWRAP_LOG(NWRAP_LOG_TRACE
, "shell[%s]", pw
->pw_shell
);
2502 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2503 "Added user[%s:%s:%u:%u:%s:%s:%s]",
2504 pw
->pw_name
, pw
->pw_passwd
,
2505 pw
->pw_uid
, pw
->pw_gid
,
2506 pw
->pw_gecos
, pw
->pw_dir
, pw
->pw_shell
);
2512 static void nwrap_pw_unload(struct nwrap_cache
*nwrap
)
2514 struct nwrap_pw
*nwrap_pw
;
2515 nwrap_pw
= (struct nwrap_pw
*)nwrap
->private_data
;
2517 SAFE_FREE(nwrap_pw
->list
);
2522 static int nwrap_pw_copy_r(const struct passwd
*src
, struct passwd
*dst
,
2523 char *buf
, size_t buflen
, struct passwd
**dstp
)
2529 first
= src
->pw_name
;
2531 last
= src
->pw_shell
;
2532 while (*last
) last
++;
2534 ofs
= PTR_DIFF(last
+ 1, first
);
2536 if (ofs
> (off_t
) buflen
) {
2540 memcpy(buf
, first
, ofs
);
2542 ofs
= PTR_DIFF(src
->pw_name
, first
);
2543 dst
->pw_name
= buf
+ ofs
;
2544 ofs
= PTR_DIFF(src
->pw_passwd
, first
);
2545 dst
->pw_passwd
= buf
+ ofs
;
2546 dst
->pw_uid
= src
->pw_uid
;
2547 dst
->pw_gid
= src
->pw_gid
;
2548 #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
2549 ofs
= PTR_DIFF(src
->pw_class
, first
);
2550 dst
->pw_class
= buf
+ ofs
;
2551 #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
2553 #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
2555 #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
2557 #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
2559 #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
2561 ofs
= PTR_DIFF(src
->pw_gecos
, first
);
2562 dst
->pw_gecos
= buf
+ ofs
;
2563 ofs
= PTR_DIFF(src
->pw_dir
, first
);
2564 dst
->pw_dir
= buf
+ ofs
;
2565 ofs
= PTR_DIFF(src
->pw_shell
, first
);
2566 dst
->pw_shell
= buf
+ ofs
;
2575 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2576 static bool nwrap_sp_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2578 struct nwrap_sp
*nwrap_sp
;
2585 nwrap_sp
= (struct nwrap_sp
*)nwrap
->private_data
;
2587 list_size
= sizeof(*nwrap_sp
->list
) * (nwrap_sp
->num
+1);
2588 sp
= (struct spwd
*)realloc(nwrap_sp
->list
, list_size
);
2590 NWRAP_LOG(NWRAP_LOG_ERROR
,
2591 "realloc(%u) failed",
2592 (unsigned)list_size
);
2595 nwrap_sp
->list
= sp
;
2597 sp
= &nwrap_sp
->list
[nwrap_sp
->num
];
2604 NWRAP_LOG(NWRAP_LOG_ERROR
,
2605 "name -- Invalid line[%s]: '%s'",
2615 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]\n", sp
->sp_namp
);
2620 NWRAP_LOG(NWRAP_LOG_ERROR
,
2621 "pwd -- Invalid line[%s]: '%s'",
2638 NWRAP_LOG(NWRAP_LOG_ERROR
,
2639 "lstchg -- Invalid line[%s]: '%s'",
2646 sp
->sp_lstchg
= strtol(c
, &e
, 10);
2648 NWRAP_LOG(NWRAP_LOG_ERROR
,
2649 "lstchg -- Invalid line[%s]: '%s' - %s",
2650 line
, c
, strerror(errno
));
2654 NWRAP_LOG(NWRAP_LOG_ERROR
,
2655 "lstchg -- Invalid line[%s]: '%s' - %s",
2656 line
, c
, strerror(errno
));
2660 NWRAP_LOG(NWRAP_LOG_ERROR
,
2661 "lstchg -- Invalid line[%s]: '%s' - %s",
2662 line
, c
, strerror(errno
));
2675 NWRAP_LOG(NWRAP_LOG_ERROR
,
2676 "min -- Invalid line[%s]: '%s'",
2683 sp
->sp_min
= strtol(c
, &e
, 10);
2685 NWRAP_LOG(NWRAP_LOG_ERROR
,
2686 "min -- Invalid line[%s]: '%s' - %s",
2687 line
, c
, strerror(errno
));
2691 NWRAP_LOG(NWRAP_LOG_ERROR
,
2692 "min -- Invalid line[%s]: '%s' - %s",
2693 line
, c
, strerror(errno
));
2697 NWRAP_LOG(NWRAP_LOG_ERROR
,
2698 "min -- Invalid line[%s]: '%s' - %s",
2699 line
, c
, strerror(errno
));
2712 NWRAP_LOG(NWRAP_LOG_ERROR
,
2713 "max -- Invalid line[%s]: '%s'",
2720 sp
->sp_max
= strtol(c
, &e
, 10);
2722 NWRAP_LOG(NWRAP_LOG_ERROR
,
2723 "max -- Invalid line[%s]: '%s' - %s",
2724 line
, c
, strerror(errno
));
2728 NWRAP_LOG(NWRAP_LOG_ERROR
,
2729 "max -- Invalid line[%s]: '%s' - %s",
2730 line
, c
, strerror(errno
));
2734 NWRAP_LOG(NWRAP_LOG_ERROR
,
2735 "max -- Invalid line[%s]: '%s' - %s",
2736 line
, c
, strerror(errno
));
2749 NWRAP_LOG(NWRAP_LOG_ERROR
,
2750 "warn -- Invalid line[%s]: '%s'",
2757 sp
->sp_warn
= strtol(c
, &e
, 10);
2759 NWRAP_LOG(NWRAP_LOG_ERROR
,
2760 "warn -- Invalid line[%s]: '%s' - %s",
2761 line
, c
, strerror(errno
));
2765 NWRAP_LOG(NWRAP_LOG_ERROR
,
2766 "warn -- Invalid line[%s]: '%s' - %s",
2767 line
, c
, strerror(errno
));
2771 NWRAP_LOG(NWRAP_LOG_ERROR
,
2772 "warn -- Invalid line[%s]: '%s' - %s",
2773 line
, c
, strerror(errno
));
2786 NWRAP_LOG(NWRAP_LOG_ERROR
,
2787 "inact -- Invalid line[%s]: '%s'",
2794 sp
->sp_inact
= strtol(c
, &e
, 10);
2796 NWRAP_LOG(NWRAP_LOG_ERROR
,
2797 "inact -- Invalid line[%s]: '%s' - %s",
2798 line
, c
, strerror(errno
));
2802 NWRAP_LOG(NWRAP_LOG_ERROR
,
2803 "inact -- Invalid line[%s]: '%s' - %s",
2804 line
, c
, strerror(errno
));
2808 NWRAP_LOG(NWRAP_LOG_ERROR
,
2809 "inact -- Invalid line[%s]: '%s' - %s",
2810 line
, c
, strerror(errno
));
2823 NWRAP_LOG(NWRAP_LOG_ERROR
,
2824 "expire -- Invalid line[%s]: '%s'",
2831 sp
->sp_expire
= strtol(c
, &e
, 10);
2833 NWRAP_LOG(NWRAP_LOG_ERROR
,
2834 "expire -- Invalid line[%s]: '%s' - %s",
2835 line
, c
, strerror(errno
));
2839 NWRAP_LOG(NWRAP_LOG_ERROR
,
2840 "expire -- Invalid line[%s]: '%s' - %s",
2841 line
, c
, strerror(errno
));
2845 NWRAP_LOG(NWRAP_LOG_ERROR
,
2846 "expire -- Invalid line[%s]: '%s' - %s",
2847 line
, c
, strerror(errno
));
2857 static void nwrap_sp_unload(struct nwrap_cache
*nwrap
)
2859 struct nwrap_sp
*nwrap_sp
;
2860 nwrap_sp
= (struct nwrap_sp
*)nwrap
->private_data
;
2862 SAFE_FREE(nwrap_sp
->list
);
2866 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2869 * the caller has to call nwrap_unload() on failure
2871 static bool nwrap_gr_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2873 struct nwrap_gr
*nwrap_gr
;
2881 nwrap_gr
= (struct nwrap_gr
*)nwrap
->private_data
;
2883 list_size
= sizeof(*nwrap_gr
->list
) * (nwrap_gr
->num
+1);
2884 gr
= (struct group
*)realloc(nwrap_gr
->list
, list_size
);
2886 NWRAP_LOG(NWRAP_LOG_ERROR
, "realloc failed");
2889 nwrap_gr
->list
= gr
;
2891 gr
= &nwrap_gr
->list
[nwrap_gr
->num
];
2898 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2906 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]", gr
->gr_name
);
2911 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2919 NWRAP_LOG(NWRAP_LOG_TRACE
, "password[%s]", gr
->gr_passwd
);
2924 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2930 gr
->gr_gid
= (gid_t
)strtoul(c
, &e
, 10);
2932 NWRAP_LOG(NWRAP_LOG_ERROR
,
2933 "Invalid line[%s]: '%s' - %s",
2934 line
, c
, strerror(errno
));
2938 NWRAP_LOG(NWRAP_LOG_ERROR
,
2939 "Invalid line[%s]: '%s' - %s",
2940 line
, c
, strerror(errno
));
2944 NWRAP_LOG(NWRAP_LOG_ERROR
,
2945 "Invalid line[%s]: '%s' - %s",
2946 line
, c
, strerror(errno
));
2951 NWRAP_LOG(NWRAP_LOG_TRACE
, "gid[%u]", gr
->gr_gid
);
2954 gr
->gr_mem
= (char **)malloc(sizeof(char *));
2956 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
2959 gr
->gr_mem
[0] = NULL
;
2961 for(nummem
= 0; p
!= NULL
&& p
[0] != '\0'; nummem
++) {
2971 if (strlen(c
) == 0) {
2975 m_size
= sizeof(char *) * (nummem
+2);
2976 m
= (char **)realloc(gr
->gr_mem
, m_size
);
2978 NWRAP_LOG(NWRAP_LOG_ERROR
,
2979 "realloc(%zd) failed",
2984 gr
->gr_mem
[nummem
] = c
;
2985 gr
->gr_mem
[nummem
+1] = NULL
;
2987 NWRAP_LOG(NWRAP_LOG_TRACE
,
2989 nummem
, gr
->gr_mem
[nummem
]);
2992 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2993 "Added group[%s:%s:%u:] with %u members",
2994 gr
->gr_name
, gr
->gr_passwd
, gr
->gr_gid
, nummem
);
3000 static void nwrap_gr_unload(struct nwrap_cache
*nwrap
)
3003 struct nwrap_gr
*nwrap_gr
;
3004 nwrap_gr
= (struct nwrap_gr
*)nwrap
->private_data
;
3006 if (nwrap_gr
->list
) {
3007 for (i
=0; i
< nwrap_gr
->num
; i
++) {
3008 SAFE_FREE(nwrap_gr
->list
[i
].gr_mem
);
3010 SAFE_FREE(nwrap_gr
->list
);
3017 static struct nwrap_entlist
*nwrap_entlist_init(struct nwrap_entdata
*ed
)
3019 struct nwrap_entlist
*el
;
3022 NWRAP_LOG(NWRAP_LOG_ERROR
,
3023 "entry is NULL, can't create list item");
3027 el
= (struct nwrap_entlist
*)malloc(sizeof(struct nwrap_entlist
));
3029 NWRAP_LOG(NWRAP_LOG_ERROR
, "malloc failed");
3039 static bool nwrap_ed_inventarize_add_new(char *const h_name
,
3040 struct nwrap_entdata
*const ed
)
3044 struct nwrap_entlist
*el
;
3047 if (h_name
== NULL
) {
3048 NWRAP_LOG(NWRAP_LOG_ERROR
, "h_name NULL - can't add");
3052 el
= nwrap_entlist_init(ed
);
3058 e
.data
= (void *)el
;
3060 p
= hsearch(e
, ENTER
);
3062 NWRAP_LOG(NWRAP_LOG_ERROR
,
3063 "Hash table is full (%s)!",
3068 ok
= nwrap_vector_add_item(&(nwrap_he_global
.lists
), (void *)el
);
3070 NWRAP_LOG(NWRAP_LOG_ERROR
,
3071 "Failed to add list entry to vector.");
3078 static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata
*const ed
,
3079 struct nwrap_entlist
*const el
)
3081 struct nwrap_entlist
*cursor
;
3082 struct nwrap_entlist
*el_new
;
3085 NWRAP_LOG(NWRAP_LOG_ERROR
, "list is NULL, can not add");
3090 for (cursor
= el
; cursor
->next
!= NULL
; cursor
= cursor
->next
)
3092 if (cursor
->ed
== ed
) {
3093 /* The entry already exists in this list. */
3098 if (cursor
->ed
== ed
) {
3099 /* The entry already exists in this list. */
3103 el_new
= nwrap_entlist_init(ed
);
3104 if (el_new
== NULL
) {
3108 cursor
->next
= el_new
;
3112 static bool nwrap_ed_inventarize(char *const name
,
3113 struct nwrap_entdata
*const ed
)
3122 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching name: %s", e
.key
);
3124 p
= hsearch(e
, FIND
);
3126 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found. Adding...", name
);
3127 ok
= nwrap_ed_inventarize_add_new(name
, ed
);
3129 struct nwrap_entlist
*el
= (struct nwrap_entlist
*)p
->data
;
3131 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s found. Add record to list.", name
);
3132 ok
= nwrap_ed_inventarize_add_to_existing(ed
, el
);
3138 static bool nwrap_add_hname(struct nwrap_entdata
*const ed
)
3140 char *const h_name
= (char *const)(ed
->ht
.h_name
);
3144 ok
= nwrap_ed_inventarize(h_name
, ed
);
3149 if (ed
->ht
.h_aliases
== NULL
) {
3153 /* Itemize aliases */
3154 for (i
= 0; ed
->ht
.h_aliases
[i
] != NULL
; ++i
) {
3157 h_name_alias
= ed
->ht
.h_aliases
[i
];
3159 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Add alias: %s", h_name_alias
);
3161 if (!nwrap_ed_inventarize(h_name_alias
, ed
)) {
3162 NWRAP_LOG(NWRAP_LOG_ERROR
,
3163 "Unable to add alias: %s", h_name_alias
);
3171 static bool nwrap_he_parse_line(struct nwrap_cache
*nwrap
, char *line
)
3173 struct nwrap_he
*nwrap_he
= (struct nwrap_he
*)nwrap
->private_data
;
3174 bool do_aliases
= true;
3175 ssize_t aliases_count
= 0;
3183 struct nwrap_entdata
*ed
= (struct nwrap_entdata
*)
3184 malloc(sizeof(struct nwrap_entdata
));
3186 NWRAP_LOG(NWRAP_LOG_ERROR
,
3187 "Unable to allocate memory for nwrap_entdata");
3198 /* Walk to first char */
3199 for (p
= i
; *p
!= '.' && *p
!= ':' && !isxdigit((int) *p
); p
++) {
3201 NWRAP_LOG(NWRAP_LOG_ERROR
,
3202 "Invalid line[%s]: '%s'",
3209 for (i
= p
; !isspace((int)*p
); p
++) {
3211 NWRAP_LOG(NWRAP_LOG_ERROR
,
3212 "Invalid line[%s]: '%s'",
3221 if (inet_pton(AF_INET
, i
, ed
->addr
.host_addr
)) {
3222 ed
->ht
.h_addrtype
= AF_INET
;
3223 ed
->ht
.h_length
= 4;
3225 } else if (inet_pton(AF_INET6
, i
, ed
->addr
.host_addr
)) {
3226 ed
->ht
.h_addrtype
= AF_INET6
;
3227 ed
->ht
.h_length
= 16;
3230 NWRAP_LOG(NWRAP_LOG_ERROR
,
3231 "Invalid line[%s]: '%s'",
3239 ok
= nwrap_vector_add_item(&(ed
->nwrap_addrdata
),
3240 (void *const)ed
->addr
.host_addr
);
3242 NWRAP_LOG(NWRAP_LOG_ERROR
, "Unable to add addrdata to vector");
3246 ed
->ht
.h_addr_list
= nwrap_vector_head(&ed
->nwrap_addrdata
);
3254 /* Walk to first char */
3255 for (n
= p
; *p
!= '_' && !isalnum((int) *p
); p
++) {
3257 NWRAP_LOG(NWRAP_LOG_ERROR
,
3258 "Invalid line[%s]: '%s'",
3266 for (n
= p
; !isspace((int)*p
); p
++) {
3275 /* Convert to lowercase. This operate on same memory region */
3279 /* glib's getent always dereferences he->h_aliases */
3280 ed
->ht
.h_aliases
= malloc(sizeof(char *));
3281 if (ed
->ht
.h_aliases
== NULL
) {
3285 ed
->ht
.h_aliases
[0] = NULL
;
3290 while (do_aliases
) {
3296 /* Walk to first char */
3297 for (a
= p
; *p
!= '_' && !isalnum((int) *p
); p
++) {
3303 /* Only trailing spaces are left */
3308 for (a
= p
; !isspace((int)*p
); p
++) {
3317 aliases
= realloc(ed
->ht
.h_aliases
, sizeof(char *) * (aliases_count
+ 2));
3318 if (aliases
== NULL
) {
3322 ed
->ht
.h_aliases
= aliases
;
3325 aliases
[aliases_count
] = a
;
3326 aliases
[aliases_count
+ 1] = NULL
;
3331 ok
= nwrap_vector_add_item(&(nwrap_he
->entries
), (void *const)ed
);
3333 NWRAP_LOG(NWRAP_LOG_ERROR
, "Unable to add entry to vector");
3338 ed
->aliases_count
= aliases_count
;
3339 /* Inventarize item */
3340 ok
= nwrap_add_hname(ed
);
3345 ok
= nwrap_ed_inventarize(ip
, ed
);
3354 static void nwrap_he_unload(struct nwrap_cache
*nwrap
)
3356 struct nwrap_he
*nwrap_he
=
3357 (struct nwrap_he
*)nwrap
->private_data
;
3358 struct nwrap_entdata
*ed
;
3359 struct nwrap_entlist
*el
;
3363 nwrap_vector_foreach (ed
, nwrap_he
->entries
, i
)
3365 SAFE_FREE(ed
->nwrap_addrdata
.items
);
3366 SAFE_FREE(ed
->ht
.h_aliases
);
3369 SAFE_FREE(nwrap_he
->entries
.items
);
3370 nwrap_he
->entries
.count
= nwrap_he
->entries
.capacity
= 0;
3372 nwrap_vector_foreach(el
, nwrap_he
->lists
, i
)
3374 while (el
!= NULL
) {
3375 struct nwrap_entlist
*el_next
;
3382 SAFE_FREE(nwrap_he
->lists
.items
);
3383 nwrap_he
->lists
.count
= nwrap_he
->lists
.capacity
= 0;
3389 * If we unload the file, the pointers in the hash table point to
3390 * invalid memory. So we need to destroy the hash table and recreate
3394 rc
= hcreate(max_hostents
);
3396 NWRAP_LOG(NWRAP_LOG_ERROR
, "Failed to initialize hash table");
3402 /* user functions */
3403 static struct passwd
*nwrap_files_getpwnam(struct nwrap_backend
*b
,
3409 (void) b
; /* unused */
3411 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Lookup user %s in files", name
);
3413 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
3415 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
3419 for (i
=0; i
<nwrap_pw_global
.num
; i
++) {
3420 if (strcmp(nwrap_pw_global
.list
[i
].pw_name
, name
) == 0) {
3421 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] found", name
);
3422 return &nwrap_pw_global
.list
[i
];
3424 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3425 "user[%s] does not match [%s]",
3427 nwrap_pw_global
.list
[i
].pw_name
);
3430 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] not found\n", name
);
3436 static int nwrap_files_getpwnam_r(struct nwrap_backend
*b
,
3437 const char *name
, struct passwd
*pwdst
,
3438 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
3442 pw
= nwrap_files_getpwnam(b
, name
);
3450 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
3453 static struct passwd
*nwrap_files_getpwuid(struct nwrap_backend
*b
,
3459 (void) b
; /* unused */
3461 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
3463 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
3467 for (i
=0; i
<nwrap_pw_global
.num
; i
++) {
3468 if (nwrap_pw_global
.list
[i
].pw_uid
== uid
) {
3469 NWRAP_LOG(NWRAP_LOG_DEBUG
, "uid[%u] found", uid
);
3470 return &nwrap_pw_global
.list
[i
];
3472 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3473 "uid[%u] does not match [%u]",
3475 nwrap_pw_global
.list
[i
].pw_uid
);
3478 NWRAP_LOG(NWRAP_LOG_DEBUG
, "uid[%u] not found\n", uid
);
3484 static int nwrap_files_getpwuid_r(struct nwrap_backend
*b
,
3485 uid_t uid
, struct passwd
*pwdst
,
3486 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
3490 pw
= nwrap_files_getpwuid(b
, uid
);
3498 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
3501 /* user enum functions */
3502 static void nwrap_files_setpwent(struct nwrap_backend
*b
)
3504 (void) b
; /* unused */
3506 nwrap_pw_global
.idx
= 0;
3509 static struct passwd
*nwrap_files_getpwent(struct nwrap_backend
*b
)
3513 (void) b
; /* unused */
3515 if (nwrap_pw_global
.idx
== 0) {
3517 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
3519 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
3524 if (nwrap_pw_global
.idx
>= nwrap_pw_global
.num
) {
3529 pw
= &nwrap_pw_global
.list
[nwrap_pw_global
.idx
++];
3531 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3532 "return user[%s] uid[%u]",
3533 pw
->pw_name
, pw
->pw_uid
);
3538 static int nwrap_files_getpwent_r(struct nwrap_backend
*b
,
3539 struct passwd
*pwdst
, char *buf
,
3540 size_t buflen
, struct passwd
**pwdstp
)
3544 pw
= nwrap_files_getpwent(b
);
3552 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
3555 static void nwrap_files_endpwent(struct nwrap_backend
*b
)
3557 (void) b
; /* unused */
3559 nwrap_pw_global
.idx
= 0;
3564 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
3566 #ifdef HAVE_SETSPENT
3567 static void nwrap_files_setspent(void)
3569 nwrap_sp_global
.idx
= 0;
3572 static struct spwd
*nwrap_files_getspent(void)
3576 if (nwrap_sp_global
.idx
== 0) {
3579 ok
= nwrap_files_cache_reload(nwrap_sp_global
.cache
);
3581 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading shadow file");
3586 if (nwrap_sp_global
.idx
>= nwrap_sp_global
.num
) {
3591 sp
= &nwrap_sp_global
.list
[nwrap_sp_global
.idx
++];
3593 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3600 static void nwrap_files_endspent(void)
3602 nwrap_sp_global
.idx
= 0;
3604 #endif /* HAVE_SETSPENT */
3606 static struct spwd
*nwrap_files_getspnam(const char *name
)
3611 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Lookup user %s in files", name
);
3613 ok
= nwrap_files_cache_reload(nwrap_sp_global
.cache
);
3615 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading shadow file");
3619 for (i
=0; i
<nwrap_sp_global
.num
; i
++) {
3620 if (strcmp(nwrap_sp_global
.list
[i
].sp_namp
, name
) == 0) {
3621 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] found", name
);
3622 return &nwrap_sp_global
.list
[i
];
3624 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3625 "user[%s] does not match [%s]",
3627 nwrap_sp_global
.list
[i
].sp_namp
);
3630 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] not found\n", name
);
3635 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
3637 /* misc functions */
3638 static int nwrap_files_initgroups_dyn(struct nwrap_backend
*b
,
3650 (void)errnop
; /* unused */
3651 nwrap_files_setgrent(b
);
3652 while ((grp
= nwrap_files_getgrent(b
)) != NULL
) {
3653 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3654 "Inspecting %s for group membership",
3657 for (i
=0; grp
->gr_mem
&& grp
->gr_mem
[i
] != NULL
; i
++) {
3658 if (group
!= grp
->gr_gid
&&
3659 (strcmp(user
, grp
->gr_mem
[i
]) == 0)) {
3660 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3661 "%s is member of %s",
3665 if (*start
== *size
) {
3669 newsize
= 2 * (*size
);
3670 if (limit
> 0 && newsize
> limit
) {
3671 newsize
= MAX(limit
, *size
);
3673 newgroups
= (gid_t
*) realloc((*groups
),
3674 newsize
* sizeof(**groups
));
3679 *groups
= newgroups
;
3682 (*groups
)[*start
] = grp
->gr_gid
;
3688 nwrap_files_endgrent(b
);
3692 /* group functions */
3693 static struct group
*nwrap_files_getgrnam(struct nwrap_backend
*b
,
3699 (void) b
; /* unused */
3701 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3703 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3707 for (i
=0; i
<nwrap_gr_global
.num
; i
++) {
3708 if (strcmp(nwrap_gr_global
.list
[i
].gr_name
, name
) == 0) {
3709 NWRAP_LOG(NWRAP_LOG_DEBUG
, "group[%s] found", name
);
3710 return &nwrap_gr_global
.list
[i
];
3712 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3713 "group[%s] does not match [%s]",
3715 nwrap_gr_global
.list
[i
].gr_name
);
3718 NWRAP_LOG(NWRAP_LOG_DEBUG
, "group[%s] not found", name
);
3724 static int nwrap_files_getgrnam_r(struct nwrap_backend
*b
,
3725 const char *name
, struct group
*grdst
,
3726 char *buf
, size_t buflen
, struct group
**grdstp
)
3730 gr
= nwrap_files_getgrnam(b
, name
);
3738 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3741 static struct group
*nwrap_files_getgrgid(struct nwrap_backend
*b
,
3747 (void) b
; /* unused */
3749 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3751 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3755 for (i
=0; i
<nwrap_gr_global
.num
; i
++) {
3756 if (nwrap_gr_global
.list
[i
].gr_gid
== gid
) {
3757 NWRAP_LOG(NWRAP_LOG_DEBUG
, "gid[%u] found", gid
);
3758 return &nwrap_gr_global
.list
[i
];
3760 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3761 "gid[%u] does not match [%u]",
3763 nwrap_gr_global
.list
[i
].gr_gid
);
3766 NWRAP_LOG(NWRAP_LOG_DEBUG
, "gid[%u] not found", gid
);
3772 static int nwrap_files_getgrgid_r(struct nwrap_backend
*b
,
3773 gid_t gid
, struct group
*grdst
,
3774 char *buf
, size_t buflen
, struct group
**grdstp
)
3778 gr
= nwrap_files_getgrgid(b
, gid
);
3786 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3789 /* group enum functions */
3790 static void nwrap_files_setgrent(struct nwrap_backend
*b
)
3792 (void) b
; /* unused */
3794 nwrap_gr_global
.idx
= 0;
3797 static struct group
*nwrap_files_getgrent(struct nwrap_backend
*b
)
3801 (void) b
; /* unused */
3803 if (nwrap_gr_global
.idx
== 0) {
3806 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3808 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3813 if (nwrap_gr_global
.idx
>= nwrap_gr_global
.num
) {
3818 gr
= &nwrap_gr_global
.list
[nwrap_gr_global
.idx
++];
3820 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3821 "return group[%s] gid[%u]",
3822 gr
->gr_name
, gr
->gr_gid
);
3827 static int nwrap_files_getgrent_r(struct nwrap_backend
*b
,
3828 struct group
*grdst
, char *buf
,
3829 size_t buflen
, struct group
**grdstp
)
3833 gr
= nwrap_files_getgrent(b
);
3841 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3844 static void nwrap_files_endgrent(struct nwrap_backend
*b
)
3846 (void) b
; /* unused */
3848 nwrap_gr_global
.idx
= 0;
3851 /* hosts functions */
3852 static int nwrap_files_internal_gethostbyname(const char *name
, int af
,
3853 struct hostent
*result
,
3854 struct nwrap_vector
*addr_list
)
3856 struct nwrap_entlist
*el
;
3861 char canon_name
[DNS_NAME_MAX
] = { 0 };
3863 bool he_found
= false;
3867 * We need to make sure we have zeroed return pointer for consumers
3868 * which don't check return values, e.g. OpenLDAP.
3870 ZERO_STRUCTP(result
);
3872 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
3874 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
3878 name_len
= strlen(name
);
3879 if (name_len
< sizeof(canon_name
) && name
[name_len
- 1] == '.') {
3880 memcpy(canon_name
, name
, name_len
- 1);
3881 canon_name
[name_len
] = '\0';
3885 if (!str_tolower_copy(&h_name_lower
, name
)) {
3886 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3887 "Out of memory while converting to lower case");
3891 /* Look at hash table for element */
3892 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching for name: %s", h_name_lower
);
3893 e
.key
= h_name_lower
;
3895 e_p
= hsearch(e
, FIND
);
3897 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found.", h_name_lower
);
3898 SAFE_FREE(h_name_lower
);
3901 SAFE_FREE(h_name_lower
);
3903 /* Always cleanup vector and results */
3904 if (!nwrap_vector_is_initialized(addr_list
)) {
3905 if (!nwrap_vector_init(addr_list
)) {
3906 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3907 "Unable to initialize memory for addr_list vector");
3911 /* When vector is initialized data are valid no more.
3912 * Quick way how to free vector is: */
3913 addr_list
->count
= 0;
3916 /* Iterate through results */
3917 for (el
= (struct nwrap_entlist
*)e_p
->data
; el
!= NULL
; el
= el
->next
)
3921 /* Filter by address familiy if provided */
3922 if (af
!= AF_UNSPEC
&& he
->h_addrtype
!= af
) {
3928 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
3930 if (af
== AF_UNSPEC
&& he
->h_addrtype
!= AF_INET
) {
3935 memcpy(result
, he
, sizeof(struct hostent
));
3936 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3937 "Name found. Returning record for %s",
3941 nwrap_vector_merge(addr_list
, &el
->ed
->nwrap_addrdata
);
3942 result
->h_addr_list
= nwrap_vector_head(addr_list
);
3948 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3949 "Name found in database. No records matches type.");
3956 static int nwrap_files_gethostbyname2_r(struct nwrap_backend
*b
,
3957 const char *name
, int af
,
3958 struct hostent
*hedst
,
3959 char *buf
, size_t buflen
,
3960 struct hostent
**hedstp
)
3962 struct nwrap_vector
*addr_list
= NULL
;
3969 (void) b
; /* unused */
3970 (void) af
; /* unused */
3972 if (name
== NULL
|| hedst
== NULL
|| buf
== NULL
|| buflen
== 0) {
3979 addr_list
= calloc(1, sizeof(struct nwrap_vector
));
3980 if (addr_list
== NULL
) {
3981 NWRAP_LOG(NWRAP_LOG_ERROR
,
3982 "Unable to allocate memory for address list");
3987 rc
= nwrap_files_internal_gethostbyname(name
, af
, hedst
,
3990 SAFE_FREE(addr_list
->items
);
3991 SAFE_FREE(addr_list
);
3996 /* +1 i for ending NULL pointer */
3997 if (buflen
< ((addr_list
->count
+ 1) * sizeof(void *))) {
3998 SAFE_FREE(addr_list
->items
);
3999 SAFE_FREE(addr_list
);
4003 /* Copy all to user provided buffer and change
4004 * pointers in returned structure.
4005 * +1 is for ending NULL pointer. */
4006 memcpy(buf
, addr_list
->items
, (addr_list
->count
+ 1) * sizeof(void *));
4008 SAFE_FREE(addr_list
->items
);
4009 SAFE_FREE(addr_list
);
4012 hedst
->h_addr_list
= g
.list
;
4017 #ifdef HAVE_GETHOSTBYNAME_R
4018 static int nwrap_gethostbyname_r(const char *name
,
4019 struct hostent
*ret
,
4020 char *buf
, size_t buflen
,
4021 struct hostent
**result
, int *h_errnop
)
4026 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4027 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4028 rc
= b
->ops
->nw_gethostbyname2_r(b
, name
, AF_UNSPEC
, ret
,
4029 buf
, buflen
, result
);
4032 } else if (rc
== ERANGE
) {
4036 *h_errnop
= h_errno
;
4040 int gethostbyname_r(const char *name
,
4041 struct hostent
*ret
,
4042 char *buf
, size_t buflen
,
4043 struct hostent
**result
, int *h_errnop
)
4045 if (!nss_wrapper_hosts_enabled()) {
4046 return libc_gethostbyname_r(name
,
4054 return nwrap_gethostbyname_r(name
, ret
, buf
, buflen
, result
, h_errnop
);
4058 #ifdef HAVE_GETHOSTBYNAME2_R
4059 static int nwrap_gethostbyname2_r(const char *name
, int af
,
4060 struct hostent
*ret
,
4061 char *buf
, size_t buflen
,
4062 struct hostent
**result
, int *h_errnop
)
4067 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4068 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4069 rc
= b
->ops
->nw_gethostbyname2_r(b
, name
, af
, ret
,
4070 buf
, buflen
, result
);
4073 } else if (rc
== ERANGE
) {
4077 *h_errnop
= h_errno
;
4081 int gethostbyname2_r(const char *name
, int af
,
4082 struct hostent
*ret
,
4083 char *buf
, size_t buflen
,
4084 struct hostent
**result
, int *h_errnop
)
4086 if (!nss_wrapper_hosts_enabled()) {
4087 return libc_gethostbyname2_r(name
, af
, ret
, buf
, buflen
,
4091 return nwrap_gethostbyname2_r(name
, af
, ret
, buf
, buflen
, result
,
4096 static int nwrap_files_getaddrinfo(const char *name
,
4097 unsigned short port
,
4098 const struct addrinfo
*hints
,
4099 struct addrinfo
**ai
)
4101 struct nwrap_entlist
*el
;
4103 struct addrinfo
*ai_head
= NULL
;
4104 struct addrinfo
*ai_cur
= NULL
;
4107 char canon_name
[DNS_NAME_MAX
] = { 0 };
4108 bool skip_canonname
= false;
4116 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
4118 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
4122 name_len
= strlen(name
);
4123 if (name_len
== 0) {
4127 if (name_len
< sizeof(canon_name
) && name
[name_len
- 1] == '.') {
4128 memcpy(canon_name
, name
, name_len
- 1);
4129 canon_name
[name_len
] = '\0';
4133 if (!str_tolower_copy(&h_name_lower
, name
)) {
4134 NWRAP_LOG(NWRAP_LOG_DEBUG
,
4135 "Out of memory while converting to lower case");
4139 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching for name: %s", h_name_lower
);
4140 e
.key
= h_name_lower
;
4142 e_p
= hsearch(e
, FIND
);
4144 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found.", h_name_lower
);
4145 SAFE_FREE(h_name_lower
);
4149 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name: %s found.", h_name_lower
);
4150 SAFE_FREE(h_name_lower
);
4153 for (el
= (struct nwrap_entlist
*)e_p
->data
; el
!= NULL
; el
= el
->next
)
4156 struct addrinfo
*ai_new
= NULL
;
4160 if (hints
->ai_family
!= AF_UNSPEC
&&
4161 he
->h_addrtype
!= hints
->ai_family
)
4163 NWRAP_LOG(NWRAP_LOG_DEBUG
,
4164 "Entry found but with wrong AF - "
4165 "remembering EAI_ADDRINFO.");
4166 rc
= EAI_ADDRFAMILY
;
4170 /* Function allocates memory and returns it in ai. */
4171 rc2
= nwrap_convert_he_ai(he
,
4177 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error converting he to ai");
4178 if (ai_head
!= NULL
) {
4179 freeaddrinfo(ai_head
);
4183 skip_canonname
= true;
4185 if (ai_head
== NULL
) {
4188 if (ai_cur
!= NULL
) {
4189 ai_cur
->ai_next
= ai_new
;
4194 if (ai_head
!= NULL
) {
4203 static struct hostent
*nwrap_files_gethostbyaddr(struct nwrap_backend
*b
,
4205 socklen_t len
, int type
)
4208 char ip
[NWRAP_INET_ADDRSTRLEN
] = {0};
4209 struct nwrap_entdata
*ed
;
4214 (void) b
; /* unused */
4215 (void) len
; /* unused */
4217 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
4219 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
4223 a
= inet_ntop(type
, addr
, ip
, sizeof(ip
));
4229 nwrap_vector_foreach(ed
, nwrap_he_global
.entries
, i
)
4232 if (he
->h_addrtype
!= type
) {
4236 if (memcmp(addr
, he
->h_addr_list
[0], he
->h_length
) == 0) {
4245 #ifdef HAVE_GETHOSTBYADDR_R
4246 static int nwrap_gethostbyaddr_r(const void *addr
, socklen_t len
, int type
,
4247 struct hostent
*ret
,
4248 char *buf
, size_t buflen
,
4249 struct hostent
**result
, int *h_errnop
)
4252 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4253 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4254 *result
= b
->ops
->nw_gethostbyaddr(b
, addr
, len
, type
);
4255 if (*result
!= NULL
) {
4260 if (*result
!= NULL
) {
4261 memset(buf
, '\0', buflen
);
4266 *h_errnop
= h_errno
;
4270 int gethostbyaddr_r(const void *addr
, socklen_t len
, int type
,
4271 struct hostent
*ret
,
4272 char *buf
, size_t buflen
,
4273 struct hostent
**result
, int *h_errnop
)
4275 if (!nss_wrapper_hosts_enabled()) {
4276 return libc_gethostbyaddr_r(addr
,
4286 return nwrap_gethostbyaddr_r(addr
, len
, type
, ret
, buf
, buflen
, result
, h_errnop
);
4290 /* hosts enum functions */
4291 static void nwrap_files_sethostent(void)
4293 nwrap_he_global
.idx
= 0;
4296 static struct hostent
*nwrap_files_gethostent(void)
4300 if (nwrap_he_global
.idx
== 0) {
4303 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
4305 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading hosts file");
4310 if (nwrap_he_global
.idx
>= nwrap_he_global
.num
) {
4315 he
= &((struct nwrap_entdata
*)nwrap_he_global
.entries
.items
[nwrap_he_global
.idx
++])->ht
;
4317 NWRAP_LOG(NWRAP_LOG_DEBUG
, "return hosts[%s]", he
->h_name
);
4322 static void nwrap_files_endhostent(void)
4324 nwrap_he_global
.idx
= 0;
4332 static struct passwd
*nwrap_module_getpwnam(struct nwrap_backend
*b
,
4335 static struct passwd pwd
;
4336 static char buf
[1000];
4339 if (b
->symbols
->_nss_getpwnam_r
.f
== NULL
) {
4343 status
= b
->symbols
->_nss_getpwnam_r
.f(name
,
4348 if (status
== NSS_STATUS_NOTFOUND
) {
4351 if (status
!= NSS_STATUS_SUCCESS
) {
4358 static int nwrap_module_getpwnam_r(struct nwrap_backend
*b
,
4359 const char *name
, struct passwd
*pwdst
,
4360 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4366 if (b
->symbols
->_nss_getpwnam_r
.f
== NULL
) {
4367 return NSS_STATUS_NOTFOUND
;
4370 ret
= b
->symbols
->_nss_getpwnam_r
.f(name
, pwdst
, buf
, buflen
, &errno
);
4372 case NSS_STATUS_SUCCESS
:
4375 case NSS_STATUS_NOTFOUND
:
4380 case NSS_STATUS_TRYAGAIN
:
4393 static struct passwd
*nwrap_module_getpwuid(struct nwrap_backend
*b
,
4396 static struct passwd pwd
;
4397 static char buf
[1000];
4400 if (b
->symbols
->_nss_getpwuid_r
.f
== NULL
) {
4404 status
= b
->symbols
->_nss_getpwuid_r
.f(uid
,
4409 if (status
== NSS_STATUS_NOTFOUND
) {
4412 if (status
!= NSS_STATUS_SUCCESS
) {
4418 static int nwrap_module_getpwuid_r(struct nwrap_backend
*b
,
4419 uid_t uid
, struct passwd
*pwdst
,
4420 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4426 if (b
->symbols
->_nss_getpwuid_r
.f
== NULL
) {
4430 ret
= b
->symbols
->_nss_getpwuid_r
.f(uid
, pwdst
, buf
, buflen
, &errno
);
4432 case NSS_STATUS_SUCCESS
:
4435 case NSS_STATUS_NOTFOUND
:
4440 case NSS_STATUS_TRYAGAIN
:
4453 static void nwrap_module_setpwent(struct nwrap_backend
*b
)
4455 if (b
->symbols
->_nss_setpwent
.f
== NULL
) {
4459 b
->symbols
->_nss_setpwent
.f();
4462 static struct passwd
*nwrap_module_getpwent(struct nwrap_backend
*b
)
4464 static struct passwd pwd
;
4465 static char buf
[1000];
4468 if (b
->symbols
->_nss_getpwent_r
.f
== NULL
) {
4472 status
= b
->symbols
->_nss_getpwent_r
.f(&pwd
, buf
, sizeof(buf
), &errno
);
4473 if (status
== NSS_STATUS_NOTFOUND
) {
4476 if (status
!= NSS_STATUS_SUCCESS
) {
4482 static int nwrap_module_getpwent_r(struct nwrap_backend
*b
,
4483 struct passwd
*pwdst
, char *buf
,
4484 size_t buflen
, struct passwd
**pwdstp
)
4490 if (b
->symbols
->_nss_getpwent_r
.f
== NULL
) {
4494 ret
= b
->symbols
->_nss_getpwent_r
.f(pwdst
, buf
, buflen
, &errno
);
4496 case NSS_STATUS_SUCCESS
:
4499 case NSS_STATUS_NOTFOUND
:
4504 case NSS_STATUS_TRYAGAIN
:
4517 static void nwrap_module_endpwent(struct nwrap_backend
*b
)
4519 if (b
->symbols
->_nss_endpwent
.f
== NULL
) {
4523 b
->symbols
->_nss_endpwent
.f();
4526 static int nwrap_module_initgroups_dyn(struct nwrap_backend
*b
,
4535 if (b
->symbols
->_nss_initgroups_dyn
.f
== NULL
) {
4536 return NSS_STATUS_UNAVAIL
;
4539 return b
->symbols
->_nss_initgroups_dyn
.f(user
,
4548 static struct group
*nwrap_module_getgrnam(struct nwrap_backend
*b
,
4551 static struct group grp
;
4553 static int buflen
= 1000;
4556 if (b
->symbols
->_nss_getgrnam_r
.f
== NULL
) {
4561 buf
= (char *)malloc(buflen
);
4564 status
= b
->symbols
->_nss_getgrnam_r
.f(name
, &grp
, buf
, buflen
, &errno
);
4565 if (status
== NSS_STATUS_TRYAGAIN
) {
4567 buf
= (char *)realloc(buf
, buflen
);
4573 if (status
== NSS_STATUS_NOTFOUND
) {
4577 if (status
!= NSS_STATUS_SUCCESS
) {
4584 static int nwrap_module_getgrnam_r(struct nwrap_backend
*b
,
4585 const char *name
, struct group
*grdst
,
4586 char *buf
, size_t buflen
, struct group
**grdstp
)
4592 if (b
->symbols
->_nss_getgrnam_r
.f
== NULL
) {
4596 ret
= b
->symbols
->_nss_getgrnam_r
.f(name
, grdst
, buf
, buflen
, &errno
);
4598 case NSS_STATUS_SUCCESS
:
4601 case NSS_STATUS_NOTFOUND
:
4606 case NSS_STATUS_TRYAGAIN
:
4619 static struct group
*nwrap_module_getgrgid(struct nwrap_backend
*b
,
4622 static struct group grp
;
4624 static int buflen
= 1000;
4627 if (b
->symbols
->_nss_getgrgid_r
.f
== NULL
) {
4632 buf
= (char *)malloc(buflen
);
4636 status
= b
->symbols
->_nss_getgrgid_r
.f(gid
, &grp
, buf
, buflen
, &errno
);
4637 if (status
== NSS_STATUS_TRYAGAIN
) {
4639 buf
= (char *)realloc(buf
, buflen
);
4645 if (status
== NSS_STATUS_NOTFOUND
) {
4649 if (status
!= NSS_STATUS_SUCCESS
) {
4656 static int nwrap_module_getgrgid_r(struct nwrap_backend
*b
,
4657 gid_t gid
, struct group
*grdst
,
4658 char *buf
, size_t buflen
, struct group
**grdstp
)
4664 if (b
->symbols
->_nss_getgrgid_r
.f
== NULL
) {
4668 ret
= b
->symbols
->_nss_getgrgid_r
.f(gid
, grdst
, buf
, buflen
, &errno
);
4670 case NSS_STATUS_SUCCESS
:
4673 case NSS_STATUS_NOTFOUND
:
4678 case NSS_STATUS_TRYAGAIN
:
4691 static void nwrap_module_setgrent(struct nwrap_backend
*b
)
4693 if (b
->symbols
->_nss_setgrent
.f
== NULL
) {
4697 b
->symbols
->_nss_setgrent
.f();
4700 static struct group
*nwrap_module_getgrent(struct nwrap_backend
*b
)
4702 static struct group grp
;
4704 static int buflen
= 1024;
4707 if (b
->symbols
->_nss_getgrent_r
.f
== NULL
) {
4712 buf
= (char *)malloc(buflen
);
4716 status
= b
->symbols
->_nss_getgrent_r
.f(&grp
, buf
, buflen
, &errno
);
4717 if (status
== NSS_STATUS_TRYAGAIN
) {
4719 buf
= (char *)realloc(buf
, buflen
);
4725 if (status
== NSS_STATUS_NOTFOUND
) {
4729 if (status
!= NSS_STATUS_SUCCESS
) {
4736 static int nwrap_module_getgrent_r(struct nwrap_backend
*b
,
4737 struct group
*grdst
, char *buf
,
4738 size_t buflen
, struct group
**grdstp
)
4744 if (b
->symbols
->_nss_getgrent_r
.f
== NULL
) {
4748 ret
= b
->symbols
->_nss_getgrent_r
.f(grdst
, buf
, buflen
, &errno
);
4750 case NSS_STATUS_SUCCESS
:
4753 case NSS_STATUS_NOTFOUND
:
4758 case NSS_STATUS_TRYAGAIN
:
4771 static void nwrap_module_endgrent(struct nwrap_backend
*b
)
4773 if (b
->symbols
->_nss_endgrent
.f
== NULL
) {
4777 b
->symbols
->_nss_endgrent
.f();
4780 static struct hostent
*nwrap_module_gethostbyaddr(struct nwrap_backend
*b
,
4782 socklen_t len
, int type
)
4784 static struct hostent he
;
4785 static char *buf
= NULL
;
4786 static size_t buflen
= 1000;
4789 if (b
->symbols
->_nss_gethostbyaddr_r
.f
== NULL
) {
4794 buf
= (char *)malloc(buflen
);
4800 status
= b
->symbols
->_nss_gethostbyaddr_r
.f(addr
,
4808 if (status
== NSS_STATUS_TRYAGAIN
) {
4812 p
= (char *)realloc(buf
, buflen
);
4820 if (status
== NSS_STATUS_NOTFOUND
) {
4824 if (status
!= NSS_STATUS_SUCCESS
) {
4832 static int nwrap_module_gethostbyname2_r(struct nwrap_backend
*b
,
4833 const char *name
, int af
,
4834 struct hostent
*hedst
,
4835 char *buf
, size_t buflen
,
4836 struct hostent
**hedstp
)
4842 if (b
->symbols
->_nss_gethostbyname2_r
.f
== NULL
) {
4846 status
= b
->symbols
->_nss_gethostbyname2_r
.f(name
,
4854 case NSS_STATUS_SUCCESS
:
4857 case NSS_STATUS_NOTFOUND
:
4862 case NSS_STATUS_TRYAGAIN
:
4875 static struct hostent
*nwrap_module_gethostbyname(struct nwrap_backend
*b
,
4878 static struct hostent he
;
4879 static char *buf
= NULL
;
4880 static size_t buflen
= 1000;
4883 if (b
->symbols
->_nss_gethostbyname2_r
.f
== NULL
) {
4888 buf
= (char *)malloc(buflen
);
4895 status
= b
->symbols
->_nss_gethostbyname2_r
.f(name
,
4902 if (status
== NSS_STATUS_TRYAGAIN
) {
4906 p
= (char *)realloc(buf
, buflen
);
4914 if (status
== NSS_STATUS_NOTFOUND
) {
4918 if (status
!= NSS_STATUS_SUCCESS
) {
4926 static struct hostent
*nwrap_module_gethostbyname2(struct nwrap_backend
*b
,
4927 const char *name
, int af
)
4929 static struct hostent he
;
4930 static char *buf
= NULL
;
4931 static size_t buflen
= 1000;
4934 if (b
->symbols
->_nss_gethostbyname2_r
.f
== NULL
) {
4939 buf
= (char *)malloc(buflen
);
4946 status
= b
->symbols
->_nss_gethostbyname2_r
.f(name
,
4953 if (status
== NSS_STATUS_TRYAGAIN
) {
4957 p
= (char *)realloc(buf
, buflen
);
4965 if (status
== NSS_STATUS_NOTFOUND
) {
4969 if (status
!= NSS_STATUS_SUCCESS
) {
4977 /****************************************************************************
4979 ***************************************************************************/
4981 static struct passwd
*nwrap_getpwnam(const char *name
)
4986 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4987 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4988 pwd
= b
->ops
->nw_getpwnam(b
, name
);
4997 struct passwd
*getpwnam(const char *name
)
4999 if (!nss_wrapper_enabled()) {
5000 return libc_getpwnam(name
);
5003 return nwrap_getpwnam(name
);
5006 /****************************************************************************
5008 ***************************************************************************/
5010 static int nwrap_getpwnam_r(const char *name
, struct passwd
*pwdst
,
5011 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
5016 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5017 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5018 ret
= b
->ops
->nw_getpwnam_r(b
, name
, pwdst
, buf
, buflen
, pwdstp
);
5019 if (ret
== ENOENT
) {
5028 #ifdef HAVE_GETPWNAM_R
5029 # ifdef HAVE_SOLARIS_GETPWNAM_R
5030 int getpwnam_r(const char *name
, struct passwd
*pwdst
,
5031 char *buf
, int buflen
, struct passwd
**pwdstp
)
5032 # else /* HAVE_SOLARIS_GETPWNAM_R */
5033 int getpwnam_r(const char *name
, struct passwd
*pwdst
,
5034 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
5035 # endif /* HAVE_SOLARIS_GETPWNAM_R */
5037 if (!nss_wrapper_enabled()) {
5038 return libc_getpwnam_r(name
, pwdst
, buf
, buflen
, pwdstp
);
5041 return nwrap_getpwnam_r(name
, pwdst
, buf
, buflen
, pwdstp
);
5045 /****************************************************************************
5047 ***************************************************************************/
5049 static struct passwd
*nwrap_getpwuid(uid_t uid
)
5054 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5055 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5056 pwd
= b
->ops
->nw_getpwuid(b
, uid
);
5065 struct passwd
*getpwuid(uid_t uid
)
5067 if (!nss_wrapper_enabled()) {
5068 return libc_getpwuid(uid
);
5071 return nwrap_getpwuid(uid
);
5074 /****************************************************************************
5076 ***************************************************************************/
5078 static int nwrap_getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
5079 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
5084 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5085 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5086 ret
= b
->ops
->nw_getpwuid_r(b
, uid
, pwdst
, buf
, buflen
, pwdstp
);
5087 if (ret
== ENOENT
) {
5096 #ifdef HAVE_SOLARIS_GETPWUID_R
5097 int getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
5098 char *buf
, int buflen
, struct passwd
**pwdstp
)
5100 int getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
5101 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
5104 if (!nss_wrapper_enabled()) {
5105 return libc_getpwuid_r(uid
, pwdst
, buf
, buflen
, pwdstp
);
5108 return nwrap_getpwuid_r(uid
, pwdst
, buf
, buflen
, pwdstp
);
5111 /****************************************************************************
5113 ***************************************************************************/
5115 static void nwrap_setpwent(void)
5119 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5120 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5121 b
->ops
->nw_setpwent(b
);
5127 if (!nss_wrapper_enabled()) {
5135 /****************************************************************************
5137 ***************************************************************************/
5139 static struct passwd
*nwrap_getpwent(void)
5144 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5145 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5146 pwd
= b
->ops
->nw_getpwent(b
);
5155 struct passwd
*getpwent(void)
5157 if (!nss_wrapper_enabled()) {
5158 return libc_getpwent();
5161 return nwrap_getpwent();
5164 /****************************************************************************
5166 ***************************************************************************/
5168 #ifdef HAVE_GETPWENT_R
5169 static int nwrap_getpwent_r(struct passwd
*pwdst
, char *buf
,
5170 size_t buflen
, struct passwd
**pwdstp
)
5175 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5176 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5177 ret
= b
->ops
->nw_getpwent_r(b
, pwdst
, buf
, buflen
, pwdstp
);
5178 if (ret
== ENOENT
) {
5187 # ifdef HAVE_SOLARIS_GETPWENT_R
5188 struct passwd
*getpwent_r(struct passwd
*pwdst
, char *buf
, int buflen
)
5190 struct passwd
*pwdstp
= NULL
;
5193 if (!nss_wrapper_enabled()) {
5194 return libc_getpwent_r(pwdst
, buf
, buflen
);
5196 rc
= nwrap_getpwent_r(pwdst
, buf
, buflen
, &pwdstp
);
5203 # else /* HAVE_SOLARIS_GETPWENT_R */
5204 int getpwent_r(struct passwd
*pwdst
, char *buf
,
5205 size_t buflen
, struct passwd
**pwdstp
)
5207 if (!nss_wrapper_enabled()) {
5208 return libc_getpwent_r(pwdst
, buf
, buflen
, pwdstp
);
5211 return nwrap_getpwent_r(pwdst
, buf
, buflen
, pwdstp
);
5213 # endif /* HAVE_SOLARIS_GETPWENT_R */
5214 #endif /* HAVE_GETPWENT_R */
5216 /****************************************************************************
5218 ***************************************************************************/
5220 static void nwrap_endpwent(void)
5224 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5225 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5226 b
->ops
->nw_endpwent(b
);
5232 if (!nss_wrapper_enabled()) {
5240 /****************************************************************************
5242 ***************************************************************************/
5244 static int nwrap_initgroups(const char *user
, gid_t group
)
5246 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0
5247 /* No extra groups allowed. */
5249 #elif !defined(HAVE_GETGROUPLIST)
5257 const char *env
= getenv("UID_WRAPPER");
5259 if (env
== NULL
|| env
[0] != '1') {
5260 NWRAP_LOG(NWRAP_LOG_WARN
,
5261 "initgroups() requires uid_wrapper to work!");
5265 limit
= sysconf(_SC_NGROUPS_MAX
);
5267 size
= MIN(limit
, 64);
5272 groups
= (gid_t
*)malloc(size
* sizeof(gid_t
));
5273 if (groups
== NULL
) {
5274 /* No more memory. */
5278 ngroups
= nwrap_getgrouplist(user
, group
, &size
, &groups
, limit
);
5280 /* Try to set the maximum number of groups the kernel can handle. */
5282 result
= setgroups(ngroups
, groups
);
5283 } while (result
== -1 && errno
== EINVAL
&& --ngroups
> 0);
5291 int initgroups(const char *user
, gid_t group
)
5293 if (!nss_wrapper_enabled()) {
5294 return libc_initgroups(user
, group
);
5297 return nwrap_initgroups(user
, group
);
5300 /****************************************************************************
5302 ***************************************************************************/
5304 static struct group
*nwrap_getgrnam(const char *name
)
5309 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5310 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5311 grp
= b
->ops
->nw_getgrnam(b
, name
);
5320 struct group
*getgrnam(const char *name
)
5322 if (!nss_wrapper_enabled()) {
5323 return libc_getgrnam(name
);
5326 return nwrap_getgrnam(name
);
5329 /****************************************************************************
5331 ***************************************************************************/
5333 static int nwrap_getgrnam_r(const char *name
, struct group
*grdst
,
5334 char *buf
, size_t buflen
, struct group
**grdstp
)
5339 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5340 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5341 ret
= b
->ops
->nw_getgrnam_r(b
, name
, grdst
, buf
, buflen
, grdstp
);
5342 if (ret
== ENOENT
) {
5351 #ifdef HAVE_GETGRNAM_R
5352 # ifdef HAVE_SOLARIS_GETGRNAM_R
5353 int getgrnam_r(const char *name
, struct group
*grp
,
5354 char *buf
, int buflen
, struct group
**pgrp
)
5355 # else /* HAVE_SOLARIS_GETGRNAM_R */
5356 int getgrnam_r(const char *name
, struct group
*grp
,
5357 char *buf
, size_t buflen
, struct group
**pgrp
)
5358 # endif /* HAVE_SOLARIS_GETGRNAM_R */
5360 if (!nss_wrapper_enabled()) {
5361 return libc_getgrnam_r(name
,
5368 return nwrap_getgrnam_r(name
, grp
, buf
, buflen
, pgrp
);
5370 #endif /* HAVE_GETGRNAM_R */
5372 /****************************************************************************
5374 ***************************************************************************/
5376 static struct group
*nwrap_getgrgid(gid_t gid
)
5381 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5382 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5383 grp
= b
->ops
->nw_getgrgid(b
, gid
);
5392 struct group
*getgrgid(gid_t gid
)
5394 if (!nss_wrapper_enabled()) {
5395 return libc_getgrgid(gid
);
5398 return nwrap_getgrgid(gid
);
5401 /****************************************************************************
5403 ***************************************************************************/
5405 static int nwrap_getgrgid_r(gid_t gid
, struct group
*grdst
,
5406 char *buf
, size_t buflen
, struct group
**grdstp
)
5411 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5412 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5413 ret
= b
->ops
->nw_getgrgid_r(b
, gid
, grdst
, buf
, buflen
, grdstp
);
5414 if (ret
== ENOENT
) {
5423 #ifdef HAVE_GETGRGID_R
5424 # ifdef HAVE_SOLARIS_GETGRGID_R
5425 int getgrgid_r(gid_t gid
, struct group
*grdst
,
5426 char *buf
, int buflen
, struct group
**grdstp
)
5427 # else /* HAVE_SOLARIS_GETGRGID_R */
5428 int getgrgid_r(gid_t gid
, struct group
*grdst
,
5429 char *buf
, size_t buflen
, struct group
**grdstp
)
5430 # endif /* HAVE_SOLARIS_GETGRGID_R */
5432 if (!nss_wrapper_enabled()) {
5433 return libc_getgrgid_r(gid
, grdst
, buf
, buflen
, grdstp
);
5436 return nwrap_getgrgid_r(gid
, grdst
, buf
, buflen
, grdstp
);
5440 /****************************************************************************
5442 ***************************************************************************/
5444 static void nwrap_setgrent(void)
5448 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5449 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5450 b
->ops
->nw_setgrent(b
);
5454 #ifdef HAVE_BSD_SETGRENT
5460 if (!nss_wrapper_enabled()) {
5468 #ifdef HAVE_BSD_SETGRENT
5475 /****************************************************************************
5477 ***************************************************************************/
5479 static struct group
*nwrap_getgrent(void)
5484 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5485 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5486 grp
= b
->ops
->nw_getgrent(b
);
5495 struct group
*getgrent(void)
5497 if (!nss_wrapper_enabled()) {
5498 return libc_getgrent();
5501 return nwrap_getgrent();
5504 /****************************************************************************
5506 ***************************************************************************/
5508 #ifdef HAVE_GETGRENT_R
5509 static int nwrap_getgrent_r(struct group
*grdst
, char *buf
,
5510 size_t buflen
, struct group
**grdstp
)
5515 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5516 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5517 ret
= b
->ops
->nw_getgrent_r(b
, grdst
, buf
, buflen
, grdstp
);
5518 if (ret
== ENOENT
) {
5527 # ifdef HAVE_SOLARIS_GETGRENT_R
5528 struct group
*getgrent_r(struct group
*src
, char *buf
, int buflen
)
5530 struct group
*grdstp
= NULL
;
5533 if (!nss_wrapper_enabled()) {
5534 return libc_getgrent_r(src
, buf
, buflen
);
5537 rc
= nwrap_getgrent_r(src
, buf
, buflen
, &grdstp
);
5544 # else /* HAVE_SOLARIS_GETGRENT_R */
5545 int getgrent_r(struct group
*src
, char *buf
,
5546 size_t buflen
, struct group
**grdstp
)
5548 if (!nss_wrapper_enabled()) {
5549 return libc_getgrent_r(src
, buf
, buflen
, grdstp
);
5552 return nwrap_getgrent_r(src
, buf
, buflen
, grdstp
);
5554 # endif /* HAVE_SOLARIS_GETGRENT_R */
5555 #endif /* HAVE_GETGRENT_R */
5557 /****************************************************************************
5559 ***************************************************************************/
5561 static void nwrap_endgrent(void)
5565 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5566 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5567 b
->ops
->nw_endgrent(b
);
5573 if (!nss_wrapper_enabled()) {
5581 /****************************************************************************
5583 ***************************************************************************/
5585 #ifdef HAVE_GETGROUPLIST
5586 static int nwrap_getgrouplist(const char *user
,
5592 enum nss_status status
= NSS_STATUS_UNAVAIL
;
5593 /* Start is one, because we have the first group as parameter. */
5597 /* Never store more than the starting *SIZE number of elements. */
5599 (*groupsp
)[0] = group
;
5601 for (i
= 0; i
< nwrap_main_global
->num_backends
; i
++) {
5602 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5603 long int prev_start
= start
;
5604 long int cnt
= prev_start
;
5606 status
= b
->ops
->nw_initgroups_dyn(b
,
5615 /* Remove duplicates. */
5616 while (cnt
< start
) {
5618 for (inner
= 0; inner
< prev_start
; ++inner
)
5619 if ((*groupsp
)[inner
] == (*groupsp
)[cnt
])
5622 if (inner
< prev_start
)
5623 (*groupsp
)[cnt
] = (*groupsp
)[--start
];
5627 NWRAP_LOG(NWRAP_LOG_DEBUG
,
5628 "Resource '%s' returned status=%d and increased "
5629 "count of groups to %ld",
5637 int getgrouplist(const char *user
, gid_t group
, gid_t
*groups
, int *ngroups
)
5643 if (!nss_wrapper_enabled()) {
5644 return libc_getgrouplist(user
, group
, groups
, ngroups
);
5647 size
= MAX(1, *ngroups
);
5648 newgroups
= (gid_t
*)malloc(size
* sizeof(gid_t
));
5649 if (newgroups
== NULL
) {
5653 total
= nwrap_getgrouplist(user
, group
, &size
, &newgroups
, -1);
5655 if (groups
!= NULL
) {
5656 memcpy(groups
, newgroups
, MIN(*ngroups
, total
) * sizeof(gid_t
));
5661 retval
= total
> *ngroups
? -1 : total
;
5668 /**********************************************************
5670 **********************************************************/
5672 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
5674 #ifdef HAVE_SETSPENT
5675 static void nwrap_setspent(void)
5677 nwrap_files_setspent();
5682 if (!nss_wrapper_shadow_enabled()) {
5689 static struct spwd
*nwrap_getspent(void)
5691 return nwrap_files_getspent();
5694 struct spwd
*getspent(void)
5696 if (!nss_wrapper_shadow_enabled()) {
5700 return nwrap_getspent();
5703 static void nwrap_endspent(void)
5705 nwrap_files_endspent();
5710 if (!nss_wrapper_shadow_enabled()) {
5716 #endif /* HAVE_SETSPENT */
5718 static struct spwd
*nwrap_getspnam(const char *name
)
5720 return nwrap_files_getspnam(name
);
5723 struct spwd
*getspnam(const char *name
)
5725 if (!nss_wrapper_shadow_enabled()) {
5729 return nwrap_getspnam(name
);
5732 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
5734 /**********************************************************
5736 **********************************************************/
5738 static void nwrap_sethostent(int stayopen
) {
5739 (void) stayopen
; /* ignored */
5741 nwrap_files_sethostent();
5744 #ifdef HAVE_SOLARIS_SETHOSTENT
5745 int sethostent(int stayopen
)
5747 if (!nss_wrapper_hosts_enabled()) {
5748 libc_sethostent(stayopen
);
5752 nwrap_sethostent(stayopen
);
5756 #else /* HAVE_SOLARIS_SETHOSTENT */
5757 void sethostent(int stayopen
)
5759 if (!nss_wrapper_hosts_enabled()) {
5760 libc_sethostent(stayopen
);
5764 nwrap_sethostent(stayopen
);
5766 #endif /* HAVE_SOLARIS_SETHOSTENT */
5768 static struct hostent
*nwrap_gethostent(void)
5770 return nwrap_files_gethostent();
5773 struct hostent
*gethostent(void) {
5774 if (!nss_wrapper_hosts_enabled()) {
5775 return libc_gethostent();
5778 return nwrap_gethostent();
5781 static void nwrap_endhostent(void) {
5782 nwrap_files_endhostent();
5785 #ifdef HAVE_SOLARIS_ENDHOSTENT
5786 int endhostent(void)
5788 if (!nss_wrapper_hosts_enabled()) {
5797 #else /* HAVE_SOLARIS_ENDHOSTENT */
5798 void endhostent(void)
5800 if (!nss_wrapper_hosts_enabled()) {
5807 #endif /* HAVE_SOLARIS_ENDHOSTENT */
5811 /* BSD implementation stores data in thread local storage but GLIBC does not */
5812 static __thread
struct hostent user_he
;
5813 static __thread
struct nwrap_vector user_addrlist
;
5815 static struct hostent user_he
;
5816 static struct nwrap_vector user_addrlist
;
5819 static struct hostent
*nwrap_files_gethostbyname(struct nwrap_backend
*b
,
5824 (void) b
; /* unused */
5826 ret
= nwrap_files_internal_gethostbyname(name
, AF_UNSPEC
, &user_he
,
5835 static struct hostent
*nwrap_gethostbyname(const char *name
)
5838 struct hostent
*he
= NULL
;
5840 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5841 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5842 he
= b
->ops
->nw_gethostbyname(b
, name
);
5851 struct hostent
*gethostbyname(const char *name
)
5853 if (!nss_wrapper_hosts_enabled()) {
5854 return libc_gethostbyname(name
);
5857 return nwrap_gethostbyname(name
);
5860 /* This is a GNU extension - Also can be found on BSD systems */
5861 #ifdef HAVE_GETHOSTBYNAME2
5863 /* BSD implementation stores data in thread local storage but GLIBC not */
5864 static __thread
struct hostent user_he2
;
5865 static __thread
struct nwrap_vector user_addrlist2
;
5867 static struct hostent user_he2
;
5868 static struct nwrap_vector user_addrlist2
;
5871 static struct hostent
*nwrap_files_gethostbyname2(struct nwrap_backend
*b
,
5872 const char *name
, int af
)
5876 (void) b
; /* unused */
5878 ret
= nwrap_files_internal_gethostbyname(name
, af
, &user_he2
,
5887 static struct hostent
*nwrap_gethostbyname2(const char *name
, int af
)
5890 struct hostent
*he
= NULL
;
5892 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5893 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5894 he
= b
->ops
->nw_gethostbyname2(b
, name
, af
);
5903 struct hostent
*gethostbyname2(const char *name
, int af
)
5905 if (!nss_wrapper_hosts_enabled()) {
5906 return libc_gethostbyname2(name
, af
);
5909 return nwrap_gethostbyname2(name
, af
);
5913 static struct hostent
*nwrap_gethostbyaddr(const void *addr
,
5914 socklen_t len
, int type
)
5917 struct hostent
*he
= NULL
;
5919 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
5920 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
5921 he
= b
->ops
->nw_gethostbyaddr(b
, addr
, len
, type
);
5930 struct hostent
*gethostbyaddr(const void *addr
,
5931 socklen_t len
, int type
)
5933 if (!nss_wrapper_hosts_enabled()) {
5934 return libc_gethostbyaddr(addr
, len
, type
);
5937 return nwrap_gethostbyaddr(addr
, len
, type
);
5940 static const struct addrinfo default_hints
=
5942 .ai_flags
= AI_ADDRCONFIG
|AI_V4MAPPED
,
5943 .ai_family
= AF_UNSPEC
,
5948 .ai_canonname
= NULL
,
5952 static int nwrap_convert_he_ai(const struct hostent
*he
,
5953 unsigned short port
,
5954 const struct addrinfo
*hints
,
5955 struct addrinfo
**pai
,
5956 bool skip_canonname
)
5958 struct addrinfo
*ai
;
5965 switch (he
->h_addrtype
) {
5967 socklen
= sizeof(struct sockaddr_in
);
5971 socklen
= sizeof(struct sockaddr_in6
);
5978 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
) + socklen
);
5983 ai
->ai_flags
= hints
->ai_flags
;
5984 ai
->ai_family
= he
->h_addrtype
;
5985 ai
->ai_socktype
= hints
->ai_socktype
;
5986 ai
->ai_protocol
= hints
->ai_protocol
;
5987 ai
->ai_canonname
= NULL
;
5989 if (ai
->ai_socktype
== 0) {
5990 ai
->ai_socktype
= SOCK_DGRAM
;
5992 if (ai
->ai_protocol
== 0) {
5993 if (ai
->ai_socktype
== SOCK_DGRAM
) {
5994 ai
->ai_protocol
= IPPROTO_UDP
;
5995 } else if (ai
->ai_socktype
== SOCK_STREAM
) {
5996 ai
->ai_protocol
= IPPROTO_TCP
;
6000 ai
->ai_addrlen
= socklen
;
6001 ai
->ai_addr
= (void *)(ai
+ 1);
6003 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
6004 ai
->ai_addr
->sa_len
= socklen
;
6006 ai
->ai_addr
->sa_family
= he
->h_addrtype
;
6008 switch (he
->h_addrtype
) {
6012 struct sockaddr
*sa
;
6013 struct sockaddr_in
*in
;
6016 addr
.sa
= ai
->ai_addr
;
6018 memset(addr
.in
, 0, sizeof(struct sockaddr_in
));
6020 addr
.in
->sin_port
= htons(port
);
6021 addr
.in
->sin_family
= AF_INET
;
6023 memset(addr
.in
->sin_zero
,
6025 sizeof (addr
.in
->sin_zero
));
6026 memcpy(&(addr
.in
->sin_addr
),
6036 struct sockaddr
*sa
;
6037 struct sockaddr_in6
*in6
;
6040 addr
.sa
= ai
->ai_addr
;
6042 memset(addr
.in6
, 0, sizeof(struct sockaddr_in6
));
6044 addr
.in6
->sin6_port
= htons(port
);
6045 addr
.in6
->sin6_family
= AF_INET6
;
6047 memcpy(&addr
.in6
->sin6_addr
,
6057 if (he
->h_name
&& !skip_canonname
) {
6058 ai
->ai_canonname
= strdup(he
->h_name
);
6059 if (ai
->ai_canonname
== NULL
) {
6069 static int nwrap_getaddrinfo(const char *node
,
6070 const char *service
,
6071 const struct addrinfo
*hints
,
6072 struct addrinfo
**res
)
6074 struct addrinfo
*ai
= NULL
;
6075 unsigned short port
= 0;
6085 .family
= AF_UNSPEC
,
6089 if (node
== NULL
&& service
== NULL
) {
6093 if (hints
== NULL
) {
6094 hints
= &default_hints
;
6098 hints.ai_flags contains invalid flags; or, hints.ai_flags
6099 included AI_CANONNAME and name was NULL.
6101 if ((hints
->ai_flags
& AI_CANONNAME
) && (node
== NULL
)) {
6102 return EAI_BADFLAGS
;
6105 /* If no node has been specified, let glibc deal with it */
6108 struct addrinfo
*p
= NULL
;
6110 ret
= libc_getaddrinfo(node
, service
, hints
, &p
);
6118 if (service
!= NULL
&& service
[0] != '\0') {
6119 const char *proto
= NULL
;
6125 sl
= strtol(service
, &end_ptr
, 10);
6127 if (*end_ptr
== '\0') {
6130 } else if (hints
->ai_flags
& AI_NUMERICSERV
) {
6134 if (hints
->ai_protocol
!= 0) {
6135 struct protoent
*pent
;
6137 pent
= getprotobynumber(hints
->ai_protocol
);
6139 proto
= pent
->p_name
;
6143 s
= getservbyname(service
, proto
);
6147 port
= ntohs(s
->s_port
);
6152 rc
= inet_pton(AF_INET
, node
, &addr
.in
.v4
);
6154 addr
.family
= AF_INET
;
6157 if (addr
.family
== AF_UNSPEC
) {
6158 rc
= inet_pton(AF_INET6
, node
, &addr
.in
.v6
);
6160 addr
.family
= AF_INET6
;
6165 if (addr
.family
== AF_UNSPEC
) {
6166 if (hints
->ai_flags
& AI_NUMERICHOST
) {
6169 } else if ((hints
->ai_family
!= AF_UNSPEC
) &&
6170 (hints
->ai_family
!= addr
.family
))
6172 return EAI_ADDRFAMILY
;
6175 rc
= nwrap_files_getaddrinfo(node
, port
, hints
, &ai
);
6178 struct addrinfo
*p
= NULL
;
6180 ret
= libc_getaddrinfo(node
, service
, hints
, &p
);
6184 * nwrap_files_getaddrinfo failed, but libc was
6185 * successful -- use the result from libc.
6195 * If the socktype was not specified, duplicate
6196 * each ai returned, so that we have variants for
6199 if (hints
->ai_socktype
== 0) {
6200 struct addrinfo
*ai_cur
;
6202 /* freeaddrinfo() frees ai_canonname and ai so allocate them */
6203 for (ai_cur
= ai
; ai_cur
!= NULL
; ai_cur
= ai_cur
->ai_next
) {
6204 struct addrinfo
*ai_new
;
6206 /* duplicate the current entry */
6208 ai_new
= malloc(sizeof(struct addrinfo
));
6209 if (ai_new
== NULL
) {
6214 memcpy(ai_new
, ai_cur
, sizeof(struct addrinfo
));
6215 ai_new
->ai_next
= NULL
;
6217 /* We need a deep copy or freeaddrinfo() will blow up */
6218 if (ai_cur
->ai_canonname
!= NULL
) {
6219 ai_new
->ai_canonname
=
6220 strdup(ai_cur
->ai_canonname
);
6223 if (ai_cur
->ai_socktype
== SOCK_DGRAM
) {
6224 ai_new
->ai_socktype
= SOCK_STREAM
;
6225 } else if (ai_cur
->ai_socktype
== SOCK_STREAM
) {
6226 ai_new
->ai_socktype
= SOCK_DGRAM
;
6228 if (ai_cur
->ai_protocol
== IPPROTO_TCP
) {
6229 ai_new
->ai_protocol
= IPPROTO_UDP
;
6230 } else if (ai_cur
->ai_protocol
== IPPROTO_UDP
) {
6231 ai_new
->ai_protocol
= IPPROTO_TCP
;
6234 /* now insert the new entry */
6236 ai_new
->ai_next
= ai_cur
->ai_next
;
6237 ai_cur
->ai_next
= ai_new
;
6239 /* and move on (don't duplicate the new entry) */
6250 int getaddrinfo(const char *node
, const char *service
,
6251 const struct addrinfo
*hints
,
6252 struct addrinfo
**res
)
6254 if (!nss_wrapper_hosts_enabled()) {
6255 return libc_getaddrinfo(node
, service
, hints
, res
);
6258 return nwrap_getaddrinfo(node
, service
, hints
, res
);
6261 static int nwrap_getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
6262 char *host
, size_t hostlen
,
6263 char *serv
, size_t servlen
,
6267 struct servent
*service
;
6275 if (sa
== NULL
|| salen
< sizeof(sa_family_t
)) {
6279 if ((flags
& NI_NAMEREQD
) && host
== NULL
&& serv
== NULL
) {
6283 type
= sa
->sa_family
;
6287 const struct sockaddr
*sa
;
6288 const struct sockaddr_in
*in
;
6291 if (salen
< sizeof(struct sockaddr_in
)) {
6297 addr
= &(a
.in
->sin_addr
);
6298 addrlen
= sizeof(a
.in
->sin_addr
);
6299 port
= ntohs(a
.in
->sin_port
);
6305 const struct sockaddr
*sa
;
6306 const struct sockaddr_in6
*in6
;
6309 if (salen
< sizeof(struct sockaddr_in6
)) {
6315 addr
= &(a
.in6
->sin6_addr
);
6316 addrlen
= sizeof(a
.in6
->sin6_addr
);
6317 port
= ntohs(a
.in6
->sin6_port
);
6327 if ((flags
& NI_NUMERICHOST
) == 0) {
6328 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
6329 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
6330 he
= b
->ops
->nw_gethostbyaddr(b
, addr
, addrlen
, type
);
6335 if ((flags
& NI_NAMEREQD
) && (he
== NULL
|| he
->h_name
== NULL
))
6338 if (he
!= NULL
&& he
->h_name
!= NULL
) {
6339 if (strlen(he
->h_name
) >= hostlen
)
6340 return EAI_OVERFLOW
;
6341 snprintf(host
, hostlen
, "%s", he
->h_name
);
6342 if (flags
& NI_NOFQDN
)
6343 host
[strcspn(host
, ".")] = '\0';
6345 if (inet_ntop(type
, addr
, host
, hostlen
) == NULL
)
6346 return (errno
== ENOSPC
) ? EAI_OVERFLOW
: EAI_FAIL
;
6352 if ((flags
& NI_NUMERICSERV
) == 0) {
6353 proto
= (flags
& NI_DGRAM
) ? "udp" : "tcp";
6354 service
= getservbyport(htons(port
), proto
);
6356 if (service
!= NULL
) {
6357 if (strlen(service
->s_name
) >= servlen
)
6358 return EAI_OVERFLOW
;
6359 snprintf(serv
, servlen
, "%s", service
->s_name
);
6361 if (snprintf(serv
, servlen
, "%u", port
) >= (int) servlen
)
6362 return EAI_OVERFLOW
;
6369 #ifdef HAVE_LINUX_GETNAMEINFO
6370 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
6371 char *host
, socklen_t hostlen
,
6372 char *serv
, socklen_t servlen
,
6374 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
6375 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
6376 char *host
, socklen_t hostlen
,
6377 char *serv
, socklen_t servlen
,
6380 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
6381 char *host
, size_t hostlen
,
6382 char *serv
, size_t servlen
,
6386 if (!nss_wrapper_hosts_enabled()) {
6387 return libc_getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
6390 return nwrap_getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
6393 static int nwrap_gethostname(char *name
, size_t len
)
6395 const char *hostname
= getenv("NSS_WRAPPER_HOSTNAME");
6397 if (strlen(hostname
) >= len
) {
6398 errno
= ENAMETOOLONG
;
6401 snprintf(name
, len
, "%s", hostname
);
6406 #ifdef HAVE_SOLARIS_GETHOSTNAME
6407 int gethostname(char *name
, int len
)
6408 #else /* HAVE_SOLARIS_GETHOSTNAME */
6409 int gethostname(char *name
, size_t len
)
6410 #endif /* HAVE_SOLARIS_GETHOSTNAME */
6412 if (!nwrap_hostname_enabled()) {
6413 return libc_gethostname(name
, len
);
6416 return nwrap_gethostname(name
, len
);
6419 static void nwrap_thread_prepare(void)
6425 static void nwrap_thread_parent(void)
6430 static void nwrap_thread_child(void)
6435 /****************************
6437 ***************************/
6438 void nwrap_constructor(void)
6443 * If we hold a lock and the application forks, then the child
6444 * is not able to unlock the mutex and we are in a deadlock.
6446 * Setting these handlers should prevent such deadlocks.
6448 pthread_atfork(&nwrap_thread_prepare
,
6449 &nwrap_thread_parent
,
6450 &nwrap_thread_child
);
6452 /* Do not call nwrap_init() here. */
6455 /****************************
6457 ***************************/
6460 * This function is called when the library is unloaded and makes sure that
6461 * sockets get closed and the unix file for the socket are unlinked.
6463 void nwrap_destructor(void)
6468 if (nwrap_main_global
!= NULL
) {
6469 struct nwrap_main
*m
= nwrap_main_global
;
6472 if (m
->libc
!= NULL
) {
6473 if (m
->libc
->handle
!= NULL
6475 && m
->libc
->handle
!= RTLD_NEXT
6478 dlclose(m
->libc
->handle
);
6480 if (m
->libc
->nsl_handle
!= NULL
6482 && m
->libc
->nsl_handle
!= RTLD_NEXT
6485 dlclose(m
->libc
->nsl_handle
);
6487 if (m
->libc
->sock_handle
!= NULL
6489 && m
->libc
->sock_handle
!= RTLD_NEXT
6492 dlclose(m
->libc
->sock_handle
);
6498 if (m
->backends
!= NULL
) {
6499 for (i
= 0; i
< m
->num_backends
; i
++) {
6500 struct nwrap_backend
*b
= &(m
->backends
[i
]);
6502 if (b
->so_handle
!= NULL
) {
6503 dlclose(b
->so_handle
);
6505 SAFE_FREE(b
->symbols
);
6507 SAFE_FREE(m
->backends
);
6511 if (nwrap_pw_global
.cache
!= NULL
) {
6512 struct nwrap_cache
*c
= nwrap_pw_global
.cache
;
6514 nwrap_files_cache_unload(c
);
6520 SAFE_FREE(nwrap_pw_global
.list
);
6521 nwrap_pw_global
.num
= 0;
6524 if (nwrap_gr_global
.cache
!= NULL
) {
6525 struct nwrap_cache
*c
= nwrap_gr_global
.cache
;
6527 nwrap_files_cache_unload(c
);
6533 SAFE_FREE(nwrap_gr_global
.list
);
6534 nwrap_pw_global
.num
= 0;
6537 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
6538 if (nwrap_sp_global
.cache
!= NULL
) {
6539 struct nwrap_cache
*c
= nwrap_sp_global
.cache
;
6541 nwrap_files_cache_unload(c
);
6547 nwrap_sp_global
.num
= 0;
6549 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
6551 if (nwrap_he_global
.cache
!= NULL
) {
6552 struct nwrap_cache
*c
= nwrap_he_global
.cache
;
6554 nwrap_files_cache_unload(c
);
6560 nwrap_he_global
.num
= 0;
6563 free(user_addrlist
.items
);
6564 #ifdef HAVE_GETHOSTBYNAME2
6565 free(user_addrlist2
.items
);