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>
57 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
58 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
61 #ifndef _POSIX_PTHREAD_SEMANTICS
62 #define _POSIX_PTHREAD_SEMANTICS
69 #endif /* HAVE_SHADOW_H */
72 #include <arpa/inet.h>
73 #include <netinet/in.h>
77 #if defined(HAVE_NSS_H)
81 typedef enum nss_status NSS_STATUS;
82 #elif defined(HAVE_NSS_COMMON_H)
84 #include <nss_common.h>
85 #include <nss_dbdefs.h>
88 typedef nss_status_t NSS_STATUS;
90 # define NSS_STATUS_SUCCESS NSS_SUCCESS
91 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
92 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
93 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
95 # error "No nsswitch support detected"
99 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
107 #define EAI_NODATA EAI_NONAME
110 #ifndef EAI_ADDRFAMILY
111 #define EAI_ADDRFAMILY EAI_FAMILY
115 #define __STRING(x) #x
118 #ifndef __STRINGSTRING
119 #define __STRINGSTRING(x) __STRING(x)
123 #define __LINESTR__ __STRINGSTRING(__LINE__)
127 #define __location__ __FILE__ ":" __LINESTR__
131 #define DNS_NAME_MAX 255
134 /* GCC have printf type attribute check. */
135 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
136 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
138 #define PRINTF_ATTRIBUTE(a,b)
139 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
141 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
142 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
144 #define DESTRUCTOR_ATTRIBUTE
145 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
147 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
150 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
154 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
156 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
159 enum nwrap_dbglvl_e {
167 # define NWRAP_LOG(...)
170 static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
171 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
173 static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
175 const char *format, ...)
180 unsigned int lvl = 0;
183 d = getenv("NSS_WRAPPER_DEBUGLEVEL");
188 va_start(va, format);
189 vsnprintf(buffer, sizeof(buffer), format, va);
194 case NWRAP_LOG_ERROR:
196 "NWRAP_ERROR(%d) - %s: %s\n",
201 "NWRAP_WARN(%d) - %s: %s\n",
204 case NWRAP_LOG_DEBUG:
206 "NWRAP_DEBUG(%d) - %s: %s\n",
209 case NWRAP_LOG_TRACE:
211 "NWRAP_TRACE(%d) - %s: %s\n",
217 #endif /* NDEBUG NWRAP_LOG */
219 struct nwrap_libc_fns {
220 struct passwd *(*_libc_getpwnam)(const char *name);
221 int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
222 char *buf, size_t buflen, struct passwd **result);
223 struct passwd *(*_libc_getpwuid)(uid_t uid);
224 int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
225 void (*_libc_setpwent)(void);
226 struct passwd *(*_libc_getpwent)(void);
227 #ifdef HAVE_SOLARIS_GETPWENT_R
228 struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
230 int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
232 void (*_libc_endpwent)(void);
233 int (*_libc_initgroups)(const char *user, gid_t gid);
234 struct group *(*_libc_getgrnam)(const char *name);
235 int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
236 struct group *(*_libc_getgrgid)(gid_t gid);
237 int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
238 void (*_libc_setgrent)(void);
239 struct group *(*_libc_getgrent)(void);
240 #ifdef HAVE_SOLARIS_GETGRENT_R
241 struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
243 int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
245 void (*_libc_endgrent)(void);
246 int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
248 void (*_libc_sethostent)(int stayopen);
249 struct hostent *(*_libc_gethostent)(void);
250 void (*_libc_endhostent)(void);
252 struct hostent *(*_libc_gethostbyname)(const char *name);
253 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
254 struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
256 struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
258 int (*_libc_getaddrinfo)(const char *node, const char *service,
259 const struct addrinfo *hints,
260 struct addrinfo **res);
261 int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
262 char *host, size_t hostlen,
263 char *serv, size_t servlen,
265 int (*_libc_gethostname)(char *name, size_t len);
266 #ifdef HAVE_GETHOSTBYNAME_R
267 int (*_libc_gethostbyname_r)(const char *name,
269 char *buf, size_t buflen,
270 struct hostent **result, int *h_errnop);
272 #ifdef HAVE_GETHOSTBYADDR_R
273 int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
275 char *buf, size_t buflen,
276 struct hostent **result, int *h_errnop);
280 struct nwrap_module_nss_fns {
281 NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer,
282 size_t buflen, int *errnop);
283 NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer,
284 size_t buflen, int *errnop);
285 NSS_STATUS (*_nss_setpwent)(void);
286 NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer,
287 size_t buflen, int *errnop);
288 NSS_STATUS (*_nss_endpwent)(void);
289 NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start,
290 long int *size, gid_t **groups, long int limit, int *errnop);
291 NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer,
292 size_t buflen, int *errnop);
293 NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer,
294 size_t buflen, int *errnop);
295 NSS_STATUS (*_nss_setgrent)(void);
296 NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer,
297 size_t buflen, int *errnop);
298 NSS_STATUS (*_nss_endgrent)(void);
301 struct nwrap_backend {
305 struct nwrap_ops *ops;
306 struct nwrap_module_nss_fns *fns;
310 struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
312 int (*nw_getpwnam_r)(struct nwrap_backend *b,
313 const char *name, struct passwd *pwdst,
314 char *buf, size_t buflen, struct passwd **pwdstp);
315 struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
317 int (*nw_getpwuid_r)(struct nwrap_backend *b,
318 uid_t uid, struct passwd *pwdst,
319 char *buf, size_t buflen, struct passwd **pwdstp);
320 void (*nw_setpwent)(struct nwrap_backend *b);
321 struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
322 int (*nw_getpwent_r)(struct nwrap_backend *b,
323 struct passwd *pwdst, char *buf,
324 size_t buflen, struct passwd **pwdstp);
325 void (*nw_endpwent)(struct nwrap_backend *b);
326 int (*nw_initgroups)(struct nwrap_backend *b,
327 const char *user, gid_t group);
328 struct group * (*nw_getgrnam)(struct nwrap_backend *b,
330 int (*nw_getgrnam_r)(struct nwrap_backend *b,
331 const char *name, struct group *grdst,
332 char *buf, size_t buflen, struct group **grdstp);
333 struct group * (*nw_getgrgid)(struct nwrap_backend *b,
335 int (*nw_getgrgid_r)(struct nwrap_backend *b,
336 gid_t gid, struct group *grdst,
337 char *buf, size_t buflen, struct group **grdstp);
338 void (*nw_setgrent)(struct nwrap_backend *b);
339 struct group * (*nw_getgrent)(struct nwrap_backend *b);
340 int (*nw_getgrent_r)(struct nwrap_backend *b,
341 struct group *grdst, char *buf,
342 size_t buflen, struct group **grdstp);
343 void (*nw_endgrent)(struct nwrap_backend *b);
346 /* Public prototypes */
348 bool nss_wrapper_enabled(void);
349 bool nss_wrapper_shadow_enabled(void);
350 bool nss_wrapper_hosts_enabled(void);
352 /* prototypes for files backend */
355 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
357 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
358 const char *name, struct passwd *pwdst,
359 char *buf, size_t buflen, struct passwd **pwdstp);
360 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
362 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
363 uid_t uid, struct passwd *pwdst,
364 char *buf, size_t buflen, struct passwd **pwdstp);
365 static void nwrap_files_setpwent(struct nwrap_backend *b);
366 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
367 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
368 struct passwd *pwdst, char *buf,
369 size_t buflen, struct passwd **pwdstp);
370 static void nwrap_files_endpwent(struct nwrap_backend *b);
371 static int nwrap_files_initgroups(struct nwrap_backend *b,
372 const char *user, gid_t group);
373 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
375 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
376 const char *name, struct group *grdst,
377 char *buf, size_t buflen, struct group **grdstp);
378 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
380 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
381 gid_t gid, struct group *grdst,
382 char *buf, size_t buflen, struct group **grdstp);
383 static void nwrap_files_setgrent(struct nwrap_backend *b);
384 static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
385 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
386 struct group *grdst, char *buf,
387 size_t buflen, struct group **grdstp);
388 static void nwrap_files_endgrent(struct nwrap_backend *b);
390 /* prototypes for module backend */
392 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
393 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
394 struct passwd *pwdst, char *buf,
395 size_t buflen, struct passwd **pwdstp);
396 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
398 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
399 const char *name, struct passwd *pwdst,
400 char *buf, size_t buflen, struct passwd **pwdstp);
401 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
403 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
404 uid_t uid, struct passwd *pwdst,
405 char *buf, size_t buflen, struct passwd **pwdstp);
406 static void nwrap_module_setpwent(struct nwrap_backend *b);
407 static void nwrap_module_endpwent(struct nwrap_backend *b);
408 static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
409 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
410 struct group *grdst, char *buf,
411 size_t buflen, struct group **grdstp);
412 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
414 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
415 const char *name, struct group *grdst,
416 char *buf, size_t buflen, struct group **grdstp);
417 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
419 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
420 gid_t gid, struct group *grdst,
421 char *buf, size_t buflen, struct group **grdstp);
422 static void nwrap_module_setgrent(struct nwrap_backend *b);
423 static void nwrap_module_endgrent(struct nwrap_backend *b);
424 static int nwrap_module_initgroups(struct nwrap_backend *b,
425 const char *user, gid_t group);
427 struct nwrap_ops nwrap_files_ops = {
428 .nw_getpwnam = nwrap_files_getpwnam,
429 .nw_getpwnam_r = nwrap_files_getpwnam_r,
430 .nw_getpwuid = nwrap_files_getpwuid,
431 .nw_getpwuid_r = nwrap_files_getpwuid_r,
432 .nw_setpwent = nwrap_files_setpwent,
433 .nw_getpwent = nwrap_files_getpwent,
434 .nw_getpwent_r = nwrap_files_getpwent_r,
435 .nw_endpwent = nwrap_files_endpwent,
436 .nw_initgroups = nwrap_files_initgroups,
437 .nw_getgrnam = nwrap_files_getgrnam,
438 .nw_getgrnam_r = nwrap_files_getgrnam_r,
439 .nw_getgrgid = nwrap_files_getgrgid,
440 .nw_getgrgid_r = nwrap_files_getgrgid_r,
441 .nw_setgrent = nwrap_files_setgrent,
442 .nw_getgrent = nwrap_files_getgrent,
443 .nw_getgrent_r = nwrap_files_getgrent_r,
444 .nw_endgrent = nwrap_files_endgrent,
447 struct nwrap_ops nwrap_module_ops = {
448 .nw_getpwnam = nwrap_module_getpwnam,
449 .nw_getpwnam_r = nwrap_module_getpwnam_r,
450 .nw_getpwuid = nwrap_module_getpwuid,
451 .nw_getpwuid_r = nwrap_module_getpwuid_r,
452 .nw_setpwent = nwrap_module_setpwent,
453 .nw_getpwent = nwrap_module_getpwent,
454 .nw_getpwent_r = nwrap_module_getpwent_r,
455 .nw_endpwent = nwrap_module_endpwent,
456 .nw_initgroups = nwrap_module_initgroups,
457 .nw_getgrnam = nwrap_module_getgrnam,
458 .nw_getgrnam_r = nwrap_module_getgrnam_r,
459 .nw_getgrgid = nwrap_module_getgrgid,
460 .nw_getgrgid_r = nwrap_module_getgrgid_r,
461 .nw_setgrent = nwrap_module_setgrent,
462 .nw_getgrent = nwrap_module_getgrent,
463 .nw_getgrent_r = nwrap_module_getgrent_r,
464 .nw_endgrent = nwrap_module_endgrent,
471 struct nwrap_libc_fns *fns;
476 struct nwrap_backend *backends;
477 struct nwrap_libc *libc;
480 static struct nwrap_main *nwrap_main_global;
481 static struct nwrap_main __nwrap_main_global;
486 static int nwrap_convert_he_ai(const struct hostent *he,
488 const struct addrinfo *hints,
489 struct addrinfo **pai,
490 bool skip_canonname);
496 #define DEFAULT_VECTOR_CAPACITY 16
498 struct nwrap_vector {
504 /* Macro returns pointer to first element of vector->items array.
506 * nwrap_vector is used as a memory backend which take care of
507 * memory allocations and other stuff like memory growing.
508 * nwrap_vectors should not be considered as some abstract structures.
509 * On this level, vectors are more handy than direct realloc/malloc
512 * nwrap_vector->items is array inside nwrap_vector which can be
513 * directly pointed by libc structure assembled by cwrap itself.
517 * 1) struct hostent contains char **h_addr_list element.
518 * 2) nwrap_vector holds array of pointers to addresses.
519 * It's easier to use vector to store results of
522 * Now, pretend that cwrap assembled struct hostent and
523 * we need to set h_addr_list to point to nwrap_vector.
524 * Idea behind is to shield users from internal nwrap_vector
526 * (Yes, not fully - array terminated by NULL is needed because
527 * it's result expected by libc function caller.)
533 * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
534 * ... don't care about failed allocation now ...
536 * ... fill nwrap vector ...
539 * he.h_addr_list = nwrap_vector_head(vector);
542 #define nwrap_vector_head(vect) ((void *)((vect)->items))
544 #define nwrap_vector_foreach(item, vect, iter) \
545 for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
547 (item) = (vect).items[++iter])
549 static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
551 if (vector == NULL) {
555 /* count is initialized by ZERO_STRUCTP */
556 ZERO_STRUCTP(vector);
557 vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
558 if (vector->items == NULL) {
561 vector->capacity = DEFAULT_VECTOR_CAPACITY;
562 memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
567 static bool nwrap_vector_add_item(struct nwrap_vector *cont, void *const item)
569 assert (cont != NULL);
571 if (cont->items == NULL) {
572 nwrap_vector_init(cont);
575 if (cont->count == cont->capacity) {
576 /* Items array _MUST_ be NULL terminated because it's passed
577 * as result to caller which expect NULL terminated array from libc.
579 void **items = realloc(cont->items, sizeof(void *) * ((cont->capacity * 2) + 1));
585 /* Don't count ending NULL to capacity */
589 cont->items[cont->count] = item;
592 cont->items[cont->count] = NULL;
597 static bool nwrap_vector_merge(struct nwrap_vector *dst,
598 struct nwrap_vector *src)
600 void **dst_items = NULL;
603 if (src->count == 0) {
607 count = dst->count + src->count;
609 /* We don't need reallocation if we have enough capacity. */
610 if (src->count > (dst->capacity - dst->count)) {
611 dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
612 if (dst_items == NULL) {
615 dst->items = dst_items;
616 dst->capacity = count;
619 memcpy((void *)(((long *)dst->items) + dst->count),
621 src->count * sizeof(void *));
634 struct nwrap_vector lines;
636 bool (*parse_line)(struct nwrap_cache *, char *line);
637 void (*unload)(struct nwrap_cache *);
642 struct nwrap_cache *cache;
649 struct nwrap_cache __nwrap_cache_pw;
650 struct nwrap_pw nwrap_pw_global;
652 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
653 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
656 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
658 struct nwrap_cache *cache;
665 struct nwrap_cache __nwrap_cache_sp;
666 struct nwrap_sp nwrap_sp_global;
668 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
669 static void nwrap_sp_unload(struct nwrap_cache *nwrap);
670 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
674 struct nwrap_cache *cache;
681 struct nwrap_cache __nwrap_cache_gr;
682 struct nwrap_gr nwrap_gr_global;
685 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
686 static void nwrap_he_unload(struct nwrap_cache *nwrap);
688 struct nwrap_addrdata {
689 unsigned char host_addr[16]; /* IPv4 or IPv6 address */
692 static size_t max_hostents = 100;
694 struct nwrap_entdata {
695 struct nwrap_addrdata addr;
698 struct nwrap_vector nwrap_addrdata;
700 ssize_t aliases_count;
702 struct nwrap_entdata *ed_next;
703 struct nwrap_entdata *ed_tail;
707 struct nwrap_cache *cache;
709 struct nwrap_entdata *list;
710 struct nwrap_vector entdata;
716 static struct nwrap_cache __nwrap_cache_he;
717 static struct nwrap_he nwrap_he_global;
720 /*********************************************************
722 *********************************************************/
724 static void nwrap_init(void);
725 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
726 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
727 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
729 /*********************************************************
730 * NWRAP LIBC LOADER FUNCTIONS
731 *********************************************************/
740 static const char *nwrap_str_lib(enum nwrap_lib lib)
747 case NWRAP_LIBSOCKET:
751 /* Compiler would warn us about unhandled enum value if we get here */
756 static void *nwrap_load_lib_handle(enum nwrap_lib lib)
758 int flags = RTLD_LAZY;
763 flags |= RTLD_DEEPBIND;
769 handle = nwrap_main_global->libc->nsl_handle;
770 if (handle == NULL) {
771 for (i = 10; i >= 0; i--) {
772 char soname[256] = {0};
774 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
775 handle = dlopen(soname, flags);
776 if (handle != NULL) {
781 nwrap_main_global->libc->nsl_handle = handle;
786 case NWRAP_LIBSOCKET:
787 #ifdef HAVE_LIBSOCKET
788 handle = nwrap_main_global->libc->sock_handle;
789 if (handle == NULL) {
790 for (i = 10; i >= 0; i--) {
791 char soname[256] = {0};
793 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
794 handle = dlopen(soname, flags);
795 if (handle != NULL) {
800 nwrap_main_global->libc->sock_handle = handle;
806 handle = nwrap_main_global->libc->handle;
807 if (handle == NULL) {
808 for (i = 10; i >= 0; i--) {
809 char soname[256] = {0};
811 snprintf(soname, sizeof(soname), "libc.so.%d", i);
812 handle = dlopen(soname, flags);
813 if (handle != NULL) {
818 nwrap_main_global->libc->handle = handle;
823 if (handle == NULL) {
825 handle = nwrap_main_global->libc->handle
826 = nwrap_main_global->libc->sock_handle
827 = nwrap_main_global->libc->nsl_handle
830 NWRAP_LOG(NWRAP_LOG_ERROR,
831 "Failed to dlopen library: %s\n",
840 static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
847 handle = nwrap_load_lib_handle(lib);
849 func = dlsym(handle, fn_name);
851 NWRAP_LOG(NWRAP_LOG_ERROR,
852 "Failed to find %s: %s\n",
857 NWRAP_LOG(NWRAP_LOG_TRACE,
859 fn_name, nwrap_str_lib(lib));
863 #define nwrap_load_lib_function(lib, fn_name) \
864 if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
865 *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
866 _nwrap_load_lib_function(lib, #fn_name); \
869 /* INTERNAL HELPER FUNCTIONS */
870 static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
873 for (p = 0; p < nwrap->lines.count; p++) {
874 /* Maybe some vectors were merged ... */
875 SAFE_FREE(nwrap->lines.items[p]);
877 SAFE_FREE(nwrap->lines.items);
878 nwrap->lines.count = 0;
884 * Functions expeciall from libc need to be loaded individually, you can't load
885 * all at once or gdb will segfault at startup. The same applies to valgrind and
886 * has probably something todo with with the linker.
887 * So we need load each function at the point it is called the first time.
889 static struct passwd *libc_getpwnam(const char *name)
891 nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
893 return nwrap_main_global->libc->fns->_libc_getpwnam(name);
896 #ifdef HAVE_GETPWNAM_R
897 static int libc_getpwnam_r(const char *name,
901 struct passwd **result)
903 #ifdef HAVE___POSIX_GETPWNAM_R
904 if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
905 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
906 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
909 nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
912 return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
920 static struct passwd *libc_getpwuid(uid_t uid)
922 nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
924 return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
927 #ifdef HAVE_GETPWUID_R
928 static int libc_getpwuid_r(uid_t uid,
932 struct passwd **result)
934 #ifdef HAVE___POSIX_GETPWUID_R
935 if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
936 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
937 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
940 nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
943 return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
951 static inline void str_tolower(char *dst, char *src)
953 register char *src_tmp = src;
954 register char *dst_tmp = dst;
956 while (*src_tmp != '\0') {
957 *dst_tmp = tolower(*src_tmp);
963 static bool str_tolower_copy(char **dst_name, const char *const src_name)
967 if ((dst_name == NULL) || (src_name == NULL)) {
971 h_name_lower = strdup(src_name);
972 if (h_name_lower == NULL) {
973 NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
977 str_tolower(h_name_lower, h_name_lower);
978 *dst_name = h_name_lower;
982 static void libc_setpwent(void)
984 nwrap_load_lib_function(NWRAP_LIBC, setpwent);
986 nwrap_main_global->libc->fns->_libc_setpwent();
989 static struct passwd *libc_getpwent(void)
991 nwrap_load_lib_function(NWRAP_LIBC, getpwent);
993 return nwrap_main_global->libc->fns->_libc_getpwent();
996 #ifdef HAVE_SOLARIS_GETPWENT_R
997 static struct passwd *libc_getpwent_r(struct passwd *pwdst,
1001 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
1003 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
1007 #else /* HAVE_SOLARIS_GETPWENT_R */
1008 static int libc_getpwent_r(struct passwd *pwdst,
1011 struct passwd **pwdstp)
1013 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
1015 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
1020 #endif /* HAVE_SOLARIS_GETPWENT_R */
1022 static void libc_endpwent(void)
1024 nwrap_load_lib_function(NWRAP_LIBC, endpwent);
1026 nwrap_main_global->libc->fns->_libc_endpwent();
1029 static int libc_initgroups(const char *user, gid_t gid)
1031 nwrap_load_lib_function(NWRAP_LIBC, initgroups);
1033 return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
1036 static struct group *libc_getgrnam(const char *name)
1038 nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
1040 return nwrap_main_global->libc->fns->_libc_getgrnam(name);
1043 #ifdef HAVE_GETGRNAM_R
1044 static int libc_getgrnam_r(const char *name,
1048 struct group **result)
1050 #ifdef HAVE___POSIX_GETGRNAM_R
1051 if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
1052 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
1053 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
1056 nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
1059 return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
1067 static struct group *libc_getgrgid(gid_t gid)
1069 nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
1071 return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
1074 #ifdef HAVE_GETGRGID_R
1075 static int libc_getgrgid_r(gid_t gid,
1079 struct group **result)
1081 #ifdef HAVE___POSIX_GETGRGID_R
1082 if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
1083 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
1084 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
1087 nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
1090 return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
1098 static void libc_setgrent(void)
1100 nwrap_load_lib_function(NWRAP_LIBC, setgrent);
1102 nwrap_main_global->libc->fns->_libc_setgrent();
1105 static struct group *libc_getgrent(void)
1107 nwrap_load_lib_function(NWRAP_LIBC, getgrent);
1109 return nwrap_main_global->libc->fns->_libc_getgrent();
1112 #ifdef HAVE_GETGRENT_R
1113 #ifdef HAVE_SOLARIS_GETGRENT_R
1114 static struct group *libc_getgrent_r(struct group *group,
1118 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
1120 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
1124 #else /* !HAVE_SOLARIS_GETGRENT_R */
1125 static int libc_getgrent_r(struct group *group,
1128 struct group **result)
1130 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
1132 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
1137 #endif /* HAVE_SOLARIS_GETGRENT_R */
1138 #endif /* HAVE_GETGRENT_R */
1140 static void libc_endgrent(void)
1142 nwrap_load_lib_function(NWRAP_LIBC, endgrent);
1144 nwrap_main_global->libc->fns->_libc_endgrent();
1147 #ifdef HAVE_GETGROUPLIST
1148 static int libc_getgrouplist(const char *user,
1153 nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
1155 return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
1162 static void libc_sethostent(int stayopen)
1164 nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
1166 nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
1169 static struct hostent *libc_gethostent(void)
1171 nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
1173 return nwrap_main_global->libc->fns->_libc_gethostent();
1176 static void libc_endhostent(void)
1178 nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
1180 nwrap_main_global->libc->fns->_libc_endhostent();
1183 static struct hostent *libc_gethostbyname(const char *name)
1185 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
1187 return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
1190 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1191 static struct hostent *libc_gethostbyname2(const char *name, int af)
1193 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
1195 return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
1199 static struct hostent *libc_gethostbyaddr(const void *addr,
1203 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
1205 return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
1210 static int libc_gethostname(char *name, size_t len)
1212 nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
1214 return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
1217 #ifdef HAVE_GETHOSTBYNAME_R
1218 static int libc_gethostbyname_r(const char *name,
1219 struct hostent *ret,
1222 struct hostent **result,
1225 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
1227 return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
1236 #ifdef HAVE_GETHOSTBYADDR_R
1237 static int libc_gethostbyaddr_r(const void *addr,
1240 struct hostent *ret,
1243 struct hostent **result,
1246 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
1248 return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
1259 static int libc_getaddrinfo(const char *node,
1260 const char *service,
1261 const struct addrinfo *hints,
1262 struct addrinfo **res)
1264 nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
1266 return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
1272 static int libc_getnameinfo(const struct sockaddr *sa,
1280 nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
1282 return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
1291 /*********************************************************
1292 * NWRAP NSS MODULE LOADER FUNCTIONS
1293 *********************************************************/
1295 static void *nwrap_load_module_fn(struct nwrap_backend *b,
1296 const char *fn_name)
1301 if (!b->so_handle) {
1302 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
1306 if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
1307 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1311 res = dlsym(b->so_handle, s);
1313 NWRAP_LOG(NWRAP_LOG_ERROR,
1314 "Cannot find function %s in %s",
1321 static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b)
1323 struct nwrap_module_nss_fns *fns;
1325 if (!b->so_handle) {
1329 fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns));
1334 *(void **)(&fns->_nss_getpwnam_r) =
1335 nwrap_load_module_fn(b, "getpwnam_r");
1336 *(void **)(&fns->_nss_getpwuid_r) =
1337 nwrap_load_module_fn(b, "getpwuid_r");
1338 *(void **)(&fns->_nss_setpwent) =
1339 nwrap_load_module_fn(b, "setpwent");
1340 *(void **)(&fns->_nss_getpwent_r) =
1341 nwrap_load_module_fn(b, "getpwent_r");
1342 *(void **)(&fns->_nss_endpwent) =
1343 nwrap_load_module_fn(b, "endpwent");
1344 *(void **)(&fns->_nss_initgroups) =
1345 nwrap_load_module_fn(b, "initgroups_dyn");
1346 *(void **)(&fns->_nss_getgrnam_r) =
1347 nwrap_load_module_fn(b, "getgrnam_r");
1348 *(void **)(&fns->_nss_getgrgid_r)=
1349 nwrap_load_module_fn(b, "getgrgid_r");
1350 *(void **)(&fns->_nss_setgrent) =
1351 nwrap_load_module_fn(b, "setgrent");
1352 *(void **)(&fns->_nss_getgrent_r) =
1353 nwrap_load_module_fn(b, "getgrent_r");
1354 *(void **)(&fns->_nss_endgrent) =
1355 nwrap_load_module_fn(b, "endgrent");
1360 static void *nwrap_load_module(const char *so_path)
1364 if (!so_path || !strlen(so_path)) {
1368 h = dlopen(so_path, RTLD_LAZY);
1370 NWRAP_LOG(NWRAP_LOG_ERROR,
1371 "Cannot open shared library %s",
1379 static bool nwrap_module_init(const char *name,
1380 struct nwrap_ops *ops,
1381 const char *so_path,
1383 struct nwrap_backend **backends)
1385 struct nwrap_backend *b;
1387 *backends = (struct nwrap_backend *)realloc(*backends,
1388 sizeof(struct nwrap_backend) * ((*num_backends) + 1));
1390 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1394 b = &((*backends)[*num_backends]);
1398 b->so_path = so_path;
1400 if (so_path != NULL) {
1401 b->so_handle = nwrap_load_module(so_path);
1402 b->fns = nwrap_load_module_fns(b);
1403 if (b->fns == NULL) {
1407 b->so_handle = NULL;
1416 static void nwrap_libc_init(struct nwrap_main *r)
1418 r->libc = malloc(sizeof(struct nwrap_libc));
1419 if (r->libc == NULL) {
1420 printf("Failed to allocate memory for libc");
1423 ZERO_STRUCTP(r->libc);
1425 r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
1426 if (r->libc->fns == NULL) {
1427 printf("Failed to allocate memory for libc functions");
1430 ZERO_STRUCTP(r->libc->fns);
1433 static void nwrap_backend_init(struct nwrap_main *r)
1435 const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
1436 const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1438 r->num_backends = 0;
1441 if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
1444 NWRAP_LOG(NWRAP_LOG_ERROR,
1445 "Failed to initialize 'files' backend");
1449 if (module_so_path != NULL &&
1450 module_so_path[0] != '\0' &&
1451 module_fn_name != NULL &&
1452 module_fn_name[0] != '\0') {
1453 if (!nwrap_module_init(module_fn_name,
1458 NWRAP_LOG(NWRAP_LOG_ERROR,
1459 "Failed to initialize '%s' backend",
1466 static void nwrap_init(void)
1468 static bool initialized;
1471 size_t max_hostents_tmp;
1473 if (initialized) return;
1476 env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
1478 max_hostents_tmp = (size_t)strtol(env, &endptr, 10);
1479 if (((env != '\0') && (endptr == '\0')) ||
1480 (max_hostents_tmp == 0)) {
1481 NWRAP_LOG(NWRAP_LOG_DEBUG,
1482 "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
1483 "value or value is too small. "
1484 "Using default value: %lu.",
1487 max_hostents = max_hostents_tmp;
1490 /* Initialize hash table */
1491 NWRAP_LOG(NWRAP_LOG_DEBUG,
1492 "Initializing hash table of size %lu items.", max_hostents);
1493 if (hcreate(max_hostents) == 0) {
1494 NWRAP_LOG(NWRAP_LOG_ERROR,
1495 "Failed to initialize hash table");
1499 nwrap_main_global = &__nwrap_main_global;
1501 nwrap_libc_init(nwrap_main_global);
1503 nwrap_backend_init(nwrap_main_global);
1506 nwrap_pw_global.cache = &__nwrap_cache_pw;
1508 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
1509 nwrap_pw_global.cache->fp = NULL;
1510 nwrap_pw_global.cache->fd = -1;
1511 nwrap_pw_global.cache->private_data = &nwrap_pw_global;
1512 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
1513 nwrap_pw_global.cache->unload = nwrap_pw_unload;
1516 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1517 nwrap_sp_global.cache = &__nwrap_cache_sp;
1519 nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
1520 nwrap_sp_global.cache->fp = NULL;
1521 nwrap_sp_global.cache->fd = -1;
1522 nwrap_sp_global.cache->private_data = &nwrap_sp_global;
1523 nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
1524 nwrap_sp_global.cache->unload = nwrap_sp_unload;
1525 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1528 nwrap_gr_global.cache = &__nwrap_cache_gr;
1530 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
1531 nwrap_gr_global.cache->fp = NULL;
1532 nwrap_gr_global.cache->fd = -1;
1533 nwrap_gr_global.cache->private_data = &nwrap_gr_global;
1534 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
1535 nwrap_gr_global.cache->unload = nwrap_gr_unload;
1538 nwrap_he_global.cache = &__nwrap_cache_he;
1540 nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
1541 nwrap_he_global.cache->fp = NULL;
1542 nwrap_he_global.cache->fd = -1;
1543 nwrap_he_global.cache->private_data = &nwrap_he_global;
1544 nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
1545 nwrap_he_global.cache->unload = nwrap_he_unload;
1548 bool nss_wrapper_enabled(void)
1552 if (nwrap_pw_global.cache->path == NULL ||
1553 nwrap_pw_global.cache->path[0] == '\0') {
1556 if (nwrap_gr_global.cache->path == NULL ||
1557 nwrap_gr_global.cache->path[0] == '\0') {
1564 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1565 bool nss_wrapper_shadow_enabled(void)
1569 if (nwrap_sp_global.cache->path == NULL ||
1570 nwrap_sp_global.cache->path[0] == '\0') {
1576 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1578 bool nss_wrapper_hosts_enabled(void)
1582 if (nwrap_he_global.cache->path == NULL ||
1583 nwrap_he_global.cache->path[0] == '\0') {
1590 static bool nwrap_hostname_enabled(void)
1594 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
1601 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
1605 /* Unused but getline needs it */
1609 if (nwrap->st.st_size == 0) {
1610 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
1614 /* Support for 32-bit system I guess */
1615 if (nwrap->st.st_size > INT32_MAX) {
1616 NWRAP_LOG(NWRAP_LOG_ERROR,
1617 "Size[%u] larger than INT32_MAX",
1618 (unsigned)nwrap->st.st_size);
1625 n = getline(&line, &len, nwrap->fp);
1627 if (feof(nwrap->fp)) {
1631 NWRAP_LOG(NWRAP_LOG_ERROR,
1632 "Unable to read line from file: %s",
1637 if (line[n - 1] == '\n') {
1641 if (line[0] == '\0') {
1646 ok = nwrap->parse_line(nwrap, line);
1648 NWRAP_LOG(NWRAP_LOG_ERROR,
1649 "Unable to parse line file: %s",
1655 /* Line is parsed without issues so add it to list */
1656 ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
1658 NWRAP_LOG(NWRAP_LOG_ERROR,
1659 "Unable to add line to vector");
1663 /* This forces getline to allocate new memory for line. */
1665 } while (!feof(nwrap->fp));
1670 static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
1672 nwrap->unload(nwrap);
1674 nwrap_lines_unload(nwrap);
1677 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
1682 bool retried = false;
1684 assert(nwrap != NULL);
1687 if (nwrap->fd < 0) {
1688 nwrap->fp = fopen(nwrap->path, "re");
1689 if (nwrap->fp == NULL) {
1691 NWRAP_LOG(NWRAP_LOG_ERROR,
1692 "Unable to open '%s' readonly %d:%s",
1693 nwrap->path, nwrap->fd,
1698 nwrap->fd = fileno(nwrap->fp);
1699 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
1702 ret = fstat(nwrap->fd, &st);
1704 NWRAP_LOG(NWRAP_LOG_ERROR,
1705 "fstat(%s) - %d:%s",
1715 if (retried == false && st.st_nlink == 0) {
1716 /* maybe someone has replaced the file... */
1717 NWRAP_LOG(NWRAP_LOG_TRACE,
1718 "st_nlink == 0, reopen %s",
1721 memset(&nwrap->st, 0, sizeof(nwrap->st));
1728 if (st.st_mtime == nwrap->st.st_mtime) {
1729 NWRAP_LOG(NWRAP_LOG_TRACE,
1730 "st_mtime[%u] hasn't changed, skip reload",
1731 (unsigned)st.st_mtime);
1735 NWRAP_LOG(NWRAP_LOG_TRACE,
1736 "st_mtime has changed [%u] => [%u], start reload",
1737 (unsigned)st.st_mtime,
1738 (unsigned)nwrap->st.st_mtime);
1742 nwrap_files_cache_unload(nwrap);
1744 ok = nwrap_parse_file(nwrap);
1746 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
1747 nwrap_files_cache_unload(nwrap);
1750 NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
1754 * the caller has to call nwrap_unload() on failure
1756 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
1758 struct nwrap_pw *nwrap_pw;
1765 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1767 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
1768 pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
1770 NWRAP_LOG(NWRAP_LOG_ERROR,
1771 "realloc(%u) failed",
1772 (unsigned)list_size);
1775 nwrap_pw->list = pw;
1777 pw = &nwrap_pw->list[nwrap_pw->num];
1784 NWRAP_LOG(NWRAP_LOG_ERROR,
1785 "Invalid line[%s]: '%s'",
1795 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
1800 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1808 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
1813 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1819 pw->pw_uid = (uid_t)strtoul(c, &e, 10);
1821 NWRAP_LOG(NWRAP_LOG_ERROR,
1822 "Invalid line[%s]: '%s' - %s",
1823 line, c, strerror(errno));
1827 NWRAP_LOG(NWRAP_LOG_ERROR,
1828 "Invalid line[%s]: '%s' - %s",
1829 line, c, strerror(errno));
1833 NWRAP_LOG(NWRAP_LOG_ERROR,
1834 "Invalid line[%s]: '%s' - %s",
1835 line, c, strerror(errno));
1840 NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
1845 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1851 pw->pw_gid = (gid_t)strtoul(c, &e, 10);
1853 NWRAP_LOG(NWRAP_LOG_ERROR,
1854 "Invalid line[%s]: '%s' - %s",
1855 line, c, strerror(errno));
1859 NWRAP_LOG(NWRAP_LOG_ERROR,
1860 "Invalid line[%s]: '%s' - %s",
1861 line, c, strerror(errno));
1865 NWRAP_LOG(NWRAP_LOG_ERROR,
1866 "Invalid line[%s]: '%s' - %s",
1867 line, c, strerror(errno));
1872 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
1877 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
1885 NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
1890 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
1898 NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
1902 NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
1904 NWRAP_LOG(NWRAP_LOG_DEBUG,
1905 "Added user[%s:%s:%u:%u:%s:%s:%s]",
1906 pw->pw_name, pw->pw_passwd,
1907 pw->pw_uid, pw->pw_gid,
1908 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
1914 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
1916 struct nwrap_pw *nwrap_pw;
1917 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1919 SAFE_FREE(nwrap_pw->list);
1924 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
1925 char *buf, size_t buflen, struct passwd **dstp)
1931 first = src->pw_name;
1933 last = src->pw_shell;
1934 while (*last) last++;
1936 ofs = PTR_DIFF(last + 1, first);
1938 if (ofs > (off_t) buflen) {
1942 memcpy(buf, first, ofs);
1944 ofs = PTR_DIFF(src->pw_name, first);
1945 dst->pw_name = buf + ofs;
1946 ofs = PTR_DIFF(src->pw_passwd, first);
1947 dst->pw_passwd = buf + ofs;
1948 dst->pw_uid = src->pw_uid;
1949 dst->pw_gid = src->pw_gid;
1950 ofs = PTR_DIFF(src->pw_gecos, first);
1951 dst->pw_gecos = buf + ofs;
1952 ofs = PTR_DIFF(src->pw_dir, first);
1953 dst->pw_dir = buf + ofs;
1954 ofs = PTR_DIFF(src->pw_shell, first);
1955 dst->pw_shell = buf + ofs;
1964 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1965 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
1967 struct nwrap_sp *nwrap_sp;
1974 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
1976 list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
1977 sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
1979 NWRAP_LOG(NWRAP_LOG_ERROR,
1980 "realloc(%u) failed",
1981 (unsigned)list_size);
1984 nwrap_sp->list = sp;
1986 sp = &nwrap_sp->list[nwrap_sp->num];
1993 NWRAP_LOG(NWRAP_LOG_ERROR,
1994 "name -- Invalid line[%s]: '%s'",
2004 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
2009 NWRAP_LOG(NWRAP_LOG_ERROR,
2010 "pwd -- Invalid line[%s]: '%s'",
2027 NWRAP_LOG(NWRAP_LOG_ERROR,
2028 "lstchg -- Invalid line[%s]: '%s'",
2035 sp->sp_lstchg = strtol(c, &e, 10);
2037 NWRAP_LOG(NWRAP_LOG_ERROR,
2038 "lstchg -- Invalid line[%s]: '%s' - %s",
2039 line, c, strerror(errno));
2043 NWRAP_LOG(NWRAP_LOG_ERROR,
2044 "lstchg -- Invalid line[%s]: '%s' - %s",
2045 line, c, strerror(errno));
2049 NWRAP_LOG(NWRAP_LOG_ERROR,
2050 "lstchg -- Invalid line[%s]: '%s' - %s",
2051 line, c, strerror(errno));
2064 NWRAP_LOG(NWRAP_LOG_ERROR,
2065 "min -- Invalid line[%s]: '%s'",
2072 sp->sp_min = strtol(c, &e, 10);
2074 NWRAP_LOG(NWRAP_LOG_ERROR,
2075 "min -- Invalid line[%s]: '%s' - %s",
2076 line, c, strerror(errno));
2080 NWRAP_LOG(NWRAP_LOG_ERROR,
2081 "min -- Invalid line[%s]: '%s' - %s",
2082 line, c, strerror(errno));
2086 NWRAP_LOG(NWRAP_LOG_ERROR,
2087 "min -- Invalid line[%s]: '%s' - %s",
2088 line, c, strerror(errno));
2101 NWRAP_LOG(NWRAP_LOG_ERROR,
2102 "max -- Invalid line[%s]: '%s'",
2109 sp->sp_max = strtol(c, &e, 10);
2111 NWRAP_LOG(NWRAP_LOG_ERROR,
2112 "max -- Invalid line[%s]: '%s' - %s",
2113 line, c, strerror(errno));
2117 NWRAP_LOG(NWRAP_LOG_ERROR,
2118 "max -- Invalid line[%s]: '%s' - %s",
2119 line, c, strerror(errno));
2123 NWRAP_LOG(NWRAP_LOG_ERROR,
2124 "max -- Invalid line[%s]: '%s' - %s",
2125 line, c, strerror(errno));
2138 NWRAP_LOG(NWRAP_LOG_ERROR,
2139 "warn -- Invalid line[%s]: '%s'",
2146 sp->sp_warn = strtol(c, &e, 10);
2148 NWRAP_LOG(NWRAP_LOG_ERROR,
2149 "warn -- Invalid line[%s]: '%s' - %s",
2150 line, c, strerror(errno));
2154 NWRAP_LOG(NWRAP_LOG_ERROR,
2155 "warn -- Invalid line[%s]: '%s' - %s",
2156 line, c, strerror(errno));
2160 NWRAP_LOG(NWRAP_LOG_ERROR,
2161 "warn -- Invalid line[%s]: '%s' - %s",
2162 line, c, strerror(errno));
2175 NWRAP_LOG(NWRAP_LOG_ERROR,
2176 "inact -- Invalid line[%s]: '%s'",
2183 sp->sp_inact = strtol(c, &e, 10);
2185 NWRAP_LOG(NWRAP_LOG_ERROR,
2186 "inact -- Invalid line[%s]: '%s' - %s",
2187 line, c, strerror(errno));
2191 NWRAP_LOG(NWRAP_LOG_ERROR,
2192 "inact -- Invalid line[%s]: '%s' - %s",
2193 line, c, strerror(errno));
2197 NWRAP_LOG(NWRAP_LOG_ERROR,
2198 "inact -- Invalid line[%s]: '%s' - %s",
2199 line, c, strerror(errno));
2212 NWRAP_LOG(NWRAP_LOG_ERROR,
2213 "expire -- Invalid line[%s]: '%s'",
2220 sp->sp_expire = strtol(c, &e, 10);
2222 NWRAP_LOG(NWRAP_LOG_ERROR,
2223 "expire -- Invalid line[%s]: '%s' - %s",
2224 line, c, strerror(errno));
2228 NWRAP_LOG(NWRAP_LOG_ERROR,
2229 "expire -- Invalid line[%s]: '%s' - %s",
2230 line, c, strerror(errno));
2234 NWRAP_LOG(NWRAP_LOG_ERROR,
2235 "expire -- Invalid line[%s]: '%s' - %s",
2236 line, c, strerror(errno));
2246 static void nwrap_sp_unload(struct nwrap_cache *nwrap)
2248 struct nwrap_sp *nwrap_sp;
2249 nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
2251 SAFE_FREE(nwrap_sp->list);
2255 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2258 * the caller has to call nwrap_unload() on failure
2260 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
2262 struct nwrap_gr *nwrap_gr;
2270 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2272 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
2273 gr = (struct group *)realloc(nwrap_gr->list, list_size);
2275 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
2278 nwrap_gr->list = gr;
2280 gr = &nwrap_gr->list[nwrap_gr->num];
2287 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2295 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
2300 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2308 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
2313 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
2319 gr->gr_gid = (gid_t)strtoul(c, &e, 10);
2321 NWRAP_LOG(NWRAP_LOG_ERROR,
2322 "Invalid line[%s]: '%s' - %s",
2323 line, c, strerror(errno));
2327 NWRAP_LOG(NWRAP_LOG_ERROR,
2328 "Invalid line[%s]: '%s' - %s",
2329 line, c, strerror(errno));
2333 NWRAP_LOG(NWRAP_LOG_ERROR,
2334 "Invalid line[%s]: '%s' - %s",
2335 line, c, strerror(errno));
2340 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
2343 gr->gr_mem = (char **)malloc(sizeof(char *));
2345 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
2348 gr->gr_mem[0] = NULL;
2350 for(nummem=0; p; nummem++) {
2360 if (strlen(c) == 0) {
2364 m_size = sizeof(char *) * (nummem+2);
2365 m = (char **)realloc(gr->gr_mem, m_size);
2367 NWRAP_LOG(NWRAP_LOG_ERROR,
2368 "realloc(%zd) failed",
2373 gr->gr_mem[nummem] = c;
2374 gr->gr_mem[nummem+1] = NULL;
2376 NWRAP_LOG(NWRAP_LOG_TRACE,
2378 nummem, gr->gr_mem[nummem]);
2381 NWRAP_LOG(NWRAP_LOG_DEBUG,
2382 "Added group[%s:%s:%u:] with %u members",
2383 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
2389 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
2392 struct nwrap_gr *nwrap_gr;
2393 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
2395 if (nwrap_gr->list) {
2396 for (i=0; i < nwrap_gr->num; i++) {
2397 SAFE_FREE(nwrap_gr->list[i].gr_mem);
2399 SAFE_FREE(nwrap_gr->list);
2406 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
2407 char *buf, size_t buflen, struct group **dstp)
2417 first = src->gr_name;
2419 lastm = src->gr_mem;
2426 last = src->gr_passwd;
2428 while (*last) last++;
2430 ofsb = PTR_DIFF(last + 1, first);
2431 ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
2433 if ((ofsb + ofsm) > (off_t) buflen) {
2437 memcpy(buf, first, ofsb);
2438 memcpy(buf + ofsb, src->gr_mem, ofsm);
2440 ofs = PTR_DIFF(src->gr_name, first);
2441 dst->gr_name = buf + ofs;
2442 ofs = PTR_DIFF(src->gr_passwd, first);
2443 dst->gr_passwd = buf + ofs;
2444 dst->gr_gid = src->gr_gid;
2446 dst->gr_mem = (char **)(buf + ofsb);
2447 for (i=0; src->gr_mem[i]; i++) {
2448 ofs = PTR_DIFF(src->gr_mem[i], first);
2449 dst->gr_mem[i] = buf + ofs;
2459 static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
2467 p = hsearch(e, ENTER);
2469 NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full");
2477 static bool nwrap_add_hname_add_new(char *const h_name,
2478 struct nwrap_entdata *const ed)
2480 /* No element found.. inventarize new item */
2485 e.data = (void *)ed;
2489 p = hsearch(e, ENTER);
2491 NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full!");
2498 static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
2499 struct nwrap_entdata *const ed_dst)
2501 if (ed_dst->ed_tail != NULL) {
2502 ed_dst->ed_tail->ed_next = ed;
2503 if (ed_dst->ed_tail != ed) {
2504 ed_dst->ed_tail = ed;
2508 ed_dst->ed_tail = ed;
2512 static bool nwrap_add_hname_alias(const char *const h_name_a,
2513 struct nwrap_entdata *const ed)
2515 /* One of argument 'h_hame_a' are "optional" */
2516 char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
2520 /* Maybe it's little bit late ... */
2522 assert(h_name != NULL);
2526 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
2527 p = hsearch(e, FIND);
2529 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
2530 /* Just add alias and don't mess with metadata */
2531 nwrap_add_hname_add_new(h_name, ed);
2533 /* Element found. Add them to end of list */
2534 struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
2536 assert(p->data != NULL);
2537 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
2538 nwrap_add_hname_add_to_existing(ed, ed_dst);
2544 static bool nwrap_add_hname(const char *const h_name_a,
2545 struct nwrap_entdata *const ed)
2547 /* One of argument 'h_hame_a' are "optional" */
2548 char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
2554 /* Maybe it's little bit late ... */
2556 assert(h_name != NULL);
2560 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
2561 p = hsearch(e, FIND);
2563 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
2564 /* Just add alias and don't mess with metadata */
2565 nwrap_add_hname_add_new(h_name, ed);
2567 if (ed->ed_tail == NULL) {
2571 /* Element found. Add them to end of list */
2572 struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
2574 assert(p->data != NULL);
2575 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
2576 nwrap_add_hname_add_to_existing(ed, ed_dst);
2579 /* Return true when list of aliases is empty */
2580 if (ed->ht.h_aliases == NULL) {
2584 /* Itemize aliases */
2585 for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
2586 h_name_alias = ed->ht.h_aliases[i];
2587 assert(h_name_alias != NULL);
2589 NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
2591 if (!nwrap_add_hname_alias(h_name_alias, ed)) {
2592 NWRAP_LOG(NWRAP_LOG_DEBUG,
2593 "Unable to add alias: %s", h_name_alias);
2600 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
2602 struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
2603 bool do_aliases = true;
2604 ssize_t aliases_count = 0;
2611 struct nwrap_entdata *ed = (struct nwrap_entdata *)
2612 malloc(sizeof(struct nwrap_entdata));
2614 NWRAP_LOG(NWRAP_LOG_ERROR,
2615 "Unable to allocate memory for nwrap_entdata");
2626 /* Walk to first char */
2627 for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
2629 NWRAP_LOG(NWRAP_LOG_ERROR,
2630 "Invalid line[%s]: '%s'",
2637 for (i = p; !isspace((int)*p); p++) {
2639 NWRAP_LOG(NWRAP_LOG_ERROR,
2640 "Invalid line[%s]: '%s'",
2649 if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
2650 ed->ht.h_addrtype = AF_INET;
2651 ed->ht.h_length = 4;
2653 } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
2654 ed->ht.h_addrtype = AF_INET6;
2655 ed->ht.h_length = 16;
2658 NWRAP_LOG(NWRAP_LOG_ERROR,
2659 "Invalid line[%s]: '%s'",
2667 nwrap_vector_add_item(&(ed->nwrap_addrdata),
2668 (void *const)ed->addr.host_addr);
2669 ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
2677 /* Walk to first char */
2678 for (n = p; *p != '_' && !isalnum((int) *p); p++) {
2680 NWRAP_LOG(NWRAP_LOG_ERROR,
2681 "Invalid line[%s]: '%s'",
2689 for (n = p; !isspace((int)*p); p++) {
2698 /* Convert to lowercase. This operate on same memory region */
2702 /* glib's getent always dereferences he->h_aliases */
2703 ed->ht.h_aliases = malloc(sizeof(char *));
2704 if (ed->ht.h_aliases == NULL) {
2708 ed->ht.h_aliases[0] = NULL;
2713 while (do_aliases) {
2719 /* Walk to first char */
2720 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
2726 /* Only trailing spaces are left */
2731 for (a = p; !isspace((int)*p); p++) {
2740 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
2741 if (aliases == NULL) {
2745 ed->ht.h_aliases = aliases;
2748 aliases[aliases_count] = a;
2749 aliases[aliases_count + 1] = NULL;
2754 nwrap_vector_add_item(&(nwrap_he->entdata), (void *const)ed);
2756 ed->aliases_count = aliases_count;
2757 /* Inventarize item */
2758 nwrap_add_hname(NULL, ed);
2759 nwrap_add_ai(ip, ed);
2765 static void nwrap_he_unload(struct nwrap_cache *nwrap)
2767 struct nwrap_he *nwrap_he =
2768 (struct nwrap_he *)nwrap->private_data;
2769 struct nwrap_entdata *ed;
2772 nwrap_vector_foreach (ed, nwrap_he->entdata, i)
2774 SAFE_FREE(ed->ht.h_aliases);
2777 SAFE_FREE(nwrap_he->entdata.items);
2778 nwrap_he->entdata.count = nwrap_he->entdata.capacity = 0;
2785 /* user functions */
2786 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
2791 (void) b; /* unused */
2793 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
2795 nwrap_files_cache_reload(nwrap_pw_global.cache);
2797 for (i=0; i<nwrap_pw_global.num; i++) {
2798 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
2799 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
2800 return &nwrap_pw_global.list[i];
2802 NWRAP_LOG(NWRAP_LOG_DEBUG,
2803 "user[%s] does not match [%s]",
2805 nwrap_pw_global.list[i].pw_name);
2808 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
2814 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
2815 const char *name, struct passwd *pwdst,
2816 char *buf, size_t buflen, struct passwd **pwdstp)
2820 pw = nwrap_files_getpwnam(b, name);
2828 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2831 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
2836 (void) b; /* unused */
2838 nwrap_files_cache_reload(nwrap_pw_global.cache);
2840 for (i=0; i<nwrap_pw_global.num; i++) {
2841 if (nwrap_pw_global.list[i].pw_uid == uid) {
2842 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
2843 return &nwrap_pw_global.list[i];
2845 NWRAP_LOG(NWRAP_LOG_DEBUG,
2846 "uid[%u] does not match [%u]",
2848 nwrap_pw_global.list[i].pw_uid);
2851 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
2857 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
2858 uid_t uid, struct passwd *pwdst,
2859 char *buf, size_t buflen, struct passwd **pwdstp)
2863 pw = nwrap_files_getpwuid(b, uid);
2871 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2874 /* user enum functions */
2875 static void nwrap_files_setpwent(struct nwrap_backend *b)
2877 (void) b; /* unused */
2879 nwrap_pw_global.idx = 0;
2882 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
2886 (void) b; /* unused */
2888 if (nwrap_pw_global.idx == 0) {
2889 nwrap_files_cache_reload(nwrap_pw_global.cache);
2892 if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
2897 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
2899 NWRAP_LOG(NWRAP_LOG_DEBUG,
2900 "return user[%s] uid[%u]",
2901 pw->pw_name, pw->pw_uid);
2906 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
2907 struct passwd *pwdst, char *buf,
2908 size_t buflen, struct passwd **pwdstp)
2912 pw = nwrap_files_getpwent(b);
2920 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2923 static void nwrap_files_endpwent(struct nwrap_backend *b)
2925 (void) b; /* unused */
2927 nwrap_pw_global.idx = 0;
2932 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2934 #ifdef HAVE_SETSPENT
2935 static void nwrap_files_setspent(void)
2937 nwrap_sp_global.idx = 0;
2940 static struct spwd *nwrap_files_getspent(void)
2944 if (nwrap_sp_global.idx == 0) {
2945 nwrap_files_cache_reload(nwrap_sp_global.cache);
2948 if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
2953 sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
2955 NWRAP_LOG(NWRAP_LOG_DEBUG,
2962 static void nwrap_files_endspent(void)
2964 nwrap_sp_global.idx = 0;
2966 #endif /* HAVE_SETSPENT */
2968 static struct spwd *nwrap_files_getspnam(const char *name)
2972 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
2974 nwrap_files_cache_reload(nwrap_sp_global.cache);
2976 for (i=0; i<nwrap_sp_global.num; i++) {
2977 if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
2978 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
2979 return &nwrap_sp_global.list[i];
2981 NWRAP_LOG(NWRAP_LOG_DEBUG,
2982 "user[%s] does not match [%s]",
2984 nwrap_sp_global.list[i].sp_namp);
2987 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
2992 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2994 /* misc functions */
2995 static int nwrap_files_initgroups(struct nwrap_backend *b,
3004 groups = (gid_t *)malloc(size * sizeof(gid_t));
3005 if (groups == NULL) {
3006 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
3012 nwrap_files_setgrent(b);
3013 while ((grp = nwrap_files_getgrent(b)) != NULL) {
3016 NWRAP_LOG(NWRAP_LOG_DEBUG,
3017 "Inspecting %s for group membership",
3020 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
3021 if (group != grp->gr_gid &&
3022 (strcmp(user, grp->gr_mem[i]) == 0)) {
3023 NWRAP_LOG(NWRAP_LOG_DEBUG,
3024 "%s is member of %s",
3028 groups = (gid_t *)realloc(groups,
3029 (size + 1) * sizeof(gid_t));
3030 if (groups == NULL) {
3031 NWRAP_LOG(NWRAP_LOG_ERROR,
3037 groups[size] = grp->gr_gid;
3043 nwrap_files_endgrent(b);
3045 NWRAP_LOG(NWRAP_LOG_DEBUG,
3046 "%s is member of %d groups",
3049 /* This really only works if uid_wrapper is loaded */
3050 rc = setgroups(size, groups);
3057 /* group functions */
3058 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
3063 (void) b; /* unused */
3065 nwrap_files_cache_reload(nwrap_gr_global.cache);
3067 for (i=0; i<nwrap_gr_global.num; i++) {
3068 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
3069 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
3070 return &nwrap_gr_global.list[i];
3072 NWRAP_LOG(NWRAP_LOG_DEBUG,
3073 "group[%s] does not match [%s]",
3075 nwrap_gr_global.list[i].gr_name);
3078 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
3084 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
3085 const char *name, struct group *grdst,
3086 char *buf, size_t buflen, struct group **grdstp)
3090 gr = nwrap_files_getgrnam(b, name);
3098 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3101 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
3106 (void) b; /* unused */
3108 nwrap_files_cache_reload(nwrap_gr_global.cache);
3110 for (i=0; i<nwrap_gr_global.num; i++) {
3111 if (nwrap_gr_global.list[i].gr_gid == gid) {
3112 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
3113 return &nwrap_gr_global.list[i];
3115 NWRAP_LOG(NWRAP_LOG_DEBUG,
3116 "gid[%u] does not match [%u]",
3118 nwrap_gr_global.list[i].gr_gid);
3121 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
3127 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
3128 gid_t gid, struct group *grdst,
3129 char *buf, size_t buflen, struct group **grdstp)
3133 gr = nwrap_files_getgrgid(b, gid);
3141 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3144 /* group enum functions */
3145 static void nwrap_files_setgrent(struct nwrap_backend *b)
3147 (void) b; /* unused */
3149 nwrap_gr_global.idx = 0;
3152 static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
3156 (void) b; /* unused */
3158 if (nwrap_gr_global.idx == 0) {
3159 nwrap_files_cache_reload(nwrap_gr_global.cache);
3162 if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
3167 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
3169 NWRAP_LOG(NWRAP_LOG_DEBUG,
3170 "return group[%s] gid[%u]",
3171 gr->gr_name, gr->gr_gid);
3176 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
3177 struct group *grdst, char *buf,
3178 size_t buflen, struct group **grdstp)
3182 gr = nwrap_files_getgrent(b);
3190 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
3193 static void nwrap_files_endgrent(struct nwrap_backend *b)
3195 (void) b; /* unused */
3197 nwrap_gr_global.idx = 0;
3200 /* hosts functions */
3201 static int nwrap_files_gethostbyname(const char *name, int af,
3202 struct hostent *result,
3203 struct nwrap_vector *addr_list)
3205 struct nwrap_entdata *ed_head;
3206 struct nwrap_entdata *ed_cur;
3211 char canon_name[DNS_NAME_MAX] = { 0 };
3213 bool he_found = false;
3215 nwrap_files_cache_reload(nwrap_he_global.cache);
3217 name_len = strlen(name);
3218 if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
3219 strncpy(canon_name, name, name_len - 1);
3223 if (!str_tolower_copy(&h_name_lower, name)) {
3224 NWRAP_LOG(NWRAP_LOG_DEBUG,
3225 "Out of memory while converting to lower case");
3229 /* Look at hash table for element */
3230 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
3231 e.key = h_name_lower;
3233 e_p = hsearch(e, FIND);
3235 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
3236 SAFE_FREE(h_name_lower);
3239 SAFE_FREE(h_name_lower);
3241 /* Always cleanup vector and results */
3242 if (!nwrap_vector_init(addr_list)) {
3243 NWRAP_LOG(NWRAP_LOG_DEBUG,
3244 "Unable to initialize memory for addr_list vector");
3248 /* Iterate through results */
3249 ed_head = (struct nwrap_entdata *)e_p->data;
3250 for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
3253 /* Filter by address familiy if provided */
3254 if (af != AF_UNSPEC && he->h_addrtype != af) {
3260 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
3262 if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
3267 memcpy(result, he, sizeof(struct hostent));
3268 NWRAP_LOG(NWRAP_LOG_DEBUG,
3269 "Name found. Returning record for %s",
3273 nwrap_vector_merge(addr_list, &ed_cur->nwrap_addrdata);
3274 result->h_addr_list = nwrap_vector_head(addr_list);
3280 NWRAP_LOG(NWRAP_LOG_DEBUG,
3281 "Name found in database. No records matches type.");
3288 #ifdef HAVE_GETHOSTBYNAME_R
3289 static int nwrap_gethostbyname_r(const char *name,
3290 struct hostent *ret,
3291 char *buf, size_t buflen,
3292 struct hostent **result, int *h_errnop)
3294 struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector));
3297 if (addr_list == NULL) {
3298 NWRAP_LOG(NWRAP_LOG_ERROR,
3299 "Unable to allocate memory for address list");
3304 ZERO_STRUCTP(addr_list);
3306 rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list);
3308 *h_errnop = h_errno;
3309 if (addr_list->items != NULL) {
3310 free(addr_list->items);
3312 SAFE_FREE(addr_list);
3317 memset(buf, '\0', buflen);
3322 int gethostbyname_r(const char *name,
3323 struct hostent *ret,
3324 char *buf, size_t buflen,
3325 struct hostent **result, int *h_errnop)
3327 if (!nss_wrapper_hosts_enabled()) {
3328 return libc_gethostbyname_r(name,
3336 return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
3340 static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
3341 unsigned short port,
3342 const struct addrinfo *hints,
3343 struct addrinfo **ai_tail)
3345 struct nwrap_entdata *ed_head;
3346 struct nwrap_entdata *ed_cur;
3348 struct addrinfo *ai = NULL;
3349 struct addrinfo *ai_head = NULL;
3350 struct addrinfo *ai_prev = NULL;
3353 char canon_name[DNS_NAME_MAX] = { 0 };
3354 bool skip_canonname = false;
3358 nwrap_files_cache_reload(nwrap_he_global.cache);
3360 name_len = strlen(name);
3361 if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
3362 strncpy(canon_name, name, name_len - 1);
3366 if (!str_tolower_copy(&h_name_lower, name)) {
3367 NWRAP_LOG(NWRAP_LOG_DEBUG,
3368 "Out of memory while converting to lower case");
3372 NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
3373 e.key = h_name_lower;
3375 e_p = hsearch(e, FIND);
3377 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
3378 SAFE_FREE(h_name_lower);
3382 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
3383 SAFE_FREE(h_name_lower);
3385 ed_head = (struct nwrap_entdata *)e_p->data;
3387 for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
3392 if (hints->ai_family != AF_UNSPEC &&
3393 he->h_addrtype != hints->ai_family) {
3397 /* Function allocates memory and returns it in ai. */
3398 rc = nwrap_convert_he_ai(he,
3404 /* FIXME: Investigate if this is nice to do... */
3405 NWRAP_LOG(NWRAP_LOG_ERROR,
3406 "Error in converting he to ai! Skipping.");
3409 skip_canonname = true;
3411 if (ai_head == NULL) {
3414 if (ai_prev != NULL) {
3415 ai_prev->ai_next = ai;
3424 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
3425 socklen_t len, int type)
3428 char ip[NWRAP_INET_ADDRSTRLEN] = {0};
3429 struct nwrap_entdata *ed;
3433 (void) len; /* unused */
3435 nwrap_files_cache_reload(nwrap_he_global.cache);
3437 a = inet_ntop(type, addr, ip, sizeof(ip));
3443 nwrap_vector_foreach(ed, nwrap_he_global.entdata, i)
3446 if (he->h_addrtype != type) {
3450 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
3459 #ifdef HAVE_GETHOSTBYADDR_R
3460 static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
3461 struct hostent *ret,
3462 char *buf, size_t buflen,
3463 struct hostent **result, int *h_errnop)
3465 *result = nwrap_files_gethostbyaddr(addr, len, type);
3466 if (*result != NULL) {
3467 memset(buf, '\0', buflen);
3471 *h_errnop = h_errno;
3476 int gethostbyaddr_r(const void *addr, socklen_t len, int type,
3477 struct hostent *ret,
3478 char *buf, size_t buflen,
3479 struct hostent **result, int *h_errnop)
3481 if (!nss_wrapper_hosts_enabled()) {
3482 return libc_gethostbyaddr_r(addr,
3492 return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
3496 /* hosts enum functions */
3497 static void nwrap_files_sethostent(void)
3499 nwrap_he_global.idx = 0;
3502 static struct hostent *nwrap_files_gethostent(void)
3506 if (nwrap_he_global.idx == 0) {
3507 nwrap_files_cache_reload(nwrap_he_global.cache);
3510 if (nwrap_he_global.idx >= nwrap_he_global.num) {
3515 he = &((struct nwrap_entdata *)nwrap_he_global.entdata.items[nwrap_he_global.idx++])->ht;
3517 NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
3522 static void nwrap_files_endhostent(void)
3524 nwrap_he_global.idx = 0;
3532 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
3535 static struct passwd pwd;
3536 static char buf[1000];
3539 if (!b->fns->_nss_getpwnam_r) {
3543 status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno);
3544 if (status == NSS_STATUS_NOTFOUND) {
3547 if (status != NSS_STATUS_SUCCESS) {
3554 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
3555 const char *name, struct passwd *pwdst,
3556 char *buf, size_t buflen, struct passwd **pwdstp)
3560 (void) b; /* unused */
3561 (void) pwdst; /* unused */
3562 (void) pwdstp; /* unused */
3564 if (!b->fns->_nss_getpwnam_r) {
3565 return NSS_STATUS_NOTFOUND;
3568 ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno);
3570 case NSS_STATUS_SUCCESS:
3572 case NSS_STATUS_NOTFOUND:
3577 case NSS_STATUS_TRYAGAIN:
3590 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
3593 static struct passwd pwd;
3594 static char buf[1000];
3597 if (!b->fns->_nss_getpwuid_r) {
3601 status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno);
3602 if (status == NSS_STATUS_NOTFOUND) {
3605 if (status != NSS_STATUS_SUCCESS) {
3611 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
3612 uid_t uid, struct passwd *pwdst,
3613 char *buf, size_t buflen, struct passwd **pwdstp)
3617 (void) pwdstp; /* unused */
3619 if (!b->fns->_nss_getpwuid_r) {
3623 ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno);
3625 case NSS_STATUS_SUCCESS:
3627 case NSS_STATUS_NOTFOUND:
3632 case NSS_STATUS_TRYAGAIN:
3645 static void nwrap_module_setpwent(struct nwrap_backend *b)
3647 if (!b->fns->_nss_setpwent) {
3651 b->fns->_nss_setpwent();
3654 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
3656 static struct passwd pwd;
3657 static char buf[1000];
3660 if (!b->fns->_nss_getpwent_r) {
3664 status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno);
3665 if (status == NSS_STATUS_NOTFOUND) {
3668 if (status != NSS_STATUS_SUCCESS) {
3674 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
3675 struct passwd *pwdst, char *buf,
3676 size_t buflen, struct passwd **pwdstp)
3680 (void) pwdstp; /* unused */
3682 if (!b->fns->_nss_getpwent_r) {
3686 ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno);
3688 case NSS_STATUS_SUCCESS:
3690 case NSS_STATUS_NOTFOUND:
3695 case NSS_STATUS_TRYAGAIN:
3708 static void nwrap_module_endpwent(struct nwrap_backend *b)
3710 if (!b->fns->_nss_endpwent) {
3714 b->fns->_nss_endpwent();
3717 static int nwrap_module_initgroups(struct nwrap_backend *b,
3718 const char *user, gid_t group)
3724 if (!b->fns->_nss_initgroups) {
3725 return NSS_STATUS_UNAVAIL;
3728 return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno);
3731 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
3734 static struct group grp;
3736 static int buflen = 1000;
3739 if (!b->fns->_nss_getgrnam_r) {
3744 buf = (char *)malloc(buflen);
3747 status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno);
3748 if (status == NSS_STATUS_TRYAGAIN) {
3750 buf = (char *)realloc(buf, buflen);
3756 if (status == NSS_STATUS_NOTFOUND) {
3760 if (status != NSS_STATUS_SUCCESS) {
3767 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
3768 const char *name, struct group *grdst,
3769 char *buf, size_t buflen, struct group **grdstp)
3773 (void) grdstp; /* unused */
3775 if (!b->fns->_nss_getgrnam_r) {
3779 ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno);
3781 case NSS_STATUS_SUCCESS:
3783 case NSS_STATUS_NOTFOUND:
3788 case NSS_STATUS_TRYAGAIN:
3801 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
3804 static struct group grp;
3806 static int buflen = 1000;
3809 if (!b->fns->_nss_getgrgid_r) {
3814 buf = (char *)malloc(buflen);
3818 status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno);
3819 if (status == NSS_STATUS_TRYAGAIN) {
3821 buf = (char *)realloc(buf, buflen);
3827 if (status == NSS_STATUS_NOTFOUND) {
3831 if (status != NSS_STATUS_SUCCESS) {
3838 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
3839 gid_t gid, struct group *grdst,
3840 char *buf, size_t buflen, struct group **grdstp)
3844 (void) grdstp; /* unused */
3846 if (!b->fns->_nss_getgrgid_r) {
3850 ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno);
3852 case NSS_STATUS_SUCCESS:
3854 case NSS_STATUS_NOTFOUND:
3859 case NSS_STATUS_TRYAGAIN:
3872 static void nwrap_module_setgrent(struct nwrap_backend *b)
3874 if (!b->fns->_nss_setgrent) {
3878 b->fns->_nss_setgrent();
3881 static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
3883 static struct group grp;
3885 static int buflen = 1024;
3888 if (!b->fns->_nss_getgrent_r) {
3893 buf = (char *)malloc(buflen);
3897 status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno);
3898 if (status == NSS_STATUS_TRYAGAIN) {
3900 buf = (char *)realloc(buf, buflen);
3906 if (status == NSS_STATUS_NOTFOUND) {
3910 if (status != NSS_STATUS_SUCCESS) {
3917 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
3918 struct group *grdst, char *buf,
3919 size_t buflen, struct group **grdstp)
3923 (void) grdstp; /* unused */
3925 if (!b->fns->_nss_getgrent_r) {
3929 ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno);
3931 case NSS_STATUS_SUCCESS:
3933 case NSS_STATUS_NOTFOUND:
3938 case NSS_STATUS_TRYAGAIN:
3951 static void nwrap_module_endgrent(struct nwrap_backend *b)
3953 if (!b->fns->_nss_endgrent) {
3957 b->fns->_nss_endgrent();
3960 /****************************************************************************
3962 ***************************************************************************/
3964 static struct passwd *nwrap_getpwnam(const char *name)
3969 for (i=0; i < nwrap_main_global->num_backends; i++) {
3970 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3971 pwd = b->ops->nw_getpwnam(b, name);
3980 struct passwd *getpwnam(const char *name)
3982 if (!nss_wrapper_enabled()) {
3983 return libc_getpwnam(name);
3986 return nwrap_getpwnam(name);
3989 /****************************************************************************
3991 ***************************************************************************/
3993 static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
3994 char *buf, size_t buflen, struct passwd **pwdstp)
3998 for (i=0; i < nwrap_main_global->num_backends; i++) {
3999 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4000 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
4001 if (ret == ENOENT) {
4010 #ifdef HAVE_GETPWNAM_R
4011 # ifdef HAVE_SOLARIS_GETPWNAM_R
4012 int getpwnam_r(const char *name, struct passwd *pwdst,
4013 char *buf, int buflen, struct passwd **pwdstp)
4014 # else /* HAVE_SOLARIS_GETPWNAM_R */
4015 int getpwnam_r(const char *name, struct passwd *pwdst,
4016 char *buf, size_t buflen, struct passwd **pwdstp)
4017 # endif /* HAVE_SOLARIS_GETPWNAM_R */
4019 if (!nss_wrapper_enabled()) {
4020 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
4023 return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
4027 /****************************************************************************
4029 ***************************************************************************/
4031 static struct passwd *nwrap_getpwuid(uid_t uid)
4036 for (i=0; i < nwrap_main_global->num_backends; i++) {
4037 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4038 pwd = b->ops->nw_getpwuid(b, uid);
4047 struct passwd *getpwuid(uid_t uid)
4049 if (!nss_wrapper_enabled()) {
4050 return libc_getpwuid(uid);
4053 return nwrap_getpwuid(uid);
4056 /****************************************************************************
4058 ***************************************************************************/
4060 static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
4061 char *buf, size_t buflen, struct passwd **pwdstp)
4065 for (i=0; i < nwrap_main_global->num_backends; i++) {
4066 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4067 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
4068 if (ret == ENOENT) {
4077 #ifdef HAVE_SOLARIS_GETPWUID_R
4078 int getpwuid_r(uid_t uid, struct passwd *pwdst,
4079 char *buf, int buflen, struct passwd **pwdstp)
4081 int getpwuid_r(uid_t uid, struct passwd *pwdst,
4082 char *buf, size_t buflen, struct passwd **pwdstp)
4085 if (!nss_wrapper_enabled()) {
4086 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
4089 return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
4092 /****************************************************************************
4094 ***************************************************************************/
4096 static void nwrap_setpwent(void)
4100 for (i=0; i < nwrap_main_global->num_backends; i++) {
4101 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4102 b->ops->nw_setpwent(b);
4108 if (!nss_wrapper_enabled()) {
4116 /****************************************************************************
4118 ***************************************************************************/
4120 static struct passwd *nwrap_getpwent(void)
4125 for (i=0; i < nwrap_main_global->num_backends; i++) {
4126 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4127 pwd = b->ops->nw_getpwent(b);
4136 struct passwd *getpwent(void)
4138 if (!nss_wrapper_enabled()) {
4139 return libc_getpwent();
4142 return nwrap_getpwent();
4145 /****************************************************************************
4147 ***************************************************************************/
4149 static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
4150 size_t buflen, struct passwd **pwdstp)
4154 for (i=0; i < nwrap_main_global->num_backends; i++) {
4155 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4156 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
4157 if (ret == ENOENT) {
4166 #ifdef HAVE_SOLARIS_GETPWENT_R
4167 struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
4169 struct passwd *pwdstp = NULL;
4172 if (!nss_wrapper_enabled()) {
4173 return libc_getpwent_r(pwdst, buf, buflen);
4175 rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
4182 #else /* HAVE_SOLARIS_GETPWENT_R */
4183 int getpwent_r(struct passwd *pwdst, char *buf,
4184 size_t buflen, struct passwd **pwdstp)
4186 if (!nss_wrapper_enabled()) {
4187 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
4190 return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
4192 #endif /* HAVE_SOLARIS_GETPWENT_R */
4194 /****************************************************************************
4196 ***************************************************************************/
4198 static void nwrap_endpwent(void)
4202 for (i=0; i < nwrap_main_global->num_backends; i++) {
4203 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4204 b->ops->nw_endpwent(b);
4210 if (!nss_wrapper_enabled()) {
4218 /****************************************************************************
4220 ***************************************************************************/
4222 static int nwrap_initgroups(const char *user, gid_t group)
4226 for (i=0; i < nwrap_main_global->num_backends; i++) {
4227 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4230 rc = b->ops->nw_initgroups(b, user, group);
4240 int initgroups(const char *user, gid_t group)
4242 if (!nss_wrapper_enabled()) {
4243 return libc_initgroups(user, group);
4246 return nwrap_initgroups(user, group);
4249 /****************************************************************************
4251 ***************************************************************************/
4253 static struct group *nwrap_getgrnam(const char *name)
4258 for (i=0; i < nwrap_main_global->num_backends; i++) {
4259 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4260 grp = b->ops->nw_getgrnam(b, name);
4269 struct group *getgrnam(const char *name)
4271 if (!nss_wrapper_enabled()) {
4272 return libc_getgrnam(name);
4275 return nwrap_getgrnam(name);
4278 /****************************************************************************
4280 ***************************************************************************/
4282 static int nwrap_getgrnam_r(const char *name, struct group *grdst,
4283 char *buf, size_t buflen, struct group **grdstp)
4287 for (i=0; i < nwrap_main_global->num_backends; i++) {
4288 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4289 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
4290 if (ret == ENOENT) {
4299 #ifdef HAVE_GETGRNAM_R
4300 # ifdef HAVE_SOLARIS_GETGRNAM_R
4301 int getgrnam_r(const char *name, struct group *grp,
4302 char *buf, int buflen, struct group **pgrp)
4303 # else /* HAVE_SOLARIS_GETGRNAM_R */
4304 int getgrnam_r(const char *name, struct group *grp,
4305 char *buf, size_t buflen, struct group **pgrp)
4306 # endif /* HAVE_SOLARIS_GETGRNAM_R */
4308 if (!nss_wrapper_enabled()) {
4309 return libc_getgrnam_r(name,
4316 return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
4318 #endif /* HAVE_GETGRNAM_R */
4320 /****************************************************************************
4322 ***************************************************************************/
4324 static struct group *nwrap_getgrgid(gid_t gid)
4329 for (i=0; i < nwrap_main_global->num_backends; i++) {
4330 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4331 grp = b->ops->nw_getgrgid(b, gid);
4340 struct group *getgrgid(gid_t gid)
4342 if (!nss_wrapper_enabled()) {
4343 return libc_getgrgid(gid);
4346 return nwrap_getgrgid(gid);
4349 /****************************************************************************
4351 ***************************************************************************/
4353 static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
4354 char *buf, size_t buflen, struct group **grdstp)
4358 for (i=0; i < nwrap_main_global->num_backends; i++) {
4359 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4360 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
4361 if (ret == ENOENT) {
4370 #ifdef HAVE_GETGRGID_R
4371 # ifdef HAVE_SOLARIS_GETGRGID_R
4372 int getgrgid_r(gid_t gid, struct group *grdst,
4373 char *buf, int buflen, struct group **grdstp)
4374 # else /* HAVE_SOLARIS_GETGRGID_R */
4375 int getgrgid_r(gid_t gid, struct group *grdst,
4376 char *buf, size_t buflen, struct group **grdstp)
4377 # endif /* HAVE_SOLARIS_GETGRGID_R */
4379 if (!nss_wrapper_enabled()) {
4380 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
4383 return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
4387 /****************************************************************************
4389 ***************************************************************************/
4391 static void nwrap_setgrent(void)
4395 for (i=0; i < nwrap_main_global->num_backends; i++) {
4396 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4397 b->ops->nw_setgrent(b);
4401 #ifdef HAVE_BSD_SETGRENT
4407 if (!nss_wrapper_enabled()) {
4415 #ifdef HAVE_BSD_SETGRENT
4422 /****************************************************************************
4424 ***************************************************************************/
4426 static struct group *nwrap_getgrent(void)
4431 for (i=0; i < nwrap_main_global->num_backends; i++) {
4432 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4433 grp = b->ops->nw_getgrent(b);
4442 struct group *getgrent(void)
4444 if (!nss_wrapper_enabled()) {
4445 return libc_getgrent();
4448 return nwrap_getgrent();
4451 /****************************************************************************
4453 ***************************************************************************/
4455 static int nwrap_getgrent_r(struct group *grdst, char *buf,
4456 size_t buflen, struct group **grdstp)
4460 for (i=0; i < nwrap_main_global->num_backends; i++) {
4461 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4462 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
4463 if (ret == ENOENT) {
4472 #ifdef HAVE_SOLARIS_GETGRENT_R
4473 struct group *getgrent_r(struct group *src, char *buf, int buflen)
4475 struct group *grdstp = NULL;
4478 if (!nss_wrapper_enabled()) {
4479 return libc_getgrent_r(src, buf, buflen);
4482 rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
4489 #else /* HAVE_SOLARIS_GETGRENT_R */
4490 int getgrent_r(struct group *src, char *buf,
4491 size_t buflen, struct group **grdstp)
4493 if (!nss_wrapper_enabled()) {
4494 return libc_getgrent_r(src, buf, buflen, grdstp);
4497 return nwrap_getgrent_r(src, buf, buflen, grdstp);
4499 #endif /* HAVE_SOLARIS_GETGRENT_R */
4501 /****************************************************************************
4503 ***************************************************************************/
4505 static void nwrap_endgrent(void)
4509 for (i=0; i < nwrap_main_global->num_backends; i++) {
4510 struct nwrap_backend *b = &nwrap_main_global->backends[i];
4511 b->ops->nw_endgrent(b);
4517 if (!nss_wrapper_enabled()) {
4525 /****************************************************************************
4527 ***************************************************************************/
4529 #ifdef HAVE_GETGROUPLIST
4530 static int nwrap_getgrouplist(const char *user, gid_t group,
4531 gid_t *groups, int *ngroups)
4537 NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
4539 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
4541 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
4545 groups_tmp[0] = group;
4548 while ((grp = nwrap_getgrent()) != NULL) {
4551 NWRAP_LOG(NWRAP_LOG_DEBUG,
4552 "Inspecting %s for group membership",
4555 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
4557 if (group != grp->gr_gid &&
4558 (strcmp(user, grp->gr_mem[i]) == 0)) {
4560 NWRAP_LOG(NWRAP_LOG_DEBUG,
4561 "%s is member of %s",
4565 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
4567 NWRAP_LOG(NWRAP_LOG_ERROR,
4572 groups_tmp[count] = grp->gr_gid;
4581 NWRAP_LOG(NWRAP_LOG_DEBUG,
4582 "%s is member of %d groups",
4585 if (*ngroups < count) {
4592 memcpy(groups, groups_tmp, count * sizeof(gid_t));
4598 int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
4600 if (!nss_wrapper_enabled()) {
4601 return libc_getgrouplist(user, group, groups, ngroups);
4604 return nwrap_getgrouplist(user, group, groups, ngroups);
4608 /**********************************************************
4610 **********************************************************/
4612 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
4614 #ifdef HAVE_SETSPENT
4615 static void nwrap_setspent(void)
4617 nwrap_files_setspent();
4622 if (!nss_wrapper_shadow_enabled()) {
4629 static struct spwd *nwrap_getspent(void)
4631 return nwrap_files_getspent();
4634 struct spwd *getspent(void)
4636 if (!nss_wrapper_shadow_enabled()) {
4640 return nwrap_getspent();
4643 static void nwrap_endspent(void)
4645 nwrap_files_endspent();
4650 if (!nss_wrapper_shadow_enabled()) {
4656 #endif /* HAVE_SETSPENT */
4658 static struct spwd *nwrap_getspnam(const char *name)
4660 return nwrap_files_getspnam(name);
4663 struct spwd *getspnam(const char *name)
4665 if (!nss_wrapper_shadow_enabled()) {
4669 return nwrap_getspnam(name);
4672 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
4674 /**********************************************************
4676 **********************************************************/
4678 static void nwrap_sethostent(int stayopen) {
4679 (void) stayopen; /* ignored */
4681 nwrap_files_sethostent();
4684 #ifdef HAVE_SOLARIS_SETHOSTENT
4685 int sethostent(int stayopen)
4687 if (!nss_wrapper_hosts_enabled()) {
4688 libc_sethostent(stayopen);
4692 nwrap_sethostent(stayopen);
4696 #else /* HAVE_SOLARIS_SETHOSTENT */
4697 void sethostent(int stayopen)
4699 if (!nss_wrapper_hosts_enabled()) {
4700 libc_sethostent(stayopen);
4704 nwrap_sethostent(stayopen);
4706 #endif /* HAVE_SOLARIS_SETHOSTENT */
4708 static struct hostent *nwrap_gethostent(void)
4710 return nwrap_files_gethostent();
4713 struct hostent *gethostent(void) {
4714 if (!nss_wrapper_hosts_enabled()) {
4715 return libc_gethostent();
4718 return nwrap_gethostent();
4721 static void nwrap_endhostent(void) {
4722 nwrap_files_endhostent();
4725 #ifdef HAVE_SOLARIS_ENDHOSTENT
4726 int endhostent(void)
4728 if (!nss_wrapper_hosts_enabled()) {
4737 #else /* HAVE_SOLARIS_ENDHOSTENT */
4738 void endhostent(void)
4740 if (!nss_wrapper_hosts_enabled()) {
4747 #endif /* HAVE_SOLARIS_ENDHOSTENT */
4750 /* BSD implementation stores data in thread local storage but GLIBC does not */
4751 static __thread struct hostent user_he;
4752 static __thread struct nwrap_vector user_addrlist;
4754 static struct hostent user_he;
4755 static struct nwrap_vector user_addrlist;
4757 static struct hostent *nwrap_gethostbyname(const char *name)
4759 if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
4765 struct hostent *gethostbyname(const char *name)
4767 if (!nss_wrapper_hosts_enabled()) {
4768 return libc_gethostbyname(name);
4771 return nwrap_gethostbyname(name);
4774 /* This is a GNU extension - Also can be found on BSD systems */
4775 #ifdef HAVE_GETHOSTBYNAME2
4777 /* BSD implementation stores data in thread local storage but GLIBC not */
4778 static __thread struct hostent user_he2;
4779 static __thread struct nwrap_vector user_addrlist2;
4781 static struct hostent user_he2;
4782 static struct nwrap_vector user_addrlist2;
4784 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
4786 if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
4792 struct hostent *gethostbyname2(const char *name, int af)
4794 if (!nss_wrapper_hosts_enabled()) {
4795 return libc_gethostbyname2(name, af);
4798 return nwrap_gethostbyname2(name, af);
4802 static struct hostent *nwrap_gethostbyaddr(const void *addr,
4803 socklen_t len, int type)
4805 return nwrap_files_gethostbyaddr(addr, len, type);
4808 struct hostent *gethostbyaddr(const void *addr,
4809 socklen_t len, int type)
4811 if (!nss_wrapper_hosts_enabled()) {
4812 return libc_gethostbyaddr(addr, len, type);
4815 return nwrap_gethostbyaddr(addr, len, type);
4818 static const struct addrinfo default_hints =
4820 .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
4821 .ai_family = AF_UNSPEC,
4826 .ai_canonname = NULL,
4830 static int nwrap_convert_he_ai(const struct hostent *he,
4831 unsigned short port,
4832 const struct addrinfo *hints,
4833 struct addrinfo **pai,
4834 bool skip_canonname)
4836 struct addrinfo *ai;
4843 switch (he->h_addrtype) {
4845 socklen = sizeof(struct sockaddr_in);
4849 socklen = sizeof(struct sockaddr_in6);
4856 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
4862 ai->ai_family = he->h_addrtype;
4863 ai->ai_socktype = hints->ai_socktype;
4864 ai->ai_protocol = hints->ai_protocol;
4865 ai->ai_canonname = NULL;
4867 ai->ai_addrlen = socklen;
4868 ai->ai_addr = (void *)(ai + 1);
4870 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
4871 ai->ai_addr->sa_len = socklen;
4873 ai->ai_addr->sa_family = he->h_addrtype;
4875 switch (he->h_addrtype) {
4878 struct sockaddr_in *sinp =
4879 (struct sockaddr_in *) ai->ai_addr;
4881 memset(sinp, 0, sizeof(struct sockaddr_in));
4883 sinp->sin_port = htons(port);
4884 sinp->sin_family = AF_INET;
4886 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
4887 memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
4894 struct sockaddr_in6 *sin6p =
4895 (struct sockaddr_in6 *) ai->ai_addr;
4897 memset(sin6p, 0, sizeof(struct sockaddr_in6));
4899 sin6p->sin6_port = htons(port);
4900 sin6p->sin6_family = AF_INET6;
4902 memcpy(&sin6p->sin6_addr,
4912 if (he->h_name && !skip_canonname) {
4913 ai->ai_canonname = strdup(he->h_name);
4914 if (ai->ai_canonname == NULL) {
4924 static int nwrap_getaddrinfo(const char *node,
4925 const char *service,
4926 const struct addrinfo *hints,
4927 struct addrinfo **res)
4929 struct addrinfo *ai = NULL;
4930 struct addrinfo *p = NULL;
4931 struct addrinfo *ai_tail;
4932 unsigned short port = 0;
4942 .family = AF_UNSPEC,
4944 int eai = EAI_SYSTEM;
4948 if (node == NULL && service == NULL) {
4952 if (hints == NULL) {
4953 hints = &default_hints;
4957 hints.ai_flags contains invalid flags; or, hints.ai_flags
4958 included AI_CANONNAME and name was NULL.
4960 if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
4961 return EAI_BADFLAGS;
4964 ret = libc_getaddrinfo(node, service, hints, &p);
4968 /* If no node has been specified, let glibc deal with it */
4973 if (service != NULL && service[0] != '\0') {
4974 if (isdigit((int)service[0])) {
4975 port = (unsigned short)atoi(service);
4977 const char *proto = NULL;
4980 if (hints->ai_protocol != 0) {
4981 struct protoent *pent;
4983 pent = getprotobynumber(hints->ai_protocol);
4985 proto = pent->p_name;
4989 s = getservbyname(service, proto);
4991 port = ntohs(s->s_port);
5002 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
5003 rc = inet_pton(AF_INET, node, &addr.in.v4);
5006 addr.family = AF_INET;
5009 rc = inet_pton(AF_INET6, node, &addr.in.v6);
5011 addr.family = AF_INET6;
5017 if (addr.family == AF_INET) {
5018 ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
5023 } else if (addr.family == AF_INET6) {
5024 ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
5030 ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
5037 return ret == 0 ? 0 : eai;
5044 if (ai->ai_flags == 0) {
5045 ai->ai_flags = hints->ai_flags;
5047 if (ai->ai_socktype == 0) {
5048 ai->ai_socktype = SOCK_DGRAM;
5050 if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) {
5051 ai->ai_protocol = 17; /* UDP */
5052 } else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
5053 ai->ai_protocol = 6; /* TCP */
5056 if (hints->ai_socktype == 0) {
5058 struct addrinfo *ai_head = ai;
5059 struct addrinfo *ai_tmp;
5060 struct addrinfo *ai_new_tail = ai_tail;
5062 /* Add at least one more struct */
5065 ai_tmp = malloc(sizeof(struct addrinfo));
5066 memcpy(ai_tmp, ai_head, sizeof(struct addrinfo));
5067 ai_tmp->ai_next = NULL;
5069 /* We need a deep copy or freeaddrinfo() will blow up */
5070 if (ai_head->ai_canonname != NULL) {
5071 ai_tmp->ai_canonname =
5072 strdup(ai_head->ai_canonname);
5074 ai_tmp->ai_addr = malloc(sizeof(struct sockaddr));
5075 memcpy(ai_tmp->ai_addr, ai_head, sizeof(struct sockaddr));
5077 if (ai_head->ai_flags == 0) {
5078 ai_tmp->ai_flags = hints->ai_flags;
5080 if (ai_head->ai_socktype == SOCK_DGRAM) {
5081 ai_tmp->ai_socktype = SOCK_STREAM;
5082 } else if (ai_head->ai_socktype == SOCK_STREAM) {
5083 ai_tmp->ai_socktype = SOCK_DGRAM;
5085 if (ai_head->ai_socktype == SOCK_DGRAM) {
5086 ai_tmp->ai_protocol = 17; /* UDP */
5087 } else if (ai_head->ai_socktype == SOCK_STREAM) {
5088 ai_tmp->ai_protocol = 6; /* TCP */
5090 ai_new_tail->ai_next = ai_tmp;
5091 ai_new_tail = ai_tmp;
5093 if (ai_head == ai_tail) {
5096 ai_head = ai_head->ai_next;
5105 int getaddrinfo(const char *node, const char *service,
5106 const struct addrinfo *hints,
5107 struct addrinfo **res)
5109 if (!nss_wrapper_hosts_enabled()) {
5110 return libc_getaddrinfo(node, service, hints, res);
5113 return nwrap_getaddrinfo(node, service, hints, res);
5116 static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
5117 char *host, size_t hostlen,
5118 char *serv, size_t servlen,
5122 struct servent *service;
5129 if (sa == NULL || salen < sizeof(sa_family_t)) {
5133 if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
5137 type = sa->sa_family;
5140 if (salen < sizeof(struct sockaddr_in))
5142 addr = &((const struct sockaddr_in *)sa)->sin_addr;
5143 addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
5144 port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
5148 if (salen < sizeof(struct sockaddr_in6))
5150 addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
5151 addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
5152 port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
5161 if ((flags & NI_NUMERICHOST) == 0) {
5162 he = nwrap_files_gethostbyaddr(addr, addrlen, type);
5163 if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
5166 if (he != NULL && he->h_name != NULL) {
5167 if (strlen(he->h_name) >= hostlen)
5168 return EAI_OVERFLOW;
5169 strcpy(host, he->h_name);
5170 if (flags & NI_NOFQDN)
5171 host[strcspn(host, ".")] = '\0';
5173 if (inet_ntop(type, addr, host, hostlen) == NULL)
5174 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
5180 if ((flags & NI_NUMERICSERV) == 0) {
5181 proto = (flags & NI_DGRAM) ? "udp" : "tcp";
5182 service = getservbyport(htons(port), proto);
5184 if (service != NULL) {
5185 if (strlen(service->s_name) >= servlen)
5186 return EAI_OVERFLOW;
5187 strcpy(serv, service->s_name);
5189 if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
5190 return EAI_OVERFLOW;
5197 #ifdef HAVE_LINUX_GETNAMEINFO
5198 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5199 char *host, socklen_t hostlen,
5200 char *serv, socklen_t servlen,
5202 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
5203 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5204 char *host, socklen_t hostlen,
5205 char *serv, socklen_t servlen,
5208 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
5209 char *host, size_t hostlen,
5210 char *serv, size_t servlen,
5214 if (!nss_wrapper_hosts_enabled()) {
5215 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
5218 return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
5221 static int nwrap_gethostname(char *name, size_t len)
5223 const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
5225 if (strlen(hostname) >= len) {
5226 errno = ENAMETOOLONG;
5229 snprintf(name, len, "%s", hostname);
5234 #ifdef HAVE_SOLARIS_GETHOSTNAME
5235 int gethostname(char *name, int len)
5236 #else /* HAVE_SOLARIS_GETHOSTNAME */
5237 int gethostname(char *name, size_t len)
5238 #endif /* HAVE_SOLARIS_GETHOSTNAME */
5240 if (!nwrap_hostname_enabled()) {
5241 return libc_gethostname(name, len);
5244 return nwrap_gethostname(name, len);
5247 /****************************
5249 ***************************/
5252 * This function is called when the library is unloaded and makes sure that
5253 * sockets get closed and the unix file for the socket are unlinked.
5255 void nwrap_destructor(void)
5259 if (nwrap_main_global != NULL) {
5260 struct nwrap_main *m = nwrap_main_global;
5263 SAFE_FREE(m->libc->fns);
5264 if (m->libc->handle != NULL) {
5265 dlclose(m->libc->handle);
5267 if (m->libc->nsl_handle != NULL) {
5268 dlclose(m->libc->nsl_handle);
5270 if (m->libc->sock_handle != NULL) {
5271 dlclose(m->libc->sock_handle);
5276 for (i = 0; i < m->num_backends; i++) {
5277 struct nwrap_backend *b = &(m->backends[i]);
5279 if (b->so_handle != NULL) {
5280 dlclose(b->so_handle);
5284 SAFE_FREE(m->backends);
5287 if (nwrap_pw_global.cache != NULL) {
5288 struct nwrap_cache *c = nwrap_pw_global.cache;
5290 nwrap_files_cache_unload(c);
5296 SAFE_FREE(nwrap_pw_global.list);
5297 nwrap_pw_global.num = 0;
5300 if (nwrap_gr_global.cache != NULL) {
5301 struct nwrap_cache *c = nwrap_gr_global.cache;
5303 nwrap_files_cache_unload(c);
5309 SAFE_FREE(nwrap_gr_global.list);
5310 nwrap_pw_global.num = 0;
5313 if (nwrap_he_global.cache != NULL) {
5314 struct nwrap_cache *c = nwrap_he_global.cache;
5316 nwrap_files_cache_unload(c);
5322 nwrap_he_global.num = 0;