2 * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
3 * Copyright (C) Guenther Deschner 2009 <gd@samba.org>
4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/types.h>
40 #include <sys/socket.h>
54 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
55 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
58 #ifndef _POSIX_PTHREAD_SEMANTICS
59 #define _POSIX_PTHREAD_SEMANTICS
67 #include <arpa/inet.h>
68 #include <netinet/in.h>
72 #if defined(HAVE_NSS_H)
76 typedef enum nss_status NSS_STATUS;
77 #elif defined(HAVE_NSS_COMMON_H)
79 #include <nss_common.h>
80 #include <nss_dbdefs.h>
83 typedef nss_status_t NSS_STATUS;
85 # define NSS_STATUS_SUCCESS NSS_SUCCESS
86 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
87 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
88 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
90 # error "No nsswitch support detected"
94 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
102 #define EAI_NODATA EAI_NONAME
105 #ifndef EAI_ADDRFAMILY
106 #define EAI_ADDRFAMILY EAI_FAMILY
110 #define __STRING(x) #x
113 #ifndef __STRINGSTRING
114 #define __STRINGSTRING(x) __STRING(x)
118 #define __LINESTR__ __STRINGSTRING(__LINE__)
122 #define __location__ __FILE__ ":" __LINESTR__
126 #define DNS_NAME_MAX 255
129 /* GCC have printf type attribute check. */
130 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
131 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
133 #define PRINTF_ATTRIBUTE(a,b)
134 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
136 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
137 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
139 #define DESTRUCTOR_ATTRIBUTE
140 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
142 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
145 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
149 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
151 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
154 enum nwrap_dbglvl_e {
162 # define NWRAP_LOG(...)
165 static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
166 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
168 static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
170 const char *format, ...)
175 unsigned int lvl = 0;
178 d = getenv("NSS_WRAPPER_DEBUGLEVEL");
183 va_start(va, format);
184 vsnprintf(buffer, sizeof(buffer), format, va);
189 case NWRAP_LOG_ERROR:
191 "NWRAP_ERROR(%d) - %s: %s\n",
196 "NWRAP_WARN(%d) - %s: %s\n",
199 case NWRAP_LOG_DEBUG:
201 "NWRAP_DEBUG(%d) - %s: %s\n",
204 case NWRAP_LOG_TRACE:
206 "NWRAP_TRACE(%d) - %s: %s\n",
212 #endif /* NDEBUG NWRAP_LOG */
214 struct nwrap_libc_fns {
215 struct passwd *(*_libc_getpwnam)(const char *name);
216 int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
217 char *buf, size_t buflen, struct passwd **result);
218 struct passwd *(*_libc_getpwuid)(uid_t uid);
219 int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
220 void (*_libc_setpwent)(void);
221 struct passwd *(*_libc_getpwent)(void);
222 #ifdef HAVE_SOLARIS_GETPWENT_R
223 struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
225 int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
227 void (*_libc_endpwent)(void);
228 int (*_libc_initgroups)(const char *user, gid_t gid);
229 struct group *(*_libc_getgrnam)(const char *name);
230 int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
231 struct group *(*_libc_getgrgid)(gid_t gid);
232 int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
233 void (*_libc_setgrent)(void);
234 struct group *(*_libc_getgrent)(void);
235 #ifdef HAVE_SOLARIS_GETGRENT_R
236 struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
238 int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
240 void (*_libc_endgrent)(void);
241 int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
243 void (*_libc_sethostent)(int stayopen);
244 struct hostent *(*_libc_gethostent)(void);
245 void (*_libc_endhostent)(void);
247 struct hostent *(*_libc_gethostbyname)(const char *name);
248 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
249 struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
251 struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
253 int (*_libc_getaddrinfo)(const char *node, const char *service,
254 const struct addrinfo *hints,
255 struct addrinfo **res);
256 int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
257 char *host, size_t hostlen,
258 char *serv, size_t servlen,
260 int (*_libc_gethostname)(char *name, size_t len);
261 #ifdef HAVE_GETHOSTBYNAME_R
262 int (*_libc_gethostbyname_r)(const char *name,
264 char *buf, size_t buflen,
265 struct hostent **result, int *h_errnop);
267 #ifdef HAVE_GETHOSTBYADDR_R
268 int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
270 char *buf, size_t buflen,
271 struct hostent **result, int *h_errnop);
275 struct nwrap_module_nss_fns {
276 NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer,
277 size_t buflen, int *errnop);
278 NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer,
279 size_t buflen, int *errnop);
280 NSS_STATUS (*_nss_setpwent)(void);
281 NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer,
282 size_t buflen, int *errnop);
283 NSS_STATUS (*_nss_endpwent)(void);
284 NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start,
285 long int *size, gid_t **groups, long int limit, int *errnop);
286 NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer,
287 size_t buflen, int *errnop);
288 NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer,
289 size_t buflen, int *errnop);
290 NSS_STATUS (*_nss_setgrent)(void);
291 NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer,
292 size_t buflen, int *errnop);
293 NSS_STATUS (*_nss_endgrent)(void);
296 struct nwrap_backend {
300 struct nwrap_ops *ops;
301 struct nwrap_module_nss_fns *fns;
305 struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
307 int (*nw_getpwnam_r)(struct nwrap_backend *b,
308 const char *name, struct passwd *pwdst,
309 char *buf, size_t buflen, struct passwd **pwdstp);
310 struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
312 int (*nw_getpwuid_r)(struct nwrap_backend *b,
313 uid_t uid, struct passwd *pwdst,
314 char *buf, size_t buflen, struct passwd **pwdstp);
315 void (*nw_setpwent)(struct nwrap_backend *b);
316 struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
317 int (*nw_getpwent_r)(struct nwrap_backend *b,
318 struct passwd *pwdst, char *buf,
319 size_t buflen, struct passwd **pwdstp);
320 void (*nw_endpwent)(struct nwrap_backend *b);
321 int (*nw_initgroups)(struct nwrap_backend *b,
322 const char *user, gid_t group);
323 struct group * (*nw_getgrnam)(struct nwrap_backend *b,
325 int (*nw_getgrnam_r)(struct nwrap_backend *b,
326 const char *name, struct group *grdst,
327 char *buf, size_t buflen, struct group **grdstp);
328 struct group * (*nw_getgrgid)(struct nwrap_backend *b,
330 int (*nw_getgrgid_r)(struct nwrap_backend *b,
331 gid_t gid, struct group *grdst,
332 char *buf, size_t buflen, struct group **grdstp);
333 void (*nw_setgrent)(struct nwrap_backend *b);
334 struct group * (*nw_getgrent)(struct nwrap_backend *b);
335 int (*nw_getgrent_r)(struct nwrap_backend *b,
336 struct group *grdst, char *buf,
337 size_t buflen, struct group **grdstp);
338 void (*nw_endgrent)(struct nwrap_backend *b);
341 /* Public prototypes */
343 bool nss_wrapper_enabled(void);
344 bool nss_wrapper_hosts_enabled(void);
346 /* prototypes for files backend */
349 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
351 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
352 const char *name, struct passwd *pwdst,
353 char *buf, size_t buflen, struct passwd **pwdstp);
354 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
356 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
357 uid_t uid, struct passwd *pwdst,
358 char *buf, size_t buflen, struct passwd **pwdstp);
359 static void nwrap_files_setpwent(struct nwrap_backend *b);
360 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
361 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
362 struct passwd *pwdst, char *buf,
363 size_t buflen, struct passwd **pwdstp);
364 static void nwrap_files_endpwent(struct nwrap_backend *b);
365 static int nwrap_files_initgroups(struct nwrap_backend *b,
366 const char *user, gid_t group);
367 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
369 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
370 const char *name, struct group *grdst,
371 char *buf, size_t buflen, struct group **grdstp);
372 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
374 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
375 gid_t gid, struct group *grdst,
376 char *buf, size_t buflen, struct group **grdstp);
377 static void nwrap_files_setgrent(struct nwrap_backend *b);
378 static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
379 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
380 struct group *grdst, char *buf,
381 size_t buflen, struct group **grdstp);
382 static void nwrap_files_endgrent(struct nwrap_backend *b);
384 /* prototypes for module backend */
386 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
387 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
388 struct passwd *pwdst, char *buf,
389 size_t buflen, struct passwd **pwdstp);
390 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
392 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
393 const char *name, struct passwd *pwdst,
394 char *buf, size_t buflen, struct passwd **pwdstp);
395 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
397 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
398 uid_t uid, struct passwd *pwdst,
399 char *buf, size_t buflen, struct passwd **pwdstp);
400 static void nwrap_module_setpwent(struct nwrap_backend *b);
401 static void nwrap_module_endpwent(struct nwrap_backend *b);
402 static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
403 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
404 struct group *grdst, char *buf,
405 size_t buflen, struct group **grdstp);
406 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
408 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
409 const char *name, struct group *grdst,
410 char *buf, size_t buflen, struct group **grdstp);
411 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
413 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
414 gid_t gid, struct group *grdst,
415 char *buf, size_t buflen, struct group **grdstp);
416 static void nwrap_module_setgrent(struct nwrap_backend *b);
417 static void nwrap_module_endgrent(struct nwrap_backend *b);
418 static int nwrap_module_initgroups(struct nwrap_backend *b,
419 const char *user, gid_t group);
421 struct nwrap_ops nwrap_files_ops = {
422 .nw_getpwnam = nwrap_files_getpwnam,
423 .nw_getpwnam_r = nwrap_files_getpwnam_r,
424 .nw_getpwuid = nwrap_files_getpwuid,
425 .nw_getpwuid_r = nwrap_files_getpwuid_r,
426 .nw_setpwent = nwrap_files_setpwent,
427 .nw_getpwent = nwrap_files_getpwent,
428 .nw_getpwent_r = nwrap_files_getpwent_r,
429 .nw_endpwent = nwrap_files_endpwent,
430 .nw_initgroups = nwrap_files_initgroups,
431 .nw_getgrnam = nwrap_files_getgrnam,
432 .nw_getgrnam_r = nwrap_files_getgrnam_r,
433 .nw_getgrgid = nwrap_files_getgrgid,
434 .nw_getgrgid_r = nwrap_files_getgrgid_r,
435 .nw_setgrent = nwrap_files_setgrent,
436 .nw_getgrent = nwrap_files_getgrent,
437 .nw_getgrent_r = nwrap_files_getgrent_r,
438 .nw_endgrent = nwrap_files_endgrent,
441 struct nwrap_ops nwrap_module_ops = {
442 .nw_getpwnam = nwrap_module_getpwnam,
443 .nw_getpwnam_r = nwrap_module_getpwnam_r,
444 .nw_getpwuid = nwrap_module_getpwuid,
445 .nw_getpwuid_r = nwrap_module_getpwuid_r,
446 .nw_setpwent = nwrap_module_setpwent,
447 .nw_getpwent = nwrap_module_getpwent,
448 .nw_getpwent_r = nwrap_module_getpwent_r,
449 .nw_endpwent = nwrap_module_endpwent,
450 .nw_initgroups = nwrap_module_initgroups,
451 .nw_getgrnam = nwrap_module_getgrnam,
452 .nw_getgrnam_r = nwrap_module_getgrnam_r,
453 .nw_getgrgid = nwrap_module_getgrgid,
454 .nw_getgrgid_r = nwrap_module_getgrgid_r,
455 .nw_setgrent = nwrap_module_setgrent,
456 .nw_getgrent = nwrap_module_getgrent,
457 .nw_getgrent_r = nwrap_module_getgrent_r,
458 .nw_endgrent = nwrap_module_endgrent,
465 struct nwrap_libc_fns *fns;
470 struct nwrap_backend *backends;
471 struct nwrap_libc *libc;
474 struct nwrap_main *nwrap_main_global;
475 struct nwrap_main __nwrap_main_global;
483 bool (*parse_line)(struct nwrap_cache *, char *line);
484 void (*unload)(struct nwrap_cache *);
489 struct nwrap_cache *cache;
496 struct nwrap_cache __nwrap_cache_pw;
497 struct nwrap_pw nwrap_pw_global;
499 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
500 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
504 struct nwrap_cache *cache;
511 struct nwrap_cache __nwrap_cache_sp;
512 struct nwrap_sp nwrap_sp_global;
514 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
515 static void nwrap_sp_unload(struct nwrap_cache *nwrap);
519 struct nwrap_cache *cache;
526 struct nwrap_cache __nwrap_cache_gr;
527 struct nwrap_gr nwrap_gr_global;
530 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
531 static void nwrap_he_unload(struct nwrap_cache *nwrap);
533 struct nwrap_addrdata {
534 unsigned char host_addr[16]; /* IPv4 or IPv6 address */
535 char *h_addr_ptrs[2]; /* host_addr pointer + NULL */
538 struct nwrap_entdata {
539 struct nwrap_addrdata *addr;
544 struct nwrap_cache *cache;
546 struct nwrap_entdata *list;
551 struct nwrap_cache __nwrap_cache_he;
552 struct nwrap_he nwrap_he_global;
555 /*********************************************************
557 *********************************************************/
559 static void nwrap_init(void);
560 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
561 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
562 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
564 /*********************************************************
565 * NWRAP LIBC LOADER FUNCTIONS
566 *********************************************************/
575 static const char *nwrap_str_lib(enum nwrap_lib lib)
582 case NWRAP_LIBSOCKET:
586 /* Compiler would warn us about unhandled enum value if we get here */
591 static void *nwrap_load_lib_handle(enum nwrap_lib lib)
593 int flags = RTLD_LAZY;
598 flags |= RTLD_DEEPBIND;
604 handle = nwrap_main_global->libc->nsl_handle;
605 if (handle == NULL) {
606 for (i = 10; i >= 0; i--) {
607 char soname[256] = {0};
609 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
610 handle = dlopen(soname, flags);
611 if (handle != NULL) {
616 nwrap_main_global->libc->nsl_handle = handle;
621 case NWRAP_LIBSOCKET:
622 #ifdef HAVE_LIBSOCKET
623 handle = nwrap_main_global->libc->sock_handle;
624 if (handle == NULL) {
625 for (i = 10; i >= 0; i--) {
626 char soname[256] = {0};
628 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
629 handle = dlopen(soname, flags);
630 if (handle != NULL) {
635 nwrap_main_global->libc->sock_handle = handle;
641 handle = nwrap_main_global->libc->handle;
642 if (handle == NULL) {
643 for (i = 10; i >= 0; i--) {
644 char soname[256] = {0};
646 snprintf(soname, sizeof(soname), "libc.so.%d", i);
647 handle = dlopen(soname, flags);
648 if (handle != NULL) {
653 nwrap_main_global->libc->handle = handle;
658 if (handle == NULL) {
660 handle = nwrap_main_global->libc->handle
661 = nwrap_main_global->libc->sock_handle
662 = nwrap_main_global->libc->nsl_handle
665 NWRAP_LOG(NWRAP_LOG_ERROR,
666 "Failed to dlopen library: %s\n",
675 static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
682 handle = nwrap_load_lib_handle(lib);
684 func = dlsym(handle, fn_name);
686 NWRAP_LOG(NWRAP_LOG_ERROR,
687 "Failed to find %s: %s\n",
692 NWRAP_LOG(NWRAP_LOG_TRACE,
694 fn_name, nwrap_str_lib(lib));
698 #define nwrap_load_lib_function(lib, fn_name) \
699 if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
700 *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
701 _nwrap_load_lib_function(lib, #fn_name); \
707 * Functions expeciall from libc need to be loaded individually, you can't load
708 * all at once or gdb will segfault at startup. The same applies to valgrind and
709 * has probably something todo with with the linker.
710 * So we need load each function at the point it is called the first time.
712 static struct passwd *libc_getpwnam(const char *name)
714 nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
716 return nwrap_main_global->libc->fns->_libc_getpwnam(name);
719 #ifdef HAVE_GETPWNAM_R
720 static int libc_getpwnam_r(const char *name,
724 struct passwd **result)
726 #ifdef HAVE___POSIX_GETPWNAM_R
727 if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
728 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
729 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
732 nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
735 return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
743 static struct passwd *libc_getpwuid(uid_t uid)
745 nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
747 return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
750 #ifdef HAVE_GETPWUID_R
751 static int libc_getpwuid_r(uid_t uid,
755 struct passwd **result)
757 #ifdef HAVE___POSIX_GETPWUID_R
758 if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
759 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
760 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
763 nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
766 return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
774 static void libc_setpwent(void)
776 nwrap_load_lib_function(NWRAP_LIBC, setpwent);
778 nwrap_main_global->libc->fns->_libc_setpwent();
781 static struct passwd *libc_getpwent(void)
783 nwrap_load_lib_function(NWRAP_LIBC, getpwent);
785 return nwrap_main_global->libc->fns->_libc_getpwent();
788 #ifdef HAVE_SOLARIS_GETPWENT_R
789 static struct passwd *libc_getpwent_r(struct passwd *pwdst,
793 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
795 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
799 #else /* HAVE_SOLARIS_GETPWENT_R */
800 static int libc_getpwent_r(struct passwd *pwdst,
803 struct passwd **pwdstp)
805 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
807 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
812 #endif /* HAVE_SOLARIS_GETPWENT_R */
814 static void libc_endpwent(void)
816 nwrap_load_lib_function(NWRAP_LIBC, endpwent);
818 nwrap_main_global->libc->fns->_libc_endpwent();
821 static int libc_initgroups(const char *user, gid_t gid)
823 nwrap_load_lib_function(NWRAP_LIBC, initgroups);
825 return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
828 static struct group *libc_getgrnam(const char *name)
830 nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
832 return nwrap_main_global->libc->fns->_libc_getgrnam(name);
835 #ifdef HAVE_GETGRNAM_R
836 static int libc_getgrnam_r(const char *name,
840 struct group **result)
842 #ifdef HAVE___POSIX_GETGRNAM_R
843 if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
844 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
845 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
848 nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
851 return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
859 static struct group *libc_getgrgid(gid_t gid)
861 nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
863 return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
866 #ifdef HAVE_GETGRGID_R
867 static int libc_getgrgid_r(gid_t gid,
871 struct group **result)
873 #ifdef HAVE___POSIX_GETGRGID_R
874 if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
875 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
876 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
879 nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
882 return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
890 static void libc_setgrent(void)
892 nwrap_load_lib_function(NWRAP_LIBC, setgrent);
894 nwrap_main_global->libc->fns->_libc_setgrent();
897 static struct group *libc_getgrent(void)
899 nwrap_load_lib_function(NWRAP_LIBC, getgrent);
901 return nwrap_main_global->libc->fns->_libc_getgrent();
904 #ifdef HAVE_GETGRENT_R
905 #ifdef HAVE_SOLARIS_GETGRENT_R
906 static struct group *libc_getgrent_r(struct group *group,
910 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
912 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
916 #else /* !HAVE_SOLARIS_GETGRENT_R */
917 static int libc_getgrent_r(struct group *group,
920 struct group **result)
922 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
924 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
929 #endif /* HAVE_SOLARIS_GETGRENT_R */
930 #endif /* HAVE_GETGRENT_R */
932 static void libc_endgrent(void)
934 nwrap_load_lib_function(NWRAP_LIBC, endgrent);
936 nwrap_main_global->libc->fns->_libc_endgrent();
939 #ifdef HAVE_GETGROUPLIST
940 static int libc_getgrouplist(const char *user,
945 nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
947 return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
954 static void libc_sethostent(int stayopen)
956 nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
958 nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
961 static struct hostent *libc_gethostent(void)
963 nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
965 return nwrap_main_global->libc->fns->_libc_gethostent();
968 static void libc_endhostent(void)
970 nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
972 nwrap_main_global->libc->fns->_libc_endhostent();
975 static struct hostent *libc_gethostbyname(const char *name)
977 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
979 return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
982 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
983 static struct hostent *libc_gethostbyname2(const char *name, int af)
985 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
987 return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
991 static struct hostent *libc_gethostbyaddr(const void *addr,
995 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
997 return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
1002 static int libc_gethostname(char *name, size_t len)
1004 nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
1006 return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
1009 #ifdef HAVE_GETHOSTBYNAME_R
1010 static int libc_gethostbyname_r(const char *name,
1011 struct hostent *ret,
1014 struct hostent **result,
1017 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
1019 return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
1028 #ifdef HAVE_GETHOSTBYADDR_R
1029 static int libc_gethostbyaddr_r(const void *addr,
1032 struct hostent *ret,
1035 struct hostent **result,
1038 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
1040 return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
1051 static int libc_getaddrinfo(const char *node,
1052 const char *service,
1053 const struct addrinfo *hints,
1054 struct addrinfo **res)
1056 nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
1058 return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
1064 static int libc_getnameinfo(const struct sockaddr *sa,
1072 nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
1074 return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
1083 /*********************************************************
1084 * NWRAP NSS MODULE LOADER FUNCTIONS
1085 *********************************************************/
1087 static void *nwrap_load_module_fn(struct nwrap_backend *b,
1088 const char *fn_name)
1093 if (!b->so_handle) {
1094 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
1098 if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
1099 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1103 res = dlsym(b->so_handle, s);
1105 NWRAP_LOG(NWRAP_LOG_ERROR,
1106 "Cannot find function %s in %s",
1113 static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b)
1115 struct nwrap_module_nss_fns *fns;
1117 if (!b->so_handle) {
1121 fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns));
1126 *(void **)(&fns->_nss_getpwnam_r) =
1127 nwrap_load_module_fn(b, "getpwnam_r");
1128 *(void **)(&fns->_nss_getpwuid_r) =
1129 nwrap_load_module_fn(b, "getpwuid_r");
1130 *(void **)(&fns->_nss_setpwent) =
1131 nwrap_load_module_fn(b, "setpwent");
1132 *(void **)(&fns->_nss_getpwent_r) =
1133 nwrap_load_module_fn(b, "getpwent_r");
1134 *(void **)(&fns->_nss_endpwent) =
1135 nwrap_load_module_fn(b, "endpwent");
1136 *(void **)(&fns->_nss_initgroups) =
1137 nwrap_load_module_fn(b, "initgroups_dyn");
1138 *(void **)(&fns->_nss_getgrnam_r) =
1139 nwrap_load_module_fn(b, "getgrnam_r");
1140 *(void **)(&fns->_nss_getgrgid_r)=
1141 nwrap_load_module_fn(b, "getgrgid_r");
1142 *(void **)(&fns->_nss_setgrent) =
1143 nwrap_load_module_fn(b, "setgrent");
1144 *(void **)(&fns->_nss_getgrent_r) =
1145 nwrap_load_module_fn(b, "getgrent_r");
1146 *(void **)(&fns->_nss_endgrent) =
1147 nwrap_load_module_fn(b, "endgrent");
1152 static void *nwrap_load_module(const char *so_path)
1156 if (!so_path || !strlen(so_path)) {
1160 h = dlopen(so_path, RTLD_LAZY);
1162 NWRAP_LOG(NWRAP_LOG_ERROR,
1163 "Cannot open shared library %s",
1171 static bool nwrap_module_init(const char *name,
1172 struct nwrap_ops *ops,
1173 const char *so_path,
1175 struct nwrap_backend **backends)
1177 struct nwrap_backend *b;
1179 *backends = (struct nwrap_backend *)realloc(*backends,
1180 sizeof(struct nwrap_backend) * ((*num_backends) + 1));
1182 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1186 b = &((*backends)[*num_backends]);
1190 b->so_path = so_path;
1192 if (so_path != NULL) {
1193 b->so_handle = nwrap_load_module(so_path);
1194 b->fns = nwrap_load_module_fns(b);
1195 if (b->fns == NULL) {
1199 b->so_handle = NULL;
1208 static void nwrap_libc_init(struct nwrap_main *r)
1210 r->libc = malloc(sizeof(struct nwrap_libc));
1211 if (r->libc == NULL) {
1212 printf("Failed to allocate memory for libc");
1215 ZERO_STRUCTP(r->libc);
1217 r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
1218 if (r->libc->fns == NULL) {
1219 printf("Failed to allocate memory for libc functions");
1222 ZERO_STRUCTP(r->libc->fns);
1225 static void nwrap_backend_init(struct nwrap_main *r)
1227 const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
1228 const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1230 r->num_backends = 0;
1233 if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
1236 NWRAP_LOG(NWRAP_LOG_ERROR,
1237 "Failed to initialize 'files' backend");
1241 if (module_so_path != NULL &&
1242 module_so_path[0] != '\0' &&
1243 module_fn_name != NULL &&
1244 module_fn_name[0] != '\0') {
1245 if (!nwrap_module_init(module_fn_name,
1250 NWRAP_LOG(NWRAP_LOG_ERROR,
1251 "Failed to initialize '%s' backend",
1258 static void nwrap_init(void)
1260 static bool initialized;
1262 if (initialized) return;
1265 nwrap_main_global = &__nwrap_main_global;
1267 nwrap_libc_init(nwrap_main_global);
1269 nwrap_backend_init(nwrap_main_global);
1272 nwrap_pw_global.cache = &__nwrap_cache_pw;
1274 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
1275 nwrap_pw_global.cache->fd = -1;
1276 nwrap_pw_global.cache->private_data = &nwrap_pw_global;
1277 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
1278 nwrap_pw_global.cache->unload = nwrap_pw_unload;
1281 nwrap_sp_global.cache = &__nwrap_cache_sp;
1283 nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
1284 nwrap_sp_global.cache->fd = -1;
1285 nwrap_sp_global.cache->private_data = &nwrap_sp_global;
1286 nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
1287 nwrap_sp_global.cache->unload = nwrap_sp_unload;
1290 nwrap_gr_global.cache = &__nwrap_cache_gr;
1292 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
1293 nwrap_gr_global.cache->fd = -1;
1294 nwrap_gr_global.cache->private_data = &nwrap_gr_global;
1295 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
1296 nwrap_gr_global.cache->unload = nwrap_gr_unload;
1299 nwrap_he_global.cache = &__nwrap_cache_he;
1301 nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
1302 nwrap_he_global.cache->fd = -1;
1303 nwrap_he_global.cache->private_data = &nwrap_he_global;
1304 nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
1305 nwrap_he_global.cache->unload = nwrap_he_unload;
1308 bool nss_wrapper_enabled(void)
1312 if (nwrap_pw_global.cache->path == NULL ||
1313 nwrap_pw_global.cache->path[0] == '\0') {
1316 if (nwrap_gr_global.cache->path == NULL ||
1317 nwrap_gr_global.cache->path[0] == '\0') {
1324 bool nss_wrapper_hosts_enabled(void)
1328 if (nwrap_he_global.cache->path == NULL ||
1329 nwrap_he_global.cache->path[0] == '\0') {
1336 static bool nwrap_hostname_enabled(void)
1340 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
1347 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
1350 uint8_t *buf = NULL;
1353 if (nwrap->st.st_size == 0) {
1354 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
1358 if (nwrap->st.st_size > INT32_MAX) {
1359 NWRAP_LOG(NWRAP_LOG_ERROR,
1360 "Size[%u] larger than INT32_MAX",
1361 (unsigned)nwrap->st.st_size);
1365 ret = lseek(nwrap->fd, 0, SEEK_SET);
1367 NWRAP_LOG(NWRAP_LOG_ERROR, "lseek - rc=%d\n", ret);
1371 buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
1373 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1377 ret = read(nwrap->fd, buf, nwrap->st.st_size);
1378 if (ret != nwrap->st.st_size) {
1379 NWRAP_LOG(NWRAP_LOG_ERROR,
1381 (unsigned)nwrap->st.st_size, ret);
1385 buf[nwrap->st.st_size] = '\0';
1387 nline = (char *)buf;
1388 while (nline != NULL && nline[0] != '\0') {
1396 e = strchr(line, '\n');
1407 if (strlen(line) == 0) {
1411 ok = nwrap->parse_line(nwrap, line);
1426 static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
1428 nwrap->unload(nwrap);
1430 SAFE_FREE(nwrap->buf);
1433 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
1438 bool retried = false;
1441 if (nwrap->fd < 0) {
1442 nwrap->fd = open(nwrap->path, O_RDONLY);
1443 if (nwrap->fd < 0) {
1444 NWRAP_LOG(NWRAP_LOG_ERROR,
1445 "Unable to open '%s' readonly %d:%s",
1446 nwrap->path, nwrap->fd,
1450 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
1453 ret = fstat(nwrap->fd, &st);
1455 NWRAP_LOG(NWRAP_LOG_ERROR,
1456 "fstat(%s) - %d:%s",
1463 if (retried == false && st.st_nlink == 0) {
1464 /* maybe someone has replaced the file... */
1465 NWRAP_LOG(NWRAP_LOG_TRACE,
1466 "st_nlink == 0, reopen %s",
1469 memset(&nwrap->st, 0, sizeof(nwrap->st));
1475 if (st.st_mtime == nwrap->st.st_mtime) {
1476 NWRAP_LOG(NWRAP_LOG_TRACE,
1477 "st_mtime[%u] hasn't changed, skip reload",
1478 (unsigned)st.st_mtime);
1482 NWRAP_LOG(NWRAP_LOG_TRACE,
1483 "st_mtime has changed [%u] => [%u], start reload",
1484 (unsigned)st.st_mtime,
1485 (unsigned)nwrap->st.st_mtime);
1489 nwrap_files_cache_unload(nwrap);
1491 ok = nwrap_parse_file(nwrap);
1493 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
1494 nwrap_files_cache_unload(nwrap);
1497 NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
1501 * the caller has to call nwrap_unload() on failure
1503 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
1505 struct nwrap_pw *nwrap_pw;
1512 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1514 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
1515 pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
1517 NWRAP_LOG(NWRAP_LOG_ERROR,
1518 "realloc(%u) failed",
1519 (unsigned)list_size);
1522 nwrap_pw->list = pw;
1524 pw = &nwrap_pw->list[nwrap_pw->num];
1531 NWRAP_LOG(NWRAP_LOG_ERROR,
1532 "Invalid line[%s]: '%s'",
1542 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
1547 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1555 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
1560 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1566 pw->pw_uid = (uid_t)strtoul(c, &e, 10);
1568 NWRAP_LOG(NWRAP_LOG_ERROR,
1569 "Invalid line[%s]: '%s' - %s",
1570 line, c, strerror(errno));
1574 NWRAP_LOG(NWRAP_LOG_ERROR,
1575 "Invalid line[%s]: '%s' - %s",
1576 line, c, strerror(errno));
1580 NWRAP_LOG(NWRAP_LOG_ERROR,
1581 "Invalid line[%s]: '%s' - %s",
1582 line, c, strerror(errno));
1587 NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
1592 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1598 pw->pw_gid = (gid_t)strtoul(c, &e, 10);
1600 NWRAP_LOG(NWRAP_LOG_ERROR,
1601 "Invalid line[%s]: '%s' - %s",
1602 line, c, strerror(errno));
1606 NWRAP_LOG(NWRAP_LOG_ERROR,
1607 "Invalid line[%s]: '%s' - %s",
1608 line, c, strerror(errno));
1612 NWRAP_LOG(NWRAP_LOG_ERROR,
1613 "Invalid line[%s]: '%s' - %s",
1614 line, c, strerror(errno));
1619 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
1624 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
1632 NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
1637 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
1645 NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
1649 NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
1651 NWRAP_LOG(NWRAP_LOG_DEBUG,
1652 "Added user[%s:%s:%u:%u:%s:%s:%s]",
1653 pw->pw_name, pw->pw_passwd,
1654 pw->pw_uid, pw->pw_gid,
1655 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
1661 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
1663 struct nwrap_pw *nwrap_pw;
1664 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1666 SAFE_FREE(nwrap_pw->list);
1671 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
1672 char *buf, size_t buflen, struct passwd **dstp)
1678 first = src->pw_name;
1680 last = src->pw_shell;
1681 while (*last) last++;
1683 ofs = PTR_DIFF(last + 1, first);
1685 if (ofs > (off_t) buflen) {
1689 memcpy(buf, first, ofs);
1691 ofs = PTR_DIFF(src->pw_name, first);
1692 dst->pw_name = buf + ofs;
1693 ofs = PTR_DIFF(src->pw_passwd, first);
1694 dst->pw_passwd = buf + ofs;
1695 dst->pw_uid = src->pw_uid;
1696 dst->pw_gid = src->pw_gid;
1697 ofs = PTR_DIFF(src->pw_gecos, first);
1698 dst->pw_gecos = buf + ofs;
1699 ofs = PTR_DIFF(src->pw_dir, first);
1700 dst->pw_dir = buf + ofs;
1701 ofs = PTR_DIFF(src->pw_shell, first);
1702 dst->pw_shell = buf + ofs;
1711 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
1713 struct nwrap_sp *nwrap_sp;
1720 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
1722 list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
1723 sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
1725 NWRAP_LOG(NWRAP_LOG_ERROR,
1726 "realloc(%u) failed",
1727 (unsigned)list_size);
1730 nwrap_sp->list = sp;
1732 sp = &nwrap_sp->list[nwrap_sp->num];
1739 NWRAP_LOG(NWRAP_LOG_ERROR,
1740 "name -- Invalid line[%s]: '%s'",
1750 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
1755 NWRAP_LOG(NWRAP_LOG_ERROR,
1756 "pwd -- Invalid line[%s]: '%s'",
1773 NWRAP_LOG(NWRAP_LOG_ERROR,
1774 "lstchg -- Invalid line[%s]: '%s'",
1781 sp->sp_lstchg = strtol(c, &e, 10);
1783 NWRAP_LOG(NWRAP_LOG_ERROR,
1784 "lstchg -- Invalid line[%s]: '%s' - %s",
1785 line, c, strerror(errno));
1789 NWRAP_LOG(NWRAP_LOG_ERROR,
1790 "lstchg -- Invalid line[%s]: '%s' - %s",
1791 line, c, strerror(errno));
1795 NWRAP_LOG(NWRAP_LOG_ERROR,
1796 "lstchg -- Invalid line[%s]: '%s' - %s",
1797 line, c, strerror(errno));
1810 NWRAP_LOG(NWRAP_LOG_ERROR,
1811 "min -- Invalid line[%s]: '%s'",
1818 sp->sp_min = strtol(c, &e, 10);
1820 NWRAP_LOG(NWRAP_LOG_ERROR,
1821 "min -- Invalid line[%s]: '%s' - %s",
1822 line, c, strerror(errno));
1826 NWRAP_LOG(NWRAP_LOG_ERROR,
1827 "min -- Invalid line[%s]: '%s' - %s",
1828 line, c, strerror(errno));
1832 NWRAP_LOG(NWRAP_LOG_ERROR,
1833 "min -- Invalid line[%s]: '%s' - %s",
1834 line, c, strerror(errno));
1847 NWRAP_LOG(NWRAP_LOG_ERROR,
1848 "max -- Invalid line[%s]: '%s'",
1855 sp->sp_max = strtol(c, &e, 10);
1857 NWRAP_LOG(NWRAP_LOG_ERROR,
1858 "max -- Invalid line[%s]: '%s' - %s",
1859 line, c, strerror(errno));
1863 NWRAP_LOG(NWRAP_LOG_ERROR,
1864 "max -- Invalid line[%s]: '%s' - %s",
1865 line, c, strerror(errno));
1869 NWRAP_LOG(NWRAP_LOG_ERROR,
1870 "max -- Invalid line[%s]: '%s' - %s",
1871 line, c, strerror(errno));
1884 NWRAP_LOG(NWRAP_LOG_ERROR,
1885 "warn -- Invalid line[%s]: '%s'",
1892 sp->sp_warn = strtol(c, &e, 10);
1894 NWRAP_LOG(NWRAP_LOG_ERROR,
1895 "warn -- Invalid line[%s]: '%s' - %s",
1896 line, c, strerror(errno));
1900 NWRAP_LOG(NWRAP_LOG_ERROR,
1901 "warn -- Invalid line[%s]: '%s' - %s",
1902 line, c, strerror(errno));
1906 NWRAP_LOG(NWRAP_LOG_ERROR,
1907 "warn -- Invalid line[%s]: '%s' - %s",
1908 line, c, strerror(errno));
1921 NWRAP_LOG(NWRAP_LOG_ERROR,
1922 "inact -- Invalid line[%s]: '%s'",
1929 sp->sp_inact = strtol(c, &e, 10);
1931 NWRAP_LOG(NWRAP_LOG_ERROR,
1932 "inact -- Invalid line[%s]: '%s' - %s",
1933 line, c, strerror(errno));
1937 NWRAP_LOG(NWRAP_LOG_ERROR,
1938 "inact -- Invalid line[%s]: '%s' - %s",
1939 line, c, strerror(errno));
1943 NWRAP_LOG(NWRAP_LOG_ERROR,
1944 "inact -- Invalid line[%s]: '%s' - %s",
1945 line, c, strerror(errno));
1958 NWRAP_LOG(NWRAP_LOG_ERROR,
1959 "expire -- Invalid line[%s]: '%s'",
1966 sp->sp_expire = strtol(c, &e, 10);
1968 NWRAP_LOG(NWRAP_LOG_ERROR,
1969 "expire -- Invalid line[%s]: '%s' - %s",
1970 line, c, strerror(errno));
1974 NWRAP_LOG(NWRAP_LOG_ERROR,
1975 "expire -- Invalid line[%s]: '%s' - %s",
1976 line, c, strerror(errno));
1980 NWRAP_LOG(NWRAP_LOG_ERROR,
1981 "expire -- Invalid line[%s]: '%s' - %s",
1982 line, c, strerror(errno));
1992 static void nwrap_sp_unload(struct nwrap_cache *nwrap)
1994 struct nwrap_sp *nwrap_sp;
1995 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
1997 SAFE_FREE(nwrap_sp->list);
2003 * the caller has to call nwrap_unload() on failure
2005 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
2007 struct nwrap_gr *nwrap_gr;
2015 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2017 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
2018 gr = (struct group *)realloc(nwrap_gr->list, list_size);
2020 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
2023 nwrap_gr->list = gr;
2025 gr = &nwrap_gr->list[nwrap_gr->num];
2032 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2040 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
2045 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2053 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
2058 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2064 gr->gr_gid = (gid_t)strtoul(c, &e, 10);
2066 NWRAP_LOG(NWRAP_LOG_ERROR,
2067 "Invalid line[%s]: '%s' - %s",
2068 line, c, strerror(errno));
2072 NWRAP_LOG(NWRAP_LOG_ERROR,
2073 "Invalid line[%s]: '%s' - %s",
2074 line, c, strerror(errno));
2078 NWRAP_LOG(NWRAP_LOG_ERROR,
2079 "Invalid line[%s]: '%s' - %s",
2080 line, c, strerror(errno));
2085 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
2088 gr->gr_mem = (char **)malloc(sizeof(char *));
2090 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
2093 gr->gr_mem[0] = NULL;
2095 for(nummem=0; p; nummem++) {
2105 if (strlen(c) == 0) {
2109 m_size = sizeof(char *) * (nummem+2);
2110 m = (char **)realloc(gr->gr_mem, m_size);
2112 NWRAP_LOG(NWRAP_LOG_ERROR,
2113 "realloc(%zd) failed",
2118 gr->gr_mem[nummem] = c;
2119 gr->gr_mem[nummem+1] = NULL;
2121 NWRAP_LOG(NWRAP_LOG_TRACE,
2123 nummem, gr->gr_mem[nummem]);
2126 NWRAP_LOG(NWRAP_LOG_DEBUG,
2127 "Added group[%s:%s:%u:] with %u members",
2128 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
2134 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
2137 struct nwrap_gr *nwrap_gr;
2138 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2140 if (nwrap_gr->list) {
2141 for (i=0; i < nwrap_gr->num; i++) {
2142 SAFE_FREE(nwrap_gr->list[i].gr_mem);
2144 SAFE_FREE(nwrap_gr->list);
2151 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
2152 char *buf, size_t buflen, struct group **dstp)
2162 first = src->gr_name;
2164 lastm = src->gr_mem;
2171 last = src->gr_passwd;
2173 while (*last) last++;
2175 ofsb = PTR_DIFF(last + 1, first);
2176 ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
2178 if ((ofsb + ofsm) > (off_t) buflen) {
2182 memcpy(buf, first, ofsb);
2183 memcpy(buf + ofsb, src->gr_mem, ofsm);
2185 ofs = PTR_DIFF(src->gr_name, first);
2186 dst->gr_name = buf + ofs;
2187 ofs = PTR_DIFF(src->gr_passwd, first);
2188 dst->gr_passwd = buf + ofs;
2189 dst->gr_gid = src->gr_gid;
2191 dst->gr_mem = (char **)(buf + ofsb);
2192 for (i=0; src->gr_mem[i]; i++) {
2193 ofs = PTR_DIFF(src->gr_mem[i], first);
2194 dst->gr_mem[i] = buf + ofs;
2204 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
2206 struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
2207 struct nwrap_entdata *ed;
2209 bool do_aliases = true;
2210 ssize_t aliases_count = 0;
2215 list_size = sizeof(struct nwrap_entdata) * (nwrap_he->num + 1);
2217 ed = (struct nwrap_entdata *)realloc(nwrap_he->list, list_size);
2219 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
2222 nwrap_he->list = ed;
2224 /* set it to the last element */
2225 ed = &(nwrap_he->list[nwrap_he->num]);
2227 ed->addr = malloc(sizeof(struct nwrap_addrdata));
2228 if (ed->addr == NULL) {
2229 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
2239 /* Walk to first char */
2240 for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
2242 NWRAP_LOG(NWRAP_LOG_ERROR,
2243 "Invalid line[%s]: '%s'",
2249 for (i = p; !isspace((int)*p); p++) {
2251 NWRAP_LOG(NWRAP_LOG_ERROR,
2252 "Invalid line[%s]: '%s'",
2260 if (inet_pton(AF_INET, i, ed->addr->host_addr)) {
2261 ed->ht.h_addrtype = AF_INET;
2262 ed->ht.h_length = 4;
2264 } else if (inet_pton(AF_INET6, i, ed->addr->host_addr)) {
2265 ed->ht.h_addrtype = AF_INET6;
2266 ed->ht.h_length = 16;
2269 NWRAP_LOG(NWRAP_LOG_ERROR,
2270 "Invalid line[%s]: '%s'",
2276 ed->addr->h_addr_ptrs[0] = (char *)ed->addr->host_addr;
2277 ed->addr->h_addr_ptrs[1] = NULL;
2279 ed->ht.h_addr_list = ed->addr->h_addr_ptrs;
2287 /* Walk to first char */
2288 for (n = p; *p != '_' && !isalnum((int) *p); p++) {
2290 NWRAP_LOG(NWRAP_LOG_ERROR,
2291 "Invalid line[%s]: '%s'",
2298 for (n = p; !isspace((int)*p); p++) {
2309 /* glib's getent always dereferences he->h_aliases */
2310 ed->ht.h_aliases = malloc(sizeof(char *));
2311 if (ed->ht.h_aliases == NULL) {
2314 ed->ht.h_aliases[0] = NULL;
2319 while (do_aliases) {
2325 /* Walk to first char */
2326 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
2332 /* Only trailing spaces are left */
2337 for (a = p; !isspace((int)*p); p++) {
2346 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
2347 if (aliases == NULL) {
2350 ed->ht.h_aliases = aliases;
2352 aliases[aliases_count] = a;
2353 aliases[aliases_count + 1] = NULL;
2362 static void nwrap_he_unload(struct nwrap_cache *nwrap)
2364 struct nwrap_he *nwrap_he =
2365 (struct nwrap_he *)nwrap->private_data;
2368 if (nwrap_he->list != NULL) {
2369 for (i = 0; i < nwrap_he->num; i++) {
2370 SAFE_FREE(nwrap_he->list[i].ht.h_aliases);
2371 SAFE_FREE(nwrap_he->list[i].addr);
2373 SAFE_FREE(nwrap_he->list);
2381 /* user functions */
2382 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
2387 (void) b; /* unused */
2389 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
2391 nwrap_files_cache_reload(nwrap_pw_global.cache);
2393 for (i=0; i<nwrap_pw_global.num; i++) {
2394 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
2395 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
2396 return &nwrap_pw_global.list[i];
2398 NWRAP_LOG(NWRAP_LOG_DEBUG,
2399 "user[%s] does not match [%s]",
2401 nwrap_pw_global.list[i].pw_name);
2404 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
2410 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
2411 const char *name, struct passwd *pwdst,
2412 char *buf, size_t buflen, struct passwd **pwdstp)
2416 pw = nwrap_files_getpwnam(b, name);
2424 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2427 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
2432 (void) b; /* unused */
2434 nwrap_files_cache_reload(nwrap_pw_global.cache);
2436 for (i=0; i<nwrap_pw_global.num; i++) {
2437 if (nwrap_pw_global.list[i].pw_uid == uid) {
2438 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
2439 return &nwrap_pw_global.list[i];
2441 NWRAP_LOG(NWRAP_LOG_DEBUG,
2442 "uid[%u] does not match [%u]",
2444 nwrap_pw_global.list[i].pw_uid);
2447 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
2453 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
2454 uid_t uid, struct passwd *pwdst,
2455 char *buf, size_t buflen, struct passwd **pwdstp)
2459 pw = nwrap_files_getpwuid(b, uid);
2467 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2470 /* user enum functions */
2471 static void nwrap_files_setpwent(struct nwrap_backend *b)
2473 (void) b; /* unused */
2475 nwrap_pw_global.idx = 0;
2478 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
2482 (void) b; /* unused */
2484 if (nwrap_pw_global.idx == 0) {
2485 nwrap_files_cache_reload(nwrap_pw_global.cache);
2488 if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
2493 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
2495 NWRAP_LOG(NWRAP_LOG_DEBUG,
2496 "return user[%s] uid[%u]",
2497 pw->pw_name, pw->pw_uid);
2502 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
2503 struct passwd *pwdst, char *buf,
2504 size_t buflen, struct passwd **pwdstp)
2508 pw = nwrap_files_getpwent(b);
2516 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2519 static void nwrap_files_endpwent(struct nwrap_backend *b)
2521 (void) b; /* unused */
2523 nwrap_pw_global.idx = 0;
2526 /* misc functions */
2527 static int nwrap_files_initgroups(struct nwrap_backend *b,
2536 groups = (gid_t *)malloc(size * sizeof(gid_t));
2537 if (groups == NULL) {
2538 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
2544 nwrap_files_setgrent(b);
2545 while ((grp = nwrap_files_getgrent(b)) != NULL) {
2548 NWRAP_LOG(NWRAP_LOG_DEBUG,
2549 "Inspecting %s for group membership",
2552 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
2553 if (group != grp->gr_gid &&
2554 (strcmp(user, grp->gr_mem[i]) == 0)) {
2555 NWRAP_LOG(NWRAP_LOG_DEBUG,
2556 "%s is member of %s",
2560 groups = (gid_t *)realloc(groups,
2561 (size + 1) * sizeof(gid_t));
2562 if (groups == NULL) {
2563 NWRAP_LOG(NWRAP_LOG_ERROR,
2569 groups[size] = grp->gr_gid;
2575 nwrap_files_endgrent(b);
2577 NWRAP_LOG(NWRAP_LOG_DEBUG,
2578 "%s is member of %d groups",
2581 /* This really only works if uid_wrapper is loaded */
2582 rc = setgroups(size, groups);
2589 /* group functions */
2590 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
2595 (void) b; /* unused */
2597 nwrap_files_cache_reload(nwrap_gr_global.cache);
2599 for (i=0; i<nwrap_gr_global.num; i++) {
2600 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
2601 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
2602 return &nwrap_gr_global.list[i];
2604 NWRAP_LOG(NWRAP_LOG_DEBUG,
2605 "group[%s] does not match [%s]",
2607 nwrap_gr_global.list[i].gr_name);
2610 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
2616 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
2617 const char *name, struct group *grdst,
2618 char *buf, size_t buflen, struct group **grdstp)
2622 gr = nwrap_files_getgrnam(b, name);
2630 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2633 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
2638 (void) b; /* unused */
2640 nwrap_files_cache_reload(nwrap_gr_global.cache);
2642 for (i=0; i<nwrap_gr_global.num; i++) {
2643 if (nwrap_gr_global.list[i].gr_gid == gid) {
2644 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
2645 return &nwrap_gr_global.list[i];
2647 NWRAP_LOG(NWRAP_LOG_DEBUG,
2648 "gid[%u] does not match [%u]",
2650 nwrap_gr_global.list[i].gr_gid);
2653 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
2659 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
2660 gid_t gid, struct group *grdst,
2661 char *buf, size_t buflen, struct group **grdstp)
2665 gr = nwrap_files_getgrgid(b, gid);
2673 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2676 /* group enum functions */
2677 static void nwrap_files_setgrent(struct nwrap_backend *b)
2679 (void) b; /* unused */
2681 nwrap_gr_global.idx = 0;
2684 static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
2688 (void) b; /* unused */
2690 if (nwrap_gr_global.idx == 0) {
2691 nwrap_files_cache_reload(nwrap_gr_global.cache);
2694 if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
2699 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
2701 NWRAP_LOG(NWRAP_LOG_DEBUG,
2702 "return group[%s] gid[%u]",
2703 gr->gr_name, gr->gr_gid);
2708 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
2709 struct group *grdst, char *buf,
2710 size_t buflen, struct group **grdstp)
2714 gr = nwrap_files_getgrent(b);
2722 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2725 static void nwrap_files_endgrent(struct nwrap_backend *b)
2727 (void) b; /* unused */
2729 nwrap_gr_global.idx = 0;
2732 /* hosts functions */
2733 static struct hostent *nwrap_files_gethostbyname(const char *name, int af)
2736 char canon_name[DNS_NAME_MAX] = { 0 };
2740 nwrap_files_cache_reload(nwrap_he_global.cache);
2742 name_len = strlen(name);
2743 if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
2744 strncpy(canon_name, name, name_len - 1);
2748 for (i = 0; i < nwrap_he_global.num; i++) {
2751 he = &nwrap_he_global.list[i].ht;
2753 /* Filter by address familiy if provided */
2754 if (af != AF_UNSPEC && he->h_addrtype != af) {
2758 if (strcasecmp(he->h_name, name) == 0) {
2759 NWRAP_LOG(NWRAP_LOG_DEBUG, "name[%s] found", name);
2763 if (he->h_aliases == NULL) {
2767 for (j = 0; he->h_aliases[j] != NULL; j++) {
2768 if (strcasecmp(he->h_aliases[j], name) == 0) {
2769 NWRAP_LOG(NWRAP_LOG_DEBUG,
2781 #ifdef HAVE_GETHOSTBYNAME_R
2782 static int nwrap_gethostbyname_r(const char *name,
2783 struct hostent *ret,
2784 char *buf, size_t buflen,
2785 struct hostent **result, int *h_errnop)
2787 *result = nwrap_files_gethostbyname(name, AF_UNSPEC);
2788 if (*result != NULL) {
2789 memset(buf, '\0', buflen);
2793 *h_errnop = h_errno;
2798 int gethostbyname_r(const char *name,
2799 struct hostent *ret,
2800 char *buf, size_t buflen,
2801 struct hostent **result, int *h_errnop)
2803 if (!nss_wrapper_hosts_enabled()) {
2804 return libc_gethostbyname_r(name,
2812 return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
2816 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
2817 socklen_t len, int type)
2820 char ip[NWRAP_INET_ADDRSTRLEN] = {0};
2824 (void) len; /* unused */
2826 nwrap_files_cache_reload(nwrap_he_global.cache);
2828 a = inet_ntop(type, addr, ip, sizeof(ip));
2834 for (i = 0; i < nwrap_he_global.num; i++) {
2835 he = &nwrap_he_global.list[i].ht;
2837 if (he->h_addrtype != type) {
2841 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
2850 #ifdef HAVE_GETHOSTBYADDR_R
2851 static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
2852 struct hostent *ret,
2853 char *buf, size_t buflen,
2854 struct hostent **result, int *h_errnop)
2856 *result = nwrap_files_gethostbyaddr(addr, len, type);
2857 if (*result != NULL) {
2858 memset(buf, '\0', buflen);
2862 *h_errnop = h_errno;
2867 int gethostbyaddr_r(const void *addr, socklen_t len, int type,
2868 struct hostent *ret,
2869 char *buf, size_t buflen,
2870 struct hostent **result, int *h_errnop)
2872 if (!nss_wrapper_hosts_enabled()) {
2873 return libc_gethostbyaddr_r(addr,
2883 return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
2887 /* hosts enum functions */
2888 static void nwrap_files_sethostent(void)
2890 nwrap_he_global.idx = 0;
2893 static struct hostent *nwrap_files_gethostent(void)
2897 if (nwrap_he_global.idx == 0) {
2898 nwrap_files_cache_reload(nwrap_he_global.cache);
2901 if (nwrap_he_global.idx >= nwrap_he_global.num) {
2906 he = &nwrap_he_global.list[nwrap_he_global.idx++].ht;
2908 NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
2913 static void nwrap_files_endhostent(void)
2915 nwrap_he_global.idx = 0;
2923 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
2926 static struct passwd pwd;
2927 static char buf[1000];
2930 if (!b->fns->_nss_getpwnam_r) {
2934 status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno);
2935 if (status == NSS_STATUS_NOTFOUND) {
2938 if (status != NSS_STATUS_SUCCESS) {
2945 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
2946 const char *name, struct passwd *pwdst,
2947 char *buf, size_t buflen, struct passwd **pwdstp)
2951 (void) b; /* unused */
2952 (void) pwdst; /* unused */
2953 (void) pwdstp; /* unused */
2955 if (!b->fns->_nss_getpwnam_r) {
2956 return NSS_STATUS_NOTFOUND;
2959 ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno);
2961 case NSS_STATUS_SUCCESS:
2963 case NSS_STATUS_NOTFOUND:
2968 case NSS_STATUS_TRYAGAIN:
2981 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
2984 static struct passwd pwd;
2985 static char buf[1000];
2988 if (!b->fns->_nss_getpwuid_r) {
2992 status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno);
2993 if (status == NSS_STATUS_NOTFOUND) {
2996 if (status != NSS_STATUS_SUCCESS) {
3002 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
3003 uid_t uid, struct passwd *pwdst,
3004 char *buf, size_t buflen, struct passwd **pwdstp)
3008 (void) pwdstp; /* unused */
3010 if (!b->fns->_nss_getpwuid_r) {
3014 ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno);
3016 case NSS_STATUS_SUCCESS:
3018 case NSS_STATUS_NOTFOUND:
3023 case NSS_STATUS_TRYAGAIN:
3036 static void nwrap_module_setpwent(struct nwrap_backend *b)
3038 if (!b->fns->_nss_setpwent) {
3042 b->fns->_nss_setpwent();
3045 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
3047 static struct passwd pwd;
3048 static char buf[1000];
3051 if (!b->fns->_nss_getpwent_r) {
3055 status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno);
3056 if (status == NSS_STATUS_NOTFOUND) {
3059 if (status != NSS_STATUS_SUCCESS) {
3065 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
3066 struct passwd *pwdst, char *buf,
3067 size_t buflen, struct passwd **pwdstp)
3071 (void) pwdstp; /* unused */
3073 if (!b->fns->_nss_getpwent_r) {
3077 ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno);
3079 case NSS_STATUS_SUCCESS:
3081 case NSS_STATUS_NOTFOUND:
3086 case NSS_STATUS_TRYAGAIN:
3099 static void nwrap_module_endpwent(struct nwrap_backend *b)
3101 if (!b->fns->_nss_endpwent) {
3105 b->fns->_nss_endpwent();
3108 static int nwrap_module_initgroups(struct nwrap_backend *b,
3109 const char *user, gid_t group)
3115 if (!b->fns->_nss_initgroups) {
3116 return NSS_STATUS_UNAVAIL;
3119 return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno);
3122 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
3125 static struct group grp;
3127 static int buflen = 1000;
3130 if (!b->fns->_nss_getgrnam_r) {
3135 buf = (char *)malloc(buflen);
3138 status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno);
3139 if (status == NSS_STATUS_TRYAGAIN) {
3141 buf = (char *)realloc(buf, buflen);
3147 if (status == NSS_STATUS_NOTFOUND) {
3151 if (status != NSS_STATUS_SUCCESS) {
3158 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
3159 const char *name, struct group *grdst,
3160 char *buf, size_t buflen, struct group **grdstp)
3164 (void) grdstp; /* unused */
3166 if (!b->fns->_nss_getgrnam_r) {
3170 ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno);
3172 case NSS_STATUS_SUCCESS:
3174 case NSS_STATUS_NOTFOUND:
3179 case NSS_STATUS_TRYAGAIN:
3192 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
3195 static struct group grp;
3197 static int buflen = 1000;
3200 if (!b->fns->_nss_getgrgid_r) {
3205 buf = (char *)malloc(buflen);
3209 status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno);
3210 if (status == NSS_STATUS_TRYAGAIN) {
3212 buf = (char *)realloc(buf, buflen);
3218 if (status == NSS_STATUS_NOTFOUND) {
3222 if (status != NSS_STATUS_SUCCESS) {
3229 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
3230 gid_t gid, struct group *grdst,
3231 char *buf, size_t buflen, struct group **grdstp)
3235 (void) grdstp; /* unused */
3237 if (!b->fns->_nss_getgrgid_r) {
3241 ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno);
3243 case NSS_STATUS_SUCCESS:
3245 case NSS_STATUS_NOTFOUND:
3250 case NSS_STATUS_TRYAGAIN:
3263 static void nwrap_module_setgrent(struct nwrap_backend *b)
3265 if (!b->fns->_nss_setgrent) {
3269 b->fns->_nss_setgrent();
3272 static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
3274 static struct group grp;
3276 static int buflen = 1024;
3279 if (!b->fns->_nss_getgrent_r) {
3284 buf = (char *)malloc(buflen);
3288 status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno);
3289 if (status == NSS_STATUS_TRYAGAIN) {
3291 buf = (char *)realloc(buf, buflen);
3297 if (status == NSS_STATUS_NOTFOUND) {
3301 if (status != NSS_STATUS_SUCCESS) {
3308 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
3309 struct group *grdst, char *buf,
3310 size_t buflen, struct group **grdstp)
3314 (void) grdstp; /* unused */
3316 if (!b->fns->_nss_getgrent_r) {
3320 ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno);
3322 case NSS_STATUS_SUCCESS:
3324 case NSS_STATUS_NOTFOUND:
3329 case NSS_STATUS_TRYAGAIN:
3342 static void nwrap_module_endgrent(struct nwrap_backend *b)
3344 if (!b->fns->_nss_endgrent) {
3348 b->fns->_nss_endgrent();
3351 /****************************************************************************
3353 ***************************************************************************/
3355 static struct passwd *nwrap_getpwnam(const char *name)
3360 for (i=0; i < nwrap_main_global->num_backends; i++) {
3361 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3362 pwd = b->ops->nw_getpwnam(b, name);
3371 struct passwd *getpwnam(const char *name)
3373 if (!nss_wrapper_enabled()) {
3374 return libc_getpwnam(name);
3377 return nwrap_getpwnam(name);
3380 /****************************************************************************
3382 ***************************************************************************/
3384 static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
3385 char *buf, size_t buflen, struct passwd **pwdstp)
3389 for (i=0; i < nwrap_main_global->num_backends; i++) {
3390 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3391 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
3392 if (ret == ENOENT) {
3401 #ifdef HAVE_GETPWNAM_R
3402 # ifdef HAVE_SOLARIS_GETPWNAM_R
3403 int getpwnam_r(const char *name, struct passwd *pwdst,
3404 char *buf, int buflen, struct passwd **pwdstp)
3405 # else /* HAVE_SOLARIS_GETPWNAM_R */
3406 int getpwnam_r(const char *name, struct passwd *pwdst,
3407 char *buf, size_t buflen, struct passwd **pwdstp)
3408 # endif /* HAVE_SOLARIS_GETPWNAM_R */
3410 if (!nss_wrapper_enabled()) {
3411 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
3414 return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
3418 /****************************************************************************
3420 ***************************************************************************/
3422 static struct passwd *nwrap_getpwuid(uid_t uid)
3427 for (i=0; i < nwrap_main_global->num_backends; i++) {
3428 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3429 pwd = b->ops->nw_getpwuid(b, uid);
3438 struct passwd *getpwuid(uid_t uid)
3440 if (!nss_wrapper_enabled()) {
3441 return libc_getpwuid(uid);
3444 return nwrap_getpwuid(uid);
3447 /****************************************************************************
3449 ***************************************************************************/
3451 static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
3452 char *buf, size_t buflen, struct passwd **pwdstp)
3456 for (i=0; i < nwrap_main_global->num_backends; i++) {
3457 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3458 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
3459 if (ret == ENOENT) {
3468 #ifdef HAVE_SOLARIS_GETPWUID_R
3469 int getpwuid_r(uid_t uid, struct passwd *pwdst,
3470 char *buf, int buflen, struct passwd **pwdstp)
3472 int getpwuid_r(uid_t uid, struct passwd *pwdst,
3473 char *buf, size_t buflen, struct passwd **pwdstp)
3476 if (!nss_wrapper_enabled()) {
3477 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
3480 return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
3483 /****************************************************************************
3485 ***************************************************************************/
3487 static void nwrap_setpwent(void)
3491 for (i=0; i < nwrap_main_global->num_backends; i++) {
3492 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3493 b->ops->nw_setpwent(b);
3499 if (!nss_wrapper_enabled()) {
3507 /****************************************************************************
3509 ***************************************************************************/
3511 static struct passwd *nwrap_getpwent(void)
3516 for (i=0; i < nwrap_main_global->num_backends; i++) {
3517 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3518 pwd = b->ops->nw_getpwent(b);
3527 struct passwd *getpwent(void)
3529 if (!nss_wrapper_enabled()) {
3530 return libc_getpwent();
3533 return nwrap_getpwent();
3536 /****************************************************************************
3538 ***************************************************************************/
3540 static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
3541 size_t buflen, struct passwd **pwdstp)
3545 for (i=0; i < nwrap_main_global->num_backends; i++) {
3546 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3547 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
3548 if (ret == ENOENT) {
3557 #ifdef HAVE_SOLARIS_GETPWENT_R
3558 struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
3560 struct passwd *pwdstp = NULL;
3563 if (!nss_wrapper_enabled()) {
3564 return libc_getpwent_r(pwdst, buf, buflen);
3566 rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
3573 #else /* HAVE_SOLARIS_GETPWENT_R */
3574 int getpwent_r(struct passwd *pwdst, char *buf,
3575 size_t buflen, struct passwd **pwdstp)
3577 if (!nss_wrapper_enabled()) {
3578 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
3581 return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
3583 #endif /* HAVE_SOLARIS_GETPWENT_R */
3585 /****************************************************************************
3587 ***************************************************************************/
3589 static void nwrap_endpwent(void)
3593 for (i=0; i < nwrap_main_global->num_backends; i++) {
3594 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3595 b->ops->nw_endpwent(b);
3601 if (!nss_wrapper_enabled()) {
3609 /****************************************************************************
3611 ***************************************************************************/
3613 static int nwrap_initgroups(const char *user, gid_t group)
3617 for (i=0; i < nwrap_main_global->num_backends; i++) {
3618 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3621 rc = b->ops->nw_initgroups(b, user, group);
3631 int initgroups(const char *user, gid_t group)
3633 if (!nss_wrapper_enabled()) {
3634 return libc_initgroups(user, group);
3637 return nwrap_initgroups(user, group);
3640 /****************************************************************************
3642 ***************************************************************************/
3644 static struct group *nwrap_getgrnam(const char *name)
3649 for (i=0; i < nwrap_main_global->num_backends; i++) {
3650 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3651 grp = b->ops->nw_getgrnam(b, name);
3660 struct group *getgrnam(const char *name)
3662 if (!nss_wrapper_enabled()) {
3663 return libc_getgrnam(name);
3666 return nwrap_getgrnam(name);
3669 /****************************************************************************
3671 ***************************************************************************/
3673 static int nwrap_getgrnam_r(const char *name, struct group *grdst,
3674 char *buf, size_t buflen, struct group **grdstp)
3678 for (i=0; i < nwrap_main_global->num_backends; i++) {
3679 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3680 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
3681 if (ret == ENOENT) {
3690 #ifdef HAVE_GETGRNAM_R
3691 # ifdef HAVE_SOLARIS_GETGRNAM_R
3692 int getgrnam_r(const char *name, struct group *grp,
3693 char *buf, int buflen, struct group **pgrp)
3694 # else /* HAVE_SOLARIS_GETGRNAM_R */
3695 int getgrnam_r(const char *name, struct group *grp,
3696 char *buf, size_t buflen, struct group **pgrp)
3697 # endif /* HAVE_SOLARIS_GETGRNAM_R */
3699 if (!nss_wrapper_enabled()) {
3700 return libc_getgrnam_r(name,
3707 return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
3709 #endif /* HAVE_GETGRNAM_R */
3711 /****************************************************************************
3713 ***************************************************************************/
3715 static struct group *nwrap_getgrgid(gid_t gid)
3720 for (i=0; i < nwrap_main_global->num_backends; i++) {
3721 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3722 grp = b->ops->nw_getgrgid(b, gid);
3731 struct group *getgrgid(gid_t gid)
3733 if (!nss_wrapper_enabled()) {
3734 return libc_getgrgid(gid);
3737 return nwrap_getgrgid(gid);
3740 /****************************************************************************
3742 ***************************************************************************/
3744 static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
3745 char *buf, size_t buflen, struct group **grdstp)
3749 for (i=0; i < nwrap_main_global->num_backends; i++) {
3750 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3751 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
3752 if (ret == ENOENT) {
3761 #ifdef HAVE_GETGRGID_R
3762 # ifdef HAVE_SOLARIS_GETGRGID_R
3763 int getgrgid_r(gid_t gid, struct group *grdst,
3764 char *buf, int buflen, struct group **grdstp)
3765 # else /* HAVE_SOLARIS_GETGRGID_R */
3766 int getgrgid_r(gid_t gid, struct group *grdst,
3767 char *buf, size_t buflen, struct group **grdstp)
3768 # endif /* HAVE_SOLARIS_GETGRGID_R */
3770 if (!nss_wrapper_enabled()) {
3771 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
3774 return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
3778 /****************************************************************************
3780 ***************************************************************************/
3782 static void nwrap_setgrent(void)
3786 for (i=0; i < nwrap_main_global->num_backends; i++) {
3787 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3788 b->ops->nw_setgrent(b);
3792 #ifdef HAVE_BSD_SETGRENT
3798 if (!nss_wrapper_enabled()) {
3806 #ifdef HAVE_BSD_SETGRENT
3813 /****************************************************************************
3815 ***************************************************************************/
3817 static struct group *nwrap_getgrent(void)
3822 for (i=0; i < nwrap_main_global->num_backends; i++) {
3823 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3824 grp = b->ops->nw_getgrent(b);
3833 struct group *getgrent(void)
3835 if (!nss_wrapper_enabled()) {
3836 return libc_getgrent();
3839 return nwrap_getgrent();
3842 /****************************************************************************
3844 ***************************************************************************/
3846 static int nwrap_getgrent_r(struct group *grdst, char *buf,
3847 size_t buflen, struct group **grdstp)
3851 for (i=0; i < nwrap_main_global->num_backends; i++) {
3852 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3853 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
3854 if (ret == ENOENT) {
3863 #ifdef HAVE_SOLARIS_GETGRENT_R
3864 struct group *getgrent_r(struct group *src, char *buf, int buflen)
3866 struct group *grdstp = NULL;
3869 if (!nss_wrapper_enabled()) {
3870 return libc_getgrent_r(src, buf, buflen);
3873 rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
3880 #else /* HAVE_SOLARIS_GETGRENT_R */
3881 int getgrent_r(struct group *src, char *buf,
3882 size_t buflen, struct group **grdstp)
3884 if (!nss_wrapper_enabled()) {
3885 return libc_getgrent_r(src, buf, buflen, grdstp);
3888 return nwrap_getgrent_r(src, buf, buflen, grdstp);
3890 #endif /* HAVE_SOLARIS_GETGRENT_R */
3892 /****************************************************************************
3894 ***************************************************************************/
3896 static void nwrap_endgrent(void)
3900 for (i=0; i < nwrap_main_global->num_backends; i++) {
3901 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3902 b->ops->nw_endgrent(b);
3908 if (!nss_wrapper_enabled()) {
3916 /****************************************************************************
3918 ***************************************************************************/
3920 #ifdef HAVE_GETGROUPLIST
3921 static int nwrap_getgrouplist(const char *user, gid_t group,
3922 gid_t *groups, int *ngroups)
3928 NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
3930 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
3932 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
3936 groups_tmp[0] = group;
3939 while ((grp = nwrap_getgrent()) != NULL) {
3942 NWRAP_LOG(NWRAP_LOG_DEBUG,
3943 "Inspecting %s for group membership",
3946 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
3948 if (group != grp->gr_gid &&
3949 (strcmp(user, grp->gr_mem[i]) == 0)) {
3951 NWRAP_LOG(NWRAP_LOG_DEBUG,
3952 "%s is member of %s",
3956 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
3958 NWRAP_LOG(NWRAP_LOG_ERROR,
3963 groups_tmp[count] = grp->gr_gid;
3972 NWRAP_LOG(NWRAP_LOG_DEBUG,
3973 "%s is member of %d groups",
3976 if (*ngroups < count) {
3983 memcpy(groups, groups_tmp, count * sizeof(gid_t));
3989 int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
3991 if (!nss_wrapper_enabled()) {
3992 return libc_getgrouplist(user, group, groups, ngroups);
3995 return nwrap_getgrouplist(user, group, groups, ngroups);
3999 /**********************************************************
4001 **********************************************************/
4003 static void nwrap_sethostent(int stayopen) {
4004 (void) stayopen; /* ignored */
4006 nwrap_files_sethostent();
4009 #ifdef HAVE_SOLARIS_SETHOSTENT
4010 int sethostent(int stayopen)
4012 if (!nss_wrapper_hosts_enabled()) {
4013 libc_sethostent(stayopen);
4017 nwrap_sethostent(stayopen);
4021 #else /* HAVE_SOLARIS_SETHOSTENT */
4022 void sethostent(int stayopen)
4024 if (!nss_wrapper_hosts_enabled()) {
4025 libc_sethostent(stayopen);
4029 nwrap_sethostent(stayopen);
4031 #endif /* HAVE_SOLARIS_SETHOSTENT */
4033 static struct hostent *nwrap_gethostent(void)
4035 return nwrap_files_gethostent();
4038 struct hostent *gethostent(void) {
4039 if (!nss_wrapper_hosts_enabled()) {
4040 return libc_gethostent();
4043 return nwrap_gethostent();
4046 static void nwrap_endhostent(void) {
4047 nwrap_files_endhostent();
4050 #ifdef HAVE_SOLARIS_ENDHOSTENT
4051 int endhostent(void)
4053 if (!nss_wrapper_hosts_enabled()) {
4062 #else /* HAVE_SOLARIS_ENDHOSTENT */
4063 void endhostent(void)
4065 if (!nss_wrapper_hosts_enabled()) {
4072 #endif /* HAVE_SOLARIS_ENDHOSTENT */
4074 static struct hostent *nwrap_gethostbyname(const char *name)
4076 return nwrap_files_gethostbyname(name, AF_UNSPEC);
4079 struct hostent *gethostbyname(const char *name)
4081 if (!nss_wrapper_hosts_enabled()) {
4082 return libc_gethostbyname(name);
4085 return nwrap_gethostbyname(name);
4088 /* This is a GNU extension */
4089 #ifdef HAVE_GETHOSTBYNAME2
4090 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
4092 return nwrap_files_gethostbyname(name, af);
4095 struct hostent *gethostbyname2(const char *name, int af)
4097 if (!nss_wrapper_hosts_enabled()) {
4098 return libc_gethostbyname2(name, af);
4101 return nwrap_gethostbyname2(name, af);
4105 static struct hostent *nwrap_gethostbyaddr(const void *addr,
4106 socklen_t len, int type)
4108 return nwrap_files_gethostbyaddr(addr, len, type);
4111 struct hostent *gethostbyaddr(const void *addr,
4112 socklen_t len, int type)
4114 if (!nss_wrapper_hosts_enabled()) {
4115 return libc_gethostbyaddr(addr, len, type);
4118 return nwrap_gethostbyaddr(addr, len, type);
4121 static const struct addrinfo default_hints =
4123 .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
4124 .ai_family = AF_UNSPEC,
4129 .ai_canonname = NULL,
4133 static int nwrap_convert_he_ai(const struct hostent *he,
4134 unsigned short port,
4135 const struct addrinfo *hints,
4136 struct addrinfo **pai)
4138 struct addrinfo *ai;
4141 switch (he->h_addrtype) {
4143 socklen = sizeof(struct sockaddr_in);
4147 socklen = sizeof(struct sockaddr_in6);
4154 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
4160 ai->ai_family = he->h_addrtype;
4161 ai->ai_socktype = hints->ai_socktype;
4162 ai->ai_protocol = hints->ai_protocol;
4164 ai->ai_addrlen = socklen;
4165 ai->ai_addr = (void *)(ai + 1);
4167 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
4168 ai->ai_addr->sa_len = socklen;
4170 ai->ai_addr->sa_family = he->h_addrtype;
4172 switch (he->h_addrtype) {
4175 struct sockaddr_in *sinp =
4176 (struct sockaddr_in *) ai->ai_addr;
4178 memset(sinp, 0, sizeof(struct sockaddr_in));
4180 sinp->sin_port = htons(port);
4181 sinp->sin_family = AF_INET;
4183 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
4184 memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
4191 struct sockaddr_in6 *sin6p =
4192 (struct sockaddr_in6 *) ai->ai_addr;
4194 memset(sin6p, 0, sizeof(struct sockaddr_in6));
4196 sin6p->sin6_port = htons(port);
4197 sin6p->sin6_family = AF_INET6;
4199 memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length);
4208 ai->ai_canonname = strdup(he->h_name);
4209 if (ai->ai_canonname == NULL) {
4219 static int nwrap_getaddrinfo(const char *node,
4220 const char *service,
4221 const struct addrinfo *hints,
4222 struct addrinfo **res)
4224 struct addrinfo *ai = NULL;
4225 struct addrinfo *p = NULL;
4226 unsigned short port = 0;
4237 .family = AF_UNSPEC,
4239 int eai = EAI_SYSTEM;
4243 if (node == NULL && service == NULL) {
4247 ret = libc_getaddrinfo(node, service, hints, &p);
4252 /* If no node has been specified, let glibc deal with it */
4257 if (hints == NULL) {
4258 hints = &default_hints;
4261 if ((hints->ai_flags & AI_CANONNAME) && node == NULL) {
4262 return EAI_BADFLAGS;
4265 if (service != NULL && service[0] != '\0') {
4266 if (isdigit((int)service[0])) {
4267 port = (unsigned short)atoi(service);
4269 const char *proto = NULL;
4272 if (hints->ai_protocol != 0) {
4273 struct protoent *pent;
4275 pent = getprotobynumber(hints->ai_protocol);
4277 proto = pent->p_name;
4281 s = getservbyname(service, proto);
4283 port = ntohs(s->s_port);
4294 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
4295 rc = inet_pton(AF_INET, node, &addr.in.v4);
4298 addr.family = AF_INET;
4301 rc = inet_pton(AF_INET6, node, &addr.in.v6);
4303 addr.family = AF_INET6;
4308 if (addr.family == AF_INET) {
4309 he = nwrap_files_gethostbyaddr(&addr.in.v4,
4310 sizeof(struct in_addr),
4313 rc = nwrap_convert_he_ai(he, port, hints, &ai);
4319 } else if (addr.family == AF_INET6) {
4320 he = nwrap_files_gethostbyaddr(&addr.in.v6,
4321 sizeof(struct in6_addr),
4324 rc = nwrap_convert_he_ai(he, port, hints, &ai);
4332 he = nwrap_files_gethostbyname(node, hints->ai_family);
4334 rc = nwrap_convert_he_ai(he, port, hints, &ai);
4343 return ret == 0 ? 0 : eai;
4350 if (ai->ai_flags == 0) {
4351 ai->ai_flags = hints->ai_flags;
4353 if (ai->ai_socktype == 0) {
4354 ai->ai_socktype = SOCK_DGRAM;
4356 if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) {
4357 ai->ai_protocol = 17; /* UDP */
4358 } else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
4359 ai->ai_protocol = 6; /* TCP */
4362 if (hints->ai_socktype == 0) {
4364 rc = nwrap_convert_he_ai(he, port, hints, &ai->ai_next);
4370 if (ai->ai_next->ai_flags == 0) {
4371 ai->ai_next->ai_flags = hints->ai_flags;
4373 if (ai->ai_socktype == SOCK_DGRAM) {
4374 ai->ai_next->ai_socktype = SOCK_STREAM;
4375 } else if (ai->ai_socktype == SOCK_STREAM) {
4376 ai->ai_next->ai_socktype = SOCK_DGRAM;
4378 if (ai->ai_next->ai_socktype == SOCK_DGRAM) {
4379 ai->ai_next->ai_protocol = 17; /* UDP */
4380 } else if (ai->ai_next->ai_socktype == SOCK_STREAM) {
4381 ai->ai_next->ai_protocol = 6; /* TCP */
4390 int getaddrinfo(const char *node, const char *service,
4391 const struct addrinfo *hints,
4392 struct addrinfo **res)
4394 if (!nss_wrapper_hosts_enabled()) {
4395 return libc_getaddrinfo(node, service, hints, res);
4398 return nwrap_getaddrinfo(node, service, hints, res);
4401 static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
4402 char *host, size_t hostlen,
4403 char *serv, size_t servlen,
4407 struct servent *service;
4414 if (sa == NULL || salen < sizeof(sa_family_t)) {
4418 if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
4422 type = sa->sa_family;
4425 if (salen < sizeof(struct sockaddr_in))
4427 addr = &((const struct sockaddr_in *)sa)->sin_addr;
4428 addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
4429 port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
4433 if (salen < sizeof(struct sockaddr_in6))
4435 addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
4436 addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
4437 port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
4446 if ((flags & NI_NUMERICHOST) == 0) {
4447 he = nwrap_files_gethostbyaddr(addr, addrlen, type);
4448 if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
4451 if (he != NULL && he->h_name != NULL) {
4452 if (strlen(he->h_name) >= hostlen)
4453 return EAI_OVERFLOW;
4454 strcpy(host, he->h_name);
4455 if (flags & NI_NOFQDN)
4456 host[strcspn(host, ".")] = '\0';
4458 if (inet_ntop(type, addr, host, hostlen) == NULL)
4459 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
4465 if ((flags & NI_NUMERICSERV) == 0) {
4466 proto = (flags & NI_DGRAM) ? "udp" : "tcp";
4467 service = getservbyport(htons(port), proto);
4469 if (service != NULL) {
4470 if (strlen(service->s_name) >= servlen)
4471 return EAI_OVERFLOW;
4472 strcpy(serv, service->s_name);
4474 if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
4475 return EAI_OVERFLOW;
4482 #ifdef HAVE_LINUX_GETNAMEINFO
4483 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4484 char *host, socklen_t hostlen,
4485 char *serv, socklen_t servlen,
4487 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
4488 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4489 char *host, socklen_t hostlen,
4490 char *serv, socklen_t servlen,
4493 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4494 char *host, size_t hostlen,
4495 char *serv, size_t servlen,
4499 if (!nss_wrapper_hosts_enabled()) {
4500 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
4503 return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
4506 static int nwrap_gethostname(char *name, size_t len)
4508 const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
4510 if (strlen(hostname) >= len) {
4511 errno = ENAMETOOLONG;
4514 snprintf(name, len, "%s", hostname);
4519 #ifdef HAVE_SOLARIS_GETHOSTNAME
4520 int gethostname(char *name, int len)
4521 #else /* HAVE_SOLARIS_GETHOSTNAME */
4522 int gethostname(char *name, size_t len)
4523 #endif /* HAVE_SOLARIS_GETHOSTNAME */
4525 if (!nwrap_hostname_enabled()) {
4526 return libc_gethostname(name, len);
4529 return nwrap_gethostname(name, len);
4532 /****************************
4534 ***************************/
4537 * This function is called when the library is unloaded and makes sure that
4538 * sockets get closed and the unix file for the socket are unlinked.
4540 void nwrap_destructor(void)
4544 if (nwrap_main_global != NULL) {
4545 struct nwrap_main *m = nwrap_main_global;
4548 SAFE_FREE(m->libc->fns);
4549 if (m->libc->handle != NULL) {
4550 dlclose(m->libc->handle);
4552 if (m->libc->nsl_handle != NULL) {
4553 dlclose(m->libc->nsl_handle);
4555 if (m->libc->sock_handle != NULL) {
4556 dlclose(m->libc->sock_handle);
4561 for (i = 0; i < m->num_backends; i++) {
4562 struct nwrap_backend *b = &(m->backends[i]);
4564 if (b->so_handle != NULL) {
4565 dlclose(b->so_handle);
4569 SAFE_FREE(m->backends);
4572 if (nwrap_pw_global.cache != NULL) {
4573 struct nwrap_cache *c = nwrap_pw_global.cache;
4575 nwrap_files_cache_unload(c);
4580 SAFE_FREE(nwrap_pw_global.list);
4581 nwrap_pw_global.num = 0;
4584 if (nwrap_gr_global.cache != NULL) {
4585 struct nwrap_cache *c = nwrap_gr_global.cache;
4587 nwrap_files_cache_unload(c);
4592 SAFE_FREE(nwrap_gr_global.list);
4593 nwrap_pw_global.num = 0;
4596 if (nwrap_he_global.cache != NULL) {
4597 struct nwrap_cache *c = nwrap_he_global.cache;
4599 nwrap_files_cache_unload(c);
4604 SAFE_FREE(nwrap_he_global.list);
4605 nwrap_he_global.num = 0;