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
40 #include <sys/types.h>
42 #include <sys/socket.h>
55 #include <netinet/in.h>
61 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
62 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
65 #ifndef _POSIX_PTHREAD_SEMANTICS
66 #define _POSIX_PTHREAD_SEMANTICS
73 #endif /* HAVE_SHADOW_H */
76 #include <arpa/inet.h>
77 #include <netinet/in.h>
81 #if defined(HAVE_NSS_H)
85 typedef enum nss_status NSS_STATUS
;
86 #elif defined(HAVE_NSS_COMMON_H)
88 #include <nss_common.h>
89 #include <nss_dbdefs.h>
92 typedef nss_status_t NSS_STATUS
;
94 # define NSS_STATUS_SUCCESS NSS_SUCCESS
95 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
96 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
97 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
99 # error "No nsswitch support detected"
103 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
111 #define EAI_NODATA EAI_NONAME
114 #ifndef EAI_ADDRFAMILY
115 #define EAI_ADDRFAMILY EAI_FAMILY
119 #define __STRING(x) #x
122 #ifndef __STRINGSTRING
123 #define __STRINGSTRING(x) __STRING(x)
127 #define __LINESTR__ __STRINGSTRING(__LINE__)
131 #define __location__ __FILE__ ":" __LINESTR__
135 #define DNS_NAME_MAX 255
138 /* GCC have printf type attribute check. */
139 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
140 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
142 #define PRINTF_ATTRIBUTE(a,b)
143 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
145 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
146 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
148 #define DESTRUCTOR_ATTRIBUTE
149 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
151 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
154 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
158 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
160 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
163 #define NWRAP_LOCK(m) do { \
164 pthread_mutex_lock(&( m ## _mutex)); \
167 #define NWRAP_UNLOCK(m) do { \
168 pthread_mutex_unlock(&( m ## _mutex)); \
172 static bool nwrap_initialized
= false;
173 static pthread_mutex_t nwrap_initialized_mutex
= PTHREAD_MUTEX_INITIALIZER
;
175 /* The mutex or accessing the id */
176 static pthread_mutex_t nwrap_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
177 static pthread_mutex_t nwrap_gr_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
178 static pthread_mutex_t nwrap_he_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
179 static pthread_mutex_t nwrap_pw_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
180 static pthread_mutex_t nwrap_sp_global_mutex
= PTHREAD_MUTEX_INITIALIZER
;
182 /* Add new global locks here please */
183 /* Also don't forget to add locks to
184 * nwrap_init() function.
186 # define NWRAP_LOCK_ALL do { \
187 NWRAP_LOCK(nwrap_initialized); \
188 NWRAP_LOCK(nwrap_global); \
189 NWRAP_LOCK(nwrap_gr_global); \
190 NWRAP_LOCK(nwrap_he_global); \
191 NWRAP_LOCK(nwrap_pw_global); \
192 NWRAP_LOCK(nwrap_sp_global); \
195 # define NWRAP_UNLOCK_ALL do {\
196 NWRAP_UNLOCK(nwrap_sp_global); \
197 NWRAP_UNLOCK(nwrap_pw_global); \
198 NWRAP_UNLOCK(nwrap_he_global); \
199 NWRAP_UNLOCK(nwrap_gr_global); \
200 NWRAP_UNLOCK(nwrap_global); \
201 NWRAP_UNLOCK(nwrap_initialized); \
204 static void nwrap_thread_prepare(void)
209 static void nwrap_thread_parent(void)
214 static void nwrap_thread_child(void)
219 enum nwrap_dbglvl_e
{
227 # define NWRAP_LOG(...)
230 static void nwrap_log(enum nwrap_dbglvl_e dbglvl
, const char *func
, const char *format
, ...) PRINTF_ATTRIBUTE(3, 4);
231 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
233 static void nwrap_log(enum nwrap_dbglvl_e dbglvl
,
235 const char *format
, ...)
240 unsigned int lvl
= 0;
243 d
= getenv("NSS_WRAPPER_DEBUGLEVEL");
248 va_start(va
, format
);
249 vsnprintf(buffer
, sizeof(buffer
), format
, va
);
254 case NWRAP_LOG_ERROR
:
256 "NWRAP_ERROR(%d) - %s: %s\n",
261 "NWRAP_WARN(%d) - %s: %s\n",
264 case NWRAP_LOG_DEBUG
:
266 "NWRAP_DEBUG(%d) - %s: %s\n",
269 case NWRAP_LOG_TRACE
:
271 "NWRAP_TRACE(%d) - %s: %s\n",
277 #endif /* NDEBUG NWRAP_LOG */
279 struct nwrap_libc_fns
{
280 struct passwd
*(*_libc_getpwnam
)(const char *name
);
281 int (*_libc_getpwnam_r
)(const char *name
, struct passwd
*pwd
,
282 char *buf
, size_t buflen
, struct passwd
**result
);
283 struct passwd
*(*_libc_getpwuid
)(uid_t uid
);
284 int (*_libc_getpwuid_r
)(uid_t uid
, struct passwd
*pwd
, char *buf
, size_t buflen
, struct passwd
**result
);
285 void (*_libc_setpwent
)(void);
286 struct passwd
*(*_libc_getpwent
)(void);
287 #ifdef HAVE_SOLARIS_GETPWENT_R
288 struct passwd
*(*_libc_getpwent_r
)(struct passwd
*pwbuf
, char *buf
, size_t buflen
);
290 int (*_libc_getpwent_r
)(struct passwd
*pwbuf
, char *buf
, size_t buflen
, struct passwd
**pwbufp
);
292 void (*_libc_endpwent
)(void);
293 int (*_libc_initgroups
)(const char *user
, gid_t gid
);
294 struct group
*(*_libc_getgrnam
)(const char *name
);
295 int (*_libc_getgrnam_r
)(const char *name
, struct group
*grp
, char *buf
, size_t buflen
, struct group
**result
);
296 struct group
*(*_libc_getgrgid
)(gid_t gid
);
297 int (*_libc_getgrgid_r
)(gid_t gid
, struct group
*grp
, char *buf
, size_t buflen
, struct group
**result
);
298 void (*_libc_setgrent
)(void);
299 struct group
*(*_libc_getgrent
)(void);
300 #ifdef HAVE_SOLARIS_GETGRENT_R
301 struct group
*(*_libc_getgrent_r
)(struct group
*group
, char *buf
, size_t buflen
);
303 int (*_libc_getgrent_r
)(struct group
*group
, char *buf
, size_t buflen
, struct group
**result
);
305 void (*_libc_endgrent
)(void);
306 int (*_libc_getgrouplist
)(const char *user
, gid_t group
, gid_t
*groups
, int *ngroups
);
308 void (*_libc_sethostent
)(int stayopen
);
309 struct hostent
*(*_libc_gethostent
)(void);
310 void (*_libc_endhostent
)(void);
312 struct hostent
*(*_libc_gethostbyname
)(const char *name
);
313 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
314 struct hostent
*(*_libc_gethostbyname2
)(const char *name
, int af
);
316 struct hostent
*(*_libc_gethostbyaddr
)(const void *addr
, socklen_t len
, int type
);
318 int (*_libc_getaddrinfo
)(const char *node
, const char *service
,
319 const struct addrinfo
*hints
,
320 struct addrinfo
**res
);
321 int (*_libc_getnameinfo
)(const struct sockaddr
*sa
, socklen_t salen
,
322 char *host
, size_t hostlen
,
323 char *serv
, size_t servlen
,
325 int (*_libc_gethostname
)(char *name
, size_t len
);
326 #ifdef HAVE_GETHOSTBYNAME_R
327 int (*_libc_gethostbyname_r
)(const char *name
,
329 char *buf
, size_t buflen
,
330 struct hostent
**result
, int *h_errnop
);
332 #ifdef HAVE_GETHOSTBYADDR_R
333 int (*_libc_gethostbyaddr_r
)(const void *addr
, socklen_t len
, int type
,
335 char *buf
, size_t buflen
,
336 struct hostent
**result
, int *h_errnop
);
340 struct nwrap_module_nss_fns
{
341 NSS_STATUS (*_nss_getpwnam_r
)(const char *name
, struct passwd
*result
, char *buffer
,
342 size_t buflen
, int *errnop
);
343 NSS_STATUS (*_nss_getpwuid_r
)(uid_t uid
, struct passwd
*result
, char *buffer
,
344 size_t buflen
, int *errnop
);
345 NSS_STATUS (*_nss_setpwent
)(void);
346 NSS_STATUS (*_nss_getpwent_r
)(struct passwd
*result
, char *buffer
,
347 size_t buflen
, int *errnop
);
348 NSS_STATUS (*_nss_endpwent
)(void);
349 NSS_STATUS (*_nss_initgroups
)(const char *user
, gid_t group
, long int *start
,
350 long int *size
, gid_t
**groups
, long int limit
, int *errnop
);
351 NSS_STATUS (*_nss_getgrnam_r
)(const char *name
, struct group
*result
, char *buffer
,
352 size_t buflen
, int *errnop
);
353 NSS_STATUS (*_nss_getgrgid_r
)(gid_t gid
, struct group
*result
, char *buffer
,
354 size_t buflen
, int *errnop
);
355 NSS_STATUS (*_nss_setgrent
)(void);
356 NSS_STATUS (*_nss_getgrent_r
)(struct group
*result
, char *buffer
,
357 size_t buflen
, int *errnop
);
358 NSS_STATUS (*_nss_endgrent
)(void);
361 struct nwrap_backend
{
365 struct nwrap_ops
*ops
;
366 struct nwrap_module_nss_fns
*fns
;
370 struct passwd
* (*nw_getpwnam
)(struct nwrap_backend
*b
,
372 int (*nw_getpwnam_r
)(struct nwrap_backend
*b
,
373 const char *name
, struct passwd
*pwdst
,
374 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
375 struct passwd
* (*nw_getpwuid
)(struct nwrap_backend
*b
,
377 int (*nw_getpwuid_r
)(struct nwrap_backend
*b
,
378 uid_t uid
, struct passwd
*pwdst
,
379 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
380 void (*nw_setpwent
)(struct nwrap_backend
*b
);
381 struct passwd
* (*nw_getpwent
)(struct nwrap_backend
*b
);
382 int (*nw_getpwent_r
)(struct nwrap_backend
*b
,
383 struct passwd
*pwdst
, char *buf
,
384 size_t buflen
, struct passwd
**pwdstp
);
385 void (*nw_endpwent
)(struct nwrap_backend
*b
);
386 int (*nw_initgroups
)(struct nwrap_backend
*b
,
387 const char *user
, gid_t group
);
388 struct group
* (*nw_getgrnam
)(struct nwrap_backend
*b
,
390 int (*nw_getgrnam_r
)(struct nwrap_backend
*b
,
391 const char *name
, struct group
*grdst
,
392 char *buf
, size_t buflen
, struct group
**grdstp
);
393 struct group
* (*nw_getgrgid
)(struct nwrap_backend
*b
,
395 int (*nw_getgrgid_r
)(struct nwrap_backend
*b
,
396 gid_t gid
, struct group
*grdst
,
397 char *buf
, size_t buflen
, struct group
**grdstp
);
398 void (*nw_setgrent
)(struct nwrap_backend
*b
);
399 struct group
* (*nw_getgrent
)(struct nwrap_backend
*b
);
400 int (*nw_getgrent_r
)(struct nwrap_backend
*b
,
401 struct group
*grdst
, char *buf
,
402 size_t buflen
, struct group
**grdstp
);
403 void (*nw_endgrent
)(struct nwrap_backend
*b
);
406 /* Public prototypes */
408 bool nss_wrapper_enabled(void);
409 bool nss_wrapper_shadow_enabled(void);
410 bool nss_wrapper_hosts_enabled(void);
412 /* prototypes for files backend */
415 static struct passwd
*nwrap_files_getpwnam(struct nwrap_backend
*b
,
417 static int nwrap_files_getpwnam_r(struct nwrap_backend
*b
,
418 const char *name
, struct passwd
*pwdst
,
419 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
420 static struct passwd
*nwrap_files_getpwuid(struct nwrap_backend
*b
,
422 static int nwrap_files_getpwuid_r(struct nwrap_backend
*b
,
423 uid_t uid
, struct passwd
*pwdst
,
424 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
425 static void nwrap_files_setpwent(struct nwrap_backend
*b
);
426 static struct passwd
*nwrap_files_getpwent(struct nwrap_backend
*b
);
427 static int nwrap_files_getpwent_r(struct nwrap_backend
*b
,
428 struct passwd
*pwdst
, char *buf
,
429 size_t buflen
, struct passwd
**pwdstp
);
430 static void nwrap_files_endpwent(struct nwrap_backend
*b
);
431 static int nwrap_files_initgroups(struct nwrap_backend
*b
,
432 const char *user
, gid_t group
);
433 static struct group
*nwrap_files_getgrnam(struct nwrap_backend
*b
,
435 static int nwrap_files_getgrnam_r(struct nwrap_backend
*b
,
436 const char *name
, struct group
*grdst
,
437 char *buf
, size_t buflen
, struct group
**grdstp
);
438 static struct group
*nwrap_files_getgrgid(struct nwrap_backend
*b
,
440 static int nwrap_files_getgrgid_r(struct nwrap_backend
*b
,
441 gid_t gid
, struct group
*grdst
,
442 char *buf
, size_t buflen
, struct group
**grdstp
);
443 static void nwrap_files_setgrent(struct nwrap_backend
*b
);
444 static struct group
*nwrap_files_getgrent(struct nwrap_backend
*b
);
445 static int nwrap_files_getgrent_r(struct nwrap_backend
*b
,
446 struct group
*grdst
, char *buf
,
447 size_t buflen
, struct group
**grdstp
);
448 static void nwrap_files_endgrent(struct nwrap_backend
*b
);
450 /* prototypes for module backend */
452 static struct passwd
*nwrap_module_getpwent(struct nwrap_backend
*b
);
453 static int nwrap_module_getpwent_r(struct nwrap_backend
*b
,
454 struct passwd
*pwdst
, char *buf
,
455 size_t buflen
, struct passwd
**pwdstp
);
456 static struct passwd
*nwrap_module_getpwnam(struct nwrap_backend
*b
,
458 static int nwrap_module_getpwnam_r(struct nwrap_backend
*b
,
459 const char *name
, struct passwd
*pwdst
,
460 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
461 static struct passwd
*nwrap_module_getpwuid(struct nwrap_backend
*b
,
463 static int nwrap_module_getpwuid_r(struct nwrap_backend
*b
,
464 uid_t uid
, struct passwd
*pwdst
,
465 char *buf
, size_t buflen
, struct passwd
**pwdstp
);
466 static void nwrap_module_setpwent(struct nwrap_backend
*b
);
467 static void nwrap_module_endpwent(struct nwrap_backend
*b
);
468 static struct group
*nwrap_module_getgrent(struct nwrap_backend
*b
);
469 static int nwrap_module_getgrent_r(struct nwrap_backend
*b
,
470 struct group
*grdst
, char *buf
,
471 size_t buflen
, struct group
**grdstp
);
472 static struct group
*nwrap_module_getgrnam(struct nwrap_backend
*b
,
474 static int nwrap_module_getgrnam_r(struct nwrap_backend
*b
,
475 const char *name
, struct group
*grdst
,
476 char *buf
, size_t buflen
, struct group
**grdstp
);
477 static struct group
*nwrap_module_getgrgid(struct nwrap_backend
*b
,
479 static int nwrap_module_getgrgid_r(struct nwrap_backend
*b
,
480 gid_t gid
, struct group
*grdst
,
481 char *buf
, size_t buflen
, struct group
**grdstp
);
482 static void nwrap_module_setgrent(struct nwrap_backend
*b
);
483 static void nwrap_module_endgrent(struct nwrap_backend
*b
);
484 static int nwrap_module_initgroups(struct nwrap_backend
*b
,
485 const char *user
, gid_t group
);
487 struct nwrap_ops nwrap_files_ops
= {
488 .nw_getpwnam
= nwrap_files_getpwnam
,
489 .nw_getpwnam_r
= nwrap_files_getpwnam_r
,
490 .nw_getpwuid
= nwrap_files_getpwuid
,
491 .nw_getpwuid_r
= nwrap_files_getpwuid_r
,
492 .nw_setpwent
= nwrap_files_setpwent
,
493 .nw_getpwent
= nwrap_files_getpwent
,
494 .nw_getpwent_r
= nwrap_files_getpwent_r
,
495 .nw_endpwent
= nwrap_files_endpwent
,
496 .nw_initgroups
= nwrap_files_initgroups
,
497 .nw_getgrnam
= nwrap_files_getgrnam
,
498 .nw_getgrnam_r
= nwrap_files_getgrnam_r
,
499 .nw_getgrgid
= nwrap_files_getgrgid
,
500 .nw_getgrgid_r
= nwrap_files_getgrgid_r
,
501 .nw_setgrent
= nwrap_files_setgrent
,
502 .nw_getgrent
= nwrap_files_getgrent
,
503 .nw_getgrent_r
= nwrap_files_getgrent_r
,
504 .nw_endgrent
= nwrap_files_endgrent
,
507 struct nwrap_ops nwrap_module_ops
= {
508 .nw_getpwnam
= nwrap_module_getpwnam
,
509 .nw_getpwnam_r
= nwrap_module_getpwnam_r
,
510 .nw_getpwuid
= nwrap_module_getpwuid
,
511 .nw_getpwuid_r
= nwrap_module_getpwuid_r
,
512 .nw_setpwent
= nwrap_module_setpwent
,
513 .nw_getpwent
= nwrap_module_getpwent
,
514 .nw_getpwent_r
= nwrap_module_getpwent_r
,
515 .nw_endpwent
= nwrap_module_endpwent
,
516 .nw_initgroups
= nwrap_module_initgroups
,
517 .nw_getgrnam
= nwrap_module_getgrnam
,
518 .nw_getgrnam_r
= nwrap_module_getgrnam_r
,
519 .nw_getgrgid
= nwrap_module_getgrgid
,
520 .nw_getgrgid_r
= nwrap_module_getgrgid_r
,
521 .nw_setgrent
= nwrap_module_setgrent
,
522 .nw_getgrent
= nwrap_module_getgrent
,
523 .nw_getgrent_r
= nwrap_module_getgrent_r
,
524 .nw_endgrent
= nwrap_module_endgrent
,
531 struct nwrap_libc_fns
*fns
;
536 struct nwrap_backend
*backends
;
537 struct nwrap_libc
*libc
;
540 static struct nwrap_main
*nwrap_main_global
;
541 static struct nwrap_main __nwrap_main_global
;
546 static int nwrap_convert_he_ai(const struct hostent
*he
,
548 const struct addrinfo
*hints
,
549 struct addrinfo
**pai
,
550 bool skip_canonname
);
556 #define DEFAULT_VECTOR_CAPACITY 16
558 struct nwrap_vector
{
564 /* Macro returns pointer to first element of vector->items array.
566 * nwrap_vector is used as a memory backend which take care of
567 * memory allocations and other stuff like memory growing.
568 * nwrap_vectors should not be considered as some abstract structures.
569 * On this level, vectors are more handy than direct realloc/malloc
572 * nwrap_vector->items is array inside nwrap_vector which can be
573 * directly pointed by libc structure assembled by cwrap itself.
577 * 1) struct hostent contains char **h_addr_list element.
578 * 2) nwrap_vector holds array of pointers to addresses.
579 * It's easier to use vector to store results of
582 * Now, pretend that cwrap assembled struct hostent and
583 * we need to set h_addr_list to point to nwrap_vector.
584 * Idea behind is to shield users from internal nwrap_vector
586 * (Yes, not fully - array terminated by NULL is needed because
587 * it's result expected by libc function caller.)
593 * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
594 * ... don't care about failed allocation now ...
596 * ... fill nwrap vector ...
599 * he.h_addr_list = nwrap_vector_head(vector);
602 #define nwrap_vector_head(vect) ((void *)((vect)->items))
604 #define nwrap_vector_foreach(item, vect, iter) \
605 for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
607 (item) = (vect).items[++iter])
609 #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
611 static inline bool nwrap_vector_init(struct nwrap_vector
*const vector
)
613 if (vector
== NULL
) {
617 /* count is initialized by ZERO_STRUCTP */
618 ZERO_STRUCTP(vector
);
619 vector
->items
= malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY
+ 1));
620 if (vector
->items
== NULL
) {
623 vector
->capacity
= DEFAULT_VECTOR_CAPACITY
;
624 memset(vector
->items
, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY
+ 1));
629 static bool nwrap_vector_add_item(struct nwrap_vector
*vector
, void *const item
)
631 assert (vector
!= NULL
);
633 if (vector
->items
== NULL
) {
634 nwrap_vector_init(vector
);
637 if (vector
->count
== vector
->capacity
) {
638 /* Items array _MUST_ be NULL terminated because it's passed
639 * as result to caller which expect NULL terminated array from libc.
641 void **items
= realloc(vector
->items
, sizeof(void *) * ((vector
->capacity
* 2) + 1));
645 vector
->items
= items
;
647 /* Don't count ending NULL to capacity */
648 vector
->capacity
*= 2;
651 vector
->items
[vector
->count
] = item
;
654 vector
->items
[vector
->count
] = NULL
;
659 static bool nwrap_vector_merge(struct nwrap_vector
*dst
,
660 struct nwrap_vector
*src
)
662 void **dst_items
= NULL
;
665 if (src
->count
== 0) {
669 count
= dst
->count
+ src
->count
;
671 /* We don't need reallocation if we have enough capacity. */
672 if (src
->count
> (dst
->capacity
- dst
->count
)) {
673 dst_items
= (void **)realloc(dst
->items
, (count
+ 1) * sizeof(void *));
674 if (dst_items
== NULL
) {
677 dst
->items
= dst_items
;
678 dst
->capacity
= count
;
681 memcpy((void *)(((long *)dst
->items
) + dst
->count
),
683 src
->count
* sizeof(void *));
696 struct nwrap_vector lines
;
698 bool (*parse_line
)(struct nwrap_cache
*, char *line
);
699 void (*unload
)(struct nwrap_cache
*);
704 struct nwrap_cache
*cache
;
711 struct nwrap_cache __nwrap_cache_pw
;
712 struct nwrap_pw nwrap_pw_global
;
714 static bool nwrap_pw_parse_line(struct nwrap_cache
*nwrap
, char *line
);
715 static void nwrap_pw_unload(struct nwrap_cache
*nwrap
);
718 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
720 struct nwrap_cache
*cache
;
727 struct nwrap_cache __nwrap_cache_sp
;
728 struct nwrap_sp nwrap_sp_global
;
730 static bool nwrap_sp_parse_line(struct nwrap_cache
*nwrap
, char *line
);
731 static void nwrap_sp_unload(struct nwrap_cache
*nwrap
);
732 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
736 struct nwrap_cache
*cache
;
743 struct nwrap_cache __nwrap_cache_gr
;
744 struct nwrap_gr nwrap_gr_global
;
747 static bool nwrap_he_parse_line(struct nwrap_cache
*nwrap
, char *line
);
748 static void nwrap_he_unload(struct nwrap_cache
*nwrap
);
750 struct nwrap_addrdata
{
751 unsigned char host_addr
[16]; /* IPv4 or IPv6 address */
754 static size_t max_hostents
= 100;
756 struct nwrap_entdata
{
757 struct nwrap_addrdata addr
;
760 struct nwrap_vector nwrap_addrdata
;
762 ssize_t aliases_count
;
765 struct nwrap_entlist
{
766 struct nwrap_entlist
*next
;
767 struct nwrap_entdata
*ed
;
771 struct nwrap_cache
*cache
;
773 struct nwrap_vector entries
;
774 struct nwrap_vector lists
;
780 static struct nwrap_cache __nwrap_cache_he
;
781 static struct nwrap_he nwrap_he_global
;
784 /*********************************************************
786 *********************************************************/
788 static void nwrap_init(void);
789 static bool nwrap_gr_parse_line(struct nwrap_cache
*nwrap
, char *line
);
790 static void nwrap_gr_unload(struct nwrap_cache
*nwrap
);
791 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE
;
793 /*********************************************************
794 * NWRAP LIBC LOADER FUNCTIONS
795 *********************************************************/
804 static const char *nwrap_str_lib(enum nwrap_lib lib
)
811 case NWRAP_LIBSOCKET
:
815 /* Compiler would warn us about unhandled enum value if we get here */
820 static void *nwrap_load_lib_handle(enum nwrap_lib lib
)
822 int flags
= RTLD_LAZY
;
827 flags
|= RTLD_DEEPBIND
;
833 handle
= nwrap_main_global
->libc
->nsl_handle
;
834 if (handle
== NULL
) {
835 for (i
= 10; i
>= 0; i
--) {
836 char soname
[256] = {0};
838 snprintf(soname
, sizeof(soname
), "libnsl.so.%d", i
);
839 handle
= dlopen(soname
, flags
);
840 if (handle
!= NULL
) {
845 nwrap_main_global
->libc
->nsl_handle
= handle
;
850 case NWRAP_LIBSOCKET
:
851 #ifdef HAVE_LIBSOCKET
852 handle
= nwrap_main_global
->libc
->sock_handle
;
853 if (handle
== NULL
) {
854 for (i
= 10; i
>= 0; i
--) {
855 char soname
[256] = {0};
857 snprintf(soname
, sizeof(soname
), "libsocket.so.%d", i
);
858 handle
= dlopen(soname
, flags
);
859 if (handle
!= NULL
) {
864 nwrap_main_global
->libc
->sock_handle
= handle
;
870 handle
= nwrap_main_global
->libc
->handle
;
871 if (handle
== NULL
) {
872 for (i
= 10; i
>= 0; i
--) {
873 char soname
[256] = {0};
875 snprintf(soname
, sizeof(soname
), "libc.so.%d", i
);
876 handle
= dlopen(soname
, flags
);
877 if (handle
!= NULL
) {
882 nwrap_main_global
->libc
->handle
= handle
;
887 if (handle
== NULL
) {
889 handle
= nwrap_main_global
->libc
->handle
890 = nwrap_main_global
->libc
->sock_handle
891 = nwrap_main_global
->libc
->nsl_handle
894 NWRAP_LOG(NWRAP_LOG_ERROR
,
895 "Failed to dlopen library: %s\n",
904 static void *_nwrap_load_lib_function(enum nwrap_lib lib
, const char *fn_name
)
911 handle
= nwrap_load_lib_handle(lib
);
913 func
= dlsym(handle
, fn_name
);
915 NWRAP_LOG(NWRAP_LOG_ERROR
,
916 "Failed to find %s: %s\n",
921 NWRAP_LOG(NWRAP_LOG_TRACE
,
923 fn_name
, nwrap_str_lib(lib
));
927 #define nwrap_load_lib_function(lib, fn_name) \
928 if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
929 *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
930 _nwrap_load_lib_function(lib, #fn_name); \
933 /* INTERNAL HELPER FUNCTIONS */
934 static void nwrap_lines_unload(struct nwrap_cache
*const nwrap
)
938 nwrap_vector_foreach(item
, nwrap
->lines
, p
) {
939 /* Maybe some vectors were merged ... */
942 SAFE_FREE(nwrap
->lines
.items
);
943 ZERO_STRUCTP(&nwrap
->lines
);
949 * Functions expeciall from libc need to be loaded individually, you can't load
950 * all at once or gdb will segfault at startup. The same applies to valgrind and
951 * has probably something todo with with the linker.
952 * So we need load each function at the point it is called the first time.
954 static struct passwd
*libc_getpwnam(const char *name
)
956 nwrap_load_lib_function(NWRAP_LIBC
, getpwnam
);
958 return nwrap_main_global
->libc
->fns
->_libc_getpwnam(name
);
961 #ifdef HAVE_GETPWNAM_R
962 static int libc_getpwnam_r(const char *name
,
966 struct passwd
**result
)
968 #ifdef HAVE___POSIX_GETPWNAM_R
969 if (nwrap_main_global
->libc
->fns
->_libc_getpwnam_r
== NULL
) {
970 *(void **) (&nwrap_main_global
->libc
->fns
->_libc_getpwnam_r
) =
971 _nwrap_load_lib_function(NWRAP_LIBC
, "__posix_getpwnam_r");
974 nwrap_load_lib_function(NWRAP_LIBC
, getpwnam_r
);
977 return nwrap_main_global
->libc
->fns
->_libc_getpwnam_r(name
,
985 static struct passwd
*libc_getpwuid(uid_t uid
)
987 nwrap_load_lib_function(NWRAP_LIBC
, getpwuid
);
989 return nwrap_main_global
->libc
->fns
->_libc_getpwuid(uid
);
992 #ifdef HAVE_GETPWUID_R
993 static int libc_getpwuid_r(uid_t uid
,
997 struct passwd
**result
)
999 #ifdef HAVE___POSIX_GETPWUID_R
1000 if (nwrap_main_global
->libc
->fns
->_libc_getpwuid_r
== NULL
) {
1001 *(void **) (&nwrap_main_global
->libc
->fns
->_libc_getpwuid_r
) =
1002 _nwrap_load_lib_function(NWRAP_LIBC
, "__posix_getpwuid_r");
1005 nwrap_load_lib_function(NWRAP_LIBC
, getpwuid_r
);
1008 return nwrap_main_global
->libc
->fns
->_libc_getpwuid_r(uid
,
1016 static inline void str_tolower(char *dst
, char *src
)
1018 register char *src_tmp
= src
;
1019 register char *dst_tmp
= dst
;
1021 while (*src_tmp
!= '\0') {
1022 *dst_tmp
= tolower(*src_tmp
);
1028 static bool str_tolower_copy(char **dst_name
, const char *const src_name
)
1032 if ((dst_name
== NULL
) || (src_name
== NULL
)) {
1036 h_name_lower
= strdup(src_name
);
1037 if (h_name_lower
== NULL
) {
1038 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Out of memory while strdup");
1042 str_tolower(h_name_lower
, h_name_lower
);
1043 *dst_name
= h_name_lower
;
1047 static void libc_setpwent(void)
1049 nwrap_load_lib_function(NWRAP_LIBC
, setpwent
);
1051 nwrap_main_global
->libc
->fns
->_libc_setpwent();
1054 static struct passwd
*libc_getpwent(void)
1056 nwrap_load_lib_function(NWRAP_LIBC
, getpwent
);
1058 return nwrap_main_global
->libc
->fns
->_libc_getpwent();
1061 #ifdef HAVE_SOLARIS_GETPWENT_R
1062 static struct passwd
*libc_getpwent_r(struct passwd
*pwdst
,
1066 nwrap_load_lib_function(NWRAP_LIBC
, getpwent_r
);
1068 return nwrap_main_global
->libc
->fns
->_libc_getpwent_r(pwdst
,
1072 #else /* HAVE_SOLARIS_GETPWENT_R */
1073 static int libc_getpwent_r(struct passwd
*pwdst
,
1076 struct passwd
**pwdstp
)
1078 nwrap_load_lib_function(NWRAP_LIBC
, getpwent_r
);
1080 return nwrap_main_global
->libc
->fns
->_libc_getpwent_r(pwdst
,
1085 #endif /* HAVE_SOLARIS_GETPWENT_R */
1087 static void libc_endpwent(void)
1089 nwrap_load_lib_function(NWRAP_LIBC
, endpwent
);
1091 nwrap_main_global
->libc
->fns
->_libc_endpwent();
1094 static int libc_initgroups(const char *user
, gid_t gid
)
1096 nwrap_load_lib_function(NWRAP_LIBC
, initgroups
);
1098 return nwrap_main_global
->libc
->fns
->_libc_initgroups(user
, gid
);
1101 static struct group
*libc_getgrnam(const char *name
)
1103 nwrap_load_lib_function(NWRAP_LIBC
, getgrnam
);
1105 return nwrap_main_global
->libc
->fns
->_libc_getgrnam(name
);
1108 #ifdef HAVE_GETGRNAM_R
1109 static int libc_getgrnam_r(const char *name
,
1113 struct group
**result
)
1115 #ifdef HAVE___POSIX_GETGRNAM_R
1116 if (nwrap_main_global
->libc
->fns
->_libc_getgrnam_r
== NULL
) {
1117 *(void **) (&nwrap_main_global
->libc
->fns
->_libc_getgrnam_r
) =
1118 _nwrap_load_lib_function(NWRAP_LIBC
, "__posix_getgrnam_r");
1121 nwrap_load_lib_function(NWRAP_LIBC
, getgrnam_r
);
1124 return nwrap_main_global
->libc
->fns
->_libc_getgrnam_r(name
,
1132 static struct group
*libc_getgrgid(gid_t gid
)
1134 nwrap_load_lib_function(NWRAP_LIBC
, getgrgid
);
1136 return nwrap_main_global
->libc
->fns
->_libc_getgrgid(gid
);
1139 #ifdef HAVE_GETGRGID_R
1140 static int libc_getgrgid_r(gid_t gid
,
1144 struct group
**result
)
1146 #ifdef HAVE___POSIX_GETGRGID_R
1147 if (nwrap_main_global
->libc
->fns
->_libc_getgrgid_r
== NULL
) {
1148 *(void **) (&nwrap_main_global
->libc
->fns
->_libc_getgrgid_r
) =
1149 _nwrap_load_lib_function(NWRAP_LIBC
, "__posix_getgrgid_r");
1152 nwrap_load_lib_function(NWRAP_LIBC
, getgrgid_r
);
1155 return nwrap_main_global
->libc
->fns
->_libc_getgrgid_r(gid
,
1163 static void libc_setgrent(void)
1165 nwrap_load_lib_function(NWRAP_LIBC
, setgrent
);
1167 nwrap_main_global
->libc
->fns
->_libc_setgrent();
1170 static struct group
*libc_getgrent(void)
1172 nwrap_load_lib_function(NWRAP_LIBC
, getgrent
);
1174 return nwrap_main_global
->libc
->fns
->_libc_getgrent();
1177 #ifdef HAVE_GETGRENT_R
1178 #ifdef HAVE_SOLARIS_GETGRENT_R
1179 static struct group
*libc_getgrent_r(struct group
*group
,
1183 nwrap_load_lib_function(NWRAP_LIBC
, getgrent_r
);
1185 return nwrap_main_global
->libc
->fns
->_libc_getgrent_r(group
,
1189 #else /* !HAVE_SOLARIS_GETGRENT_R */
1190 static int libc_getgrent_r(struct group
*group
,
1193 struct group
**result
)
1195 nwrap_load_lib_function(NWRAP_LIBC
, getgrent_r
);
1197 return nwrap_main_global
->libc
->fns
->_libc_getgrent_r(group
,
1202 #endif /* HAVE_SOLARIS_GETGRENT_R */
1203 #endif /* HAVE_GETGRENT_R */
1205 static void libc_endgrent(void)
1207 nwrap_load_lib_function(NWRAP_LIBC
, endgrent
);
1209 nwrap_main_global
->libc
->fns
->_libc_endgrent();
1212 #ifdef HAVE_GETGROUPLIST
1213 static int libc_getgrouplist(const char *user
,
1218 nwrap_load_lib_function(NWRAP_LIBC
, getgrouplist
);
1220 return nwrap_main_global
->libc
->fns
->_libc_getgrouplist(user
,
1227 static void libc_sethostent(int stayopen
)
1229 nwrap_load_lib_function(NWRAP_LIBNSL
, sethostent
);
1231 nwrap_main_global
->libc
->fns
->_libc_sethostent(stayopen
);
1234 static struct hostent
*libc_gethostent(void)
1236 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostent
);
1238 return nwrap_main_global
->libc
->fns
->_libc_gethostent();
1241 static void libc_endhostent(void)
1243 nwrap_load_lib_function(NWRAP_LIBNSL
, endhostent
);
1245 nwrap_main_global
->libc
->fns
->_libc_endhostent();
1248 static struct hostent
*libc_gethostbyname(const char *name
)
1250 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostbyname
);
1252 return nwrap_main_global
->libc
->fns
->_libc_gethostbyname(name
);
1255 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
1256 static struct hostent
*libc_gethostbyname2(const char *name
, int af
)
1258 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostbyname2
);
1260 return nwrap_main_global
->libc
->fns
->_libc_gethostbyname2(name
, af
);
1264 static struct hostent
*libc_gethostbyaddr(const void *addr
,
1268 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostbyaddr
);
1270 return nwrap_main_global
->libc
->fns
->_libc_gethostbyaddr(addr
,
1275 static int libc_gethostname(char *name
, size_t len
)
1277 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostname
);
1279 return nwrap_main_global
->libc
->fns
->_libc_gethostname(name
, len
);
1282 #ifdef HAVE_GETHOSTBYNAME_R
1283 static int libc_gethostbyname_r(const char *name
,
1284 struct hostent
*ret
,
1287 struct hostent
**result
,
1290 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostbyname_r
);
1292 return nwrap_main_global
->libc
->fns
->_libc_gethostbyname_r(name
,
1301 #ifdef HAVE_GETHOSTBYADDR_R
1302 static int libc_gethostbyaddr_r(const void *addr
,
1305 struct hostent
*ret
,
1308 struct hostent
**result
,
1311 nwrap_load_lib_function(NWRAP_LIBNSL
, gethostbyaddr_r
);
1313 return nwrap_main_global
->libc
->fns
->_libc_gethostbyaddr_r(addr
,
1324 static int libc_getaddrinfo(const char *node
,
1325 const char *service
,
1326 const struct addrinfo
*hints
,
1327 struct addrinfo
**res
)
1329 nwrap_load_lib_function(NWRAP_LIBSOCKET
, getaddrinfo
);
1331 return nwrap_main_global
->libc
->fns
->_libc_getaddrinfo(node
,
1337 static int libc_getnameinfo(const struct sockaddr
*sa
,
1345 nwrap_load_lib_function(NWRAP_LIBSOCKET
, getnameinfo
);
1347 return nwrap_main_global
->libc
->fns
->_libc_getnameinfo(sa
,
1356 /*********************************************************
1357 * NWRAP NSS MODULE LOADER FUNCTIONS
1358 *********************************************************/
1360 static void *nwrap_load_module_fn(struct nwrap_backend
*b
,
1361 const char *fn_name
)
1366 if (!b
->so_handle
) {
1367 NWRAP_LOG(NWRAP_LOG_ERROR
, "No handle");
1371 if (asprintf(&s
, "_nss_%s_%s", b
->name
, fn_name
) == -1) {
1372 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
1376 res
= dlsym(b
->so_handle
, s
);
1378 NWRAP_LOG(NWRAP_LOG_ERROR
,
1379 "Cannot find function %s in %s",
1386 static struct nwrap_module_nss_fns
*nwrap_load_module_fns(struct nwrap_backend
*b
)
1388 struct nwrap_module_nss_fns
*fns
;
1390 if (!b
->so_handle
) {
1394 fns
= (struct nwrap_module_nss_fns
*)malloc(sizeof(struct nwrap_module_nss_fns
));
1399 *(void **)(&fns
->_nss_getpwnam_r
) =
1400 nwrap_load_module_fn(b
, "getpwnam_r");
1401 *(void **)(&fns
->_nss_getpwuid_r
) =
1402 nwrap_load_module_fn(b
, "getpwuid_r");
1403 *(void **)(&fns
->_nss_setpwent
) =
1404 nwrap_load_module_fn(b
, "setpwent");
1405 *(void **)(&fns
->_nss_getpwent_r
) =
1406 nwrap_load_module_fn(b
, "getpwent_r");
1407 *(void **)(&fns
->_nss_endpwent
) =
1408 nwrap_load_module_fn(b
, "endpwent");
1409 *(void **)(&fns
->_nss_initgroups
) =
1410 nwrap_load_module_fn(b
, "initgroups_dyn");
1411 *(void **)(&fns
->_nss_getgrnam_r
) =
1412 nwrap_load_module_fn(b
, "getgrnam_r");
1413 *(void **)(&fns
->_nss_getgrgid_r
)=
1414 nwrap_load_module_fn(b
, "getgrgid_r");
1415 *(void **)(&fns
->_nss_setgrent
) =
1416 nwrap_load_module_fn(b
, "setgrent");
1417 *(void **)(&fns
->_nss_getgrent_r
) =
1418 nwrap_load_module_fn(b
, "getgrent_r");
1419 *(void **)(&fns
->_nss_endgrent
) =
1420 nwrap_load_module_fn(b
, "endgrent");
1425 static void *nwrap_load_module(const char *so_path
)
1429 if (!so_path
|| !strlen(so_path
)) {
1433 h
= dlopen(so_path
, RTLD_LAZY
);
1435 NWRAP_LOG(NWRAP_LOG_ERROR
,
1436 "Cannot open shared library %s",
1444 static bool nwrap_module_init(const char *name
,
1445 struct nwrap_ops
*ops
,
1446 const char *so_path
,
1448 struct nwrap_backend
**backends
)
1450 struct nwrap_backend
*b
;
1452 *backends
= (struct nwrap_backend
*)realloc(*backends
,
1453 sizeof(struct nwrap_backend
) * ((*num_backends
) + 1));
1455 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
1459 b
= &((*backends
)[*num_backends
]);
1463 b
->so_path
= so_path
;
1465 if (so_path
!= NULL
) {
1466 b
->so_handle
= nwrap_load_module(so_path
);
1467 b
->fns
= nwrap_load_module_fns(b
);
1468 if (b
->fns
== NULL
) {
1472 b
->so_handle
= NULL
;
1481 static void nwrap_libc_init(struct nwrap_main
*r
)
1483 r
->libc
= malloc(sizeof(struct nwrap_libc
));
1484 if (r
->libc
== NULL
) {
1485 printf("Failed to allocate memory for libc");
1488 ZERO_STRUCTP(r
->libc
);
1490 r
->libc
->fns
= malloc(sizeof(struct nwrap_libc_fns
));
1491 if (r
->libc
->fns
== NULL
) {
1492 printf("Failed to allocate memory for libc functions");
1495 ZERO_STRUCTP(r
->libc
->fns
);
1498 static void nwrap_backend_init(struct nwrap_main
*r
)
1500 const char *module_so_path
= getenv("NSS_WRAPPER_MODULE_SO_PATH");
1501 const char *module_fn_name
= getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1503 r
->num_backends
= 0;
1506 if (!nwrap_module_init("files", &nwrap_files_ops
, NULL
,
1509 NWRAP_LOG(NWRAP_LOG_ERROR
,
1510 "Failed to initialize 'files' backend");
1514 if (module_so_path
!= NULL
&&
1515 module_so_path
[0] != '\0' &&
1516 module_fn_name
!= NULL
&&
1517 module_fn_name
[0] != '\0') {
1518 if (!nwrap_module_init(module_fn_name
,
1523 NWRAP_LOG(NWRAP_LOG_ERROR
,
1524 "Failed to initialize '%s' backend",
1531 static void nwrap_init(void)
1535 size_t max_hostents_tmp
;
1537 NWRAP_LOCK(nwrap_initialized
);
1538 if (nwrap_initialized
) {
1539 NWRAP_UNLOCK(nwrap_initialized
);
1544 * Still holding nwrap_initialized lock here.
1545 * We don't use NWRAP_(UN)LOCK_ALL macros here because we
1546 * want to avoid overhead when other threads do their job.
1548 NWRAP_LOCK(nwrap_global
);
1549 NWRAP_LOCK(nwrap_gr_global
);
1550 NWRAP_LOCK(nwrap_he_global
);
1551 NWRAP_LOCK(nwrap_pw_global
);
1552 NWRAP_LOCK(nwrap_sp_global
);
1554 nwrap_initialized
= true;
1556 /* Initialize pthread_atfork handlers */
1557 pthread_atfork(&nwrap_thread_prepare
, &nwrap_thread_parent
,
1558 &nwrap_thread_child
);
1560 env
= getenv("NSS_WRAPPER_MAX_HOSTENTS");
1562 max_hostents_tmp
= (size_t)strtol(env
, &endptr
, 10);
1563 if (((env
!= '\0') && (endptr
== '\0')) ||
1564 (max_hostents_tmp
== 0)) {
1565 NWRAP_LOG(NWRAP_LOG_DEBUG
,
1566 "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
1567 "value or value is too small. "
1568 "Using default value: %lu.",
1569 (unsigned long)max_hostents
);
1571 max_hostents
= max_hostents_tmp
;
1574 /* Initialize hash table */
1575 NWRAP_LOG(NWRAP_LOG_DEBUG
,
1576 "Initializing hash table of size %lu items.",
1577 (unsigned long)max_hostents
);
1578 if (hcreate(max_hostents
) == 0) {
1579 NWRAP_LOG(NWRAP_LOG_ERROR
,
1580 "Failed to initialize hash table");
1584 nwrap_main_global
= &__nwrap_main_global
;
1586 nwrap_libc_init(nwrap_main_global
);
1588 nwrap_backend_init(nwrap_main_global
);
1591 nwrap_pw_global
.cache
= &__nwrap_cache_pw
;
1593 nwrap_pw_global
.cache
->path
= getenv("NSS_WRAPPER_PASSWD");
1594 nwrap_pw_global
.cache
->fp
= NULL
;
1595 nwrap_pw_global
.cache
->fd
= -1;
1596 nwrap_pw_global
.cache
->private_data
= &nwrap_pw_global
;
1597 nwrap_pw_global
.cache
->parse_line
= nwrap_pw_parse_line
;
1598 nwrap_pw_global
.cache
->unload
= nwrap_pw_unload
;
1601 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1602 nwrap_sp_global
.cache
= &__nwrap_cache_sp
;
1604 nwrap_sp_global
.cache
->path
= getenv("NSS_WRAPPER_SHADOW");
1605 nwrap_sp_global
.cache
->fp
= NULL
;
1606 nwrap_sp_global
.cache
->fd
= -1;
1607 nwrap_sp_global
.cache
->private_data
= &nwrap_sp_global
;
1608 nwrap_sp_global
.cache
->parse_line
= nwrap_sp_parse_line
;
1609 nwrap_sp_global
.cache
->unload
= nwrap_sp_unload
;
1610 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1613 nwrap_gr_global
.cache
= &__nwrap_cache_gr
;
1615 nwrap_gr_global
.cache
->path
= getenv("NSS_WRAPPER_GROUP");
1616 nwrap_gr_global
.cache
->fp
= NULL
;
1617 nwrap_gr_global
.cache
->fd
= -1;
1618 nwrap_gr_global
.cache
->private_data
= &nwrap_gr_global
;
1619 nwrap_gr_global
.cache
->parse_line
= nwrap_gr_parse_line
;
1620 nwrap_gr_global
.cache
->unload
= nwrap_gr_unload
;
1623 nwrap_he_global
.cache
= &__nwrap_cache_he
;
1625 nwrap_he_global
.cache
->path
= getenv("NSS_WRAPPER_HOSTS");
1626 nwrap_he_global
.cache
->fp
= NULL
;
1627 nwrap_he_global
.cache
->fd
= -1;
1628 nwrap_he_global
.cache
->private_data
= &nwrap_he_global
;
1629 nwrap_he_global
.cache
->parse_line
= nwrap_he_parse_line
;
1630 nwrap_he_global
.cache
->unload
= nwrap_he_unload
;
1633 /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
1637 bool nss_wrapper_enabled(void)
1641 if (nwrap_pw_global
.cache
->path
== NULL
||
1642 nwrap_pw_global
.cache
->path
[0] == '\0') {
1645 if (nwrap_gr_global
.cache
->path
== NULL
||
1646 nwrap_gr_global
.cache
->path
[0] == '\0') {
1653 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
1654 bool nss_wrapper_shadow_enabled(void)
1658 if (nwrap_sp_global
.cache
->path
== NULL
||
1659 nwrap_sp_global
.cache
->path
[0] == '\0') {
1665 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
1667 bool nss_wrapper_hosts_enabled(void)
1671 if (nwrap_he_global
.cache
->path
== NULL
||
1672 nwrap_he_global
.cache
->path
[0] == '\0') {
1679 static bool nwrap_hostname_enabled(void)
1683 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL
) {
1690 static bool nwrap_parse_file(struct nwrap_cache
*nwrap
)
1694 /* Unused but getline needs it */
1698 if (nwrap
->st
.st_size
== 0) {
1699 NWRAP_LOG(NWRAP_LOG_DEBUG
, "size == 0");
1703 /* Support for 32-bit system I guess */
1704 if (nwrap
->st
.st_size
> INT32_MAX
) {
1705 NWRAP_LOG(NWRAP_LOG_ERROR
,
1706 "Size[%u] larger than INT32_MAX",
1707 (unsigned)nwrap
->st
.st_size
);
1714 n
= getline(&line
, &len
, nwrap
->fp
);
1717 if (feof(nwrap
->fp
)) {
1721 NWRAP_LOG(NWRAP_LOG_ERROR
,
1722 "Unable to read line from file: %s",
1727 if (line
[n
- 1] == '\n') {
1731 if (line
[0] == '\0') {
1736 ok
= nwrap
->parse_line(nwrap
, line
);
1738 NWRAP_LOG(NWRAP_LOG_ERROR
,
1739 "Unable to parse line file: %s",
1745 /* Line is parsed without issues so add it to list */
1746 ok
= nwrap_vector_add_item(&(nwrap
->lines
), (void *const) line
);
1748 NWRAP_LOG(NWRAP_LOG_ERROR
,
1749 "Unable to add line to vector");
1753 /* This forces getline to allocate new memory for line. */
1755 } while (!feof(nwrap
->fp
));
1760 static void nwrap_files_cache_unload(struct nwrap_cache
*nwrap
)
1762 nwrap
->unload(nwrap
);
1764 nwrap_lines_unload(nwrap
);
1767 static bool nwrap_files_cache_reload(struct nwrap_cache
*nwrap
)
1772 bool retried
= false;
1774 assert(nwrap
!= NULL
);
1777 if (nwrap
->fd
< 0) {
1778 nwrap
->fp
= fopen(nwrap
->path
, "re");
1779 if (nwrap
->fp
== NULL
) {
1781 NWRAP_LOG(NWRAP_LOG_ERROR
,
1782 "Unable to open '%s' readonly %d:%s",
1783 nwrap
->path
, nwrap
->fd
,
1788 nwrap
->fd
= fileno(nwrap
->fp
);
1789 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Open '%s'", nwrap
->path
);
1792 ret
= fstat(nwrap
->fd
, &st
);
1794 NWRAP_LOG(NWRAP_LOG_ERROR
,
1795 "fstat(%s) - %d:%s",
1805 if (retried
== false && st
.st_nlink
== 0) {
1806 /* maybe someone has replaced the file... */
1807 NWRAP_LOG(NWRAP_LOG_TRACE
,
1808 "st_nlink == 0, reopen %s",
1811 memset(&nwrap
->st
, 0, sizeof(nwrap
->st
));
1818 if (st
.st_mtime
== nwrap
->st
.st_mtime
) {
1819 NWRAP_LOG(NWRAP_LOG_TRACE
,
1820 "st_mtime[%u] hasn't changed, skip reload",
1821 (unsigned)st
.st_mtime
);
1825 NWRAP_LOG(NWRAP_LOG_TRACE
,
1826 "st_mtime has changed [%u] => [%u], start reload",
1827 (unsigned)st
.st_mtime
,
1828 (unsigned)nwrap
->st
.st_mtime
);
1832 nwrap_files_cache_unload(nwrap
);
1834 ok
= nwrap_parse_file(nwrap
);
1836 NWRAP_LOG(NWRAP_LOG_ERROR
, "Failed to reload %s", nwrap
->path
);
1837 nwrap_files_cache_unload(nwrap
);
1841 NWRAP_LOG(NWRAP_LOG_TRACE
, "Reloaded %s", nwrap
->path
);
1846 * the caller has to call nwrap_unload() on failure
1848 static bool nwrap_pw_parse_line(struct nwrap_cache
*nwrap
, char *line
)
1850 struct nwrap_pw
*nwrap_pw
;
1857 nwrap_pw
= (struct nwrap_pw
*)nwrap
->private_data
;
1859 list_size
= sizeof(*nwrap_pw
->list
) * (nwrap_pw
->num
+1);
1860 pw
= (struct passwd
*)realloc(nwrap_pw
->list
, list_size
);
1862 NWRAP_LOG(NWRAP_LOG_ERROR
,
1863 "realloc(%u) failed",
1864 (unsigned)list_size
);
1867 nwrap_pw
->list
= pw
;
1869 pw
= &nwrap_pw
->list
[nwrap_pw
->num
];
1876 NWRAP_LOG(NWRAP_LOG_ERROR
,
1877 "Invalid line[%s]: '%s'",
1887 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]\n", pw
->pw_name
);
1892 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
1900 NWRAP_LOG(NWRAP_LOG_TRACE
, "password[%s]\n", pw
->pw_passwd
);
1905 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
1911 pw
->pw_uid
= (uid_t
)strtoul(c
, &e
, 10);
1913 NWRAP_LOG(NWRAP_LOG_ERROR
,
1914 "Invalid line[%s]: '%s' - %s",
1915 line
, c
, strerror(errno
));
1919 NWRAP_LOG(NWRAP_LOG_ERROR
,
1920 "Invalid line[%s]: '%s' - %s",
1921 line
, c
, strerror(errno
));
1925 NWRAP_LOG(NWRAP_LOG_ERROR
,
1926 "Invalid line[%s]: '%s' - %s",
1927 line
, c
, strerror(errno
));
1932 NWRAP_LOG(NWRAP_LOG_TRACE
, "uid[%u]", pw
->pw_uid
);
1937 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
1943 pw
->pw_gid
= (gid_t
)strtoul(c
, &e
, 10);
1945 NWRAP_LOG(NWRAP_LOG_ERROR
,
1946 "Invalid line[%s]: '%s' - %s",
1947 line
, c
, strerror(errno
));
1951 NWRAP_LOG(NWRAP_LOG_ERROR
,
1952 "Invalid line[%s]: '%s' - %s",
1953 line
, c
, strerror(errno
));
1957 NWRAP_LOG(NWRAP_LOG_ERROR
,
1958 "Invalid line[%s]: '%s' - %s",
1959 line
, c
, strerror(errno
));
1964 NWRAP_LOG(NWRAP_LOG_TRACE
, "gid[%u]\n", pw
->pw_gid
);
1969 NWRAP_LOG(NWRAP_LOG_ERROR
, "invalid line[%s]: '%s'", line
, c
);
1977 NWRAP_LOG(NWRAP_LOG_TRACE
, "gecos[%s]", pw
->pw_gecos
);
1982 NWRAP_LOG(NWRAP_LOG_ERROR
, "'%s'", c
);
1990 NWRAP_LOG(NWRAP_LOG_TRACE
, "dir[%s]", pw
->pw_dir
);
1994 NWRAP_LOG(NWRAP_LOG_TRACE
, "shell[%s]", pw
->pw_shell
);
1996 NWRAP_LOG(NWRAP_LOG_DEBUG
,
1997 "Added user[%s:%s:%u:%u:%s:%s:%s]",
1998 pw
->pw_name
, pw
->pw_passwd
,
1999 pw
->pw_uid
, pw
->pw_gid
,
2000 pw
->pw_gecos
, pw
->pw_dir
, pw
->pw_shell
);
2006 static void nwrap_pw_unload(struct nwrap_cache
*nwrap
)
2008 struct nwrap_pw
*nwrap_pw
;
2009 nwrap_pw
= (struct nwrap_pw
*)nwrap
->private_data
;
2011 SAFE_FREE(nwrap_pw
->list
);
2016 static int nwrap_pw_copy_r(const struct passwd
*src
, struct passwd
*dst
,
2017 char *buf
, size_t buflen
, struct passwd
**dstp
)
2023 first
= src
->pw_name
;
2025 last
= src
->pw_shell
;
2026 while (*last
) last
++;
2028 ofs
= PTR_DIFF(last
+ 1, first
);
2030 if (ofs
> (off_t
) buflen
) {
2034 memcpy(buf
, first
, ofs
);
2036 ofs
= PTR_DIFF(src
->pw_name
, first
);
2037 dst
->pw_name
= buf
+ ofs
;
2038 ofs
= PTR_DIFF(src
->pw_passwd
, first
);
2039 dst
->pw_passwd
= buf
+ ofs
;
2040 dst
->pw_uid
= src
->pw_uid
;
2041 dst
->pw_gid
= src
->pw_gid
;
2042 ofs
= PTR_DIFF(src
->pw_gecos
, first
);
2043 dst
->pw_gecos
= buf
+ ofs
;
2044 ofs
= PTR_DIFF(src
->pw_dir
, first
);
2045 dst
->pw_dir
= buf
+ ofs
;
2046 ofs
= PTR_DIFF(src
->pw_shell
, first
);
2047 dst
->pw_shell
= buf
+ ofs
;
2056 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2057 static bool nwrap_sp_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2059 struct nwrap_sp
*nwrap_sp
;
2066 nwrap_sp
= (struct nwrap_sp
*)nwrap
->private_data
;
2068 list_size
= sizeof(*nwrap_sp
->list
) * (nwrap_sp
->num
+1);
2069 sp
= (struct spwd
*)realloc(nwrap_sp
->list
, list_size
);
2071 NWRAP_LOG(NWRAP_LOG_ERROR
,
2072 "realloc(%u) failed",
2073 (unsigned)list_size
);
2076 nwrap_sp
->list
= sp
;
2078 sp
= &nwrap_sp
->list
[nwrap_sp
->num
];
2085 NWRAP_LOG(NWRAP_LOG_ERROR
,
2086 "name -- Invalid line[%s]: '%s'",
2096 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]\n", sp
->sp_namp
);
2101 NWRAP_LOG(NWRAP_LOG_ERROR
,
2102 "pwd -- Invalid line[%s]: '%s'",
2119 NWRAP_LOG(NWRAP_LOG_ERROR
,
2120 "lstchg -- Invalid line[%s]: '%s'",
2127 sp
->sp_lstchg
= strtol(c
, &e
, 10);
2129 NWRAP_LOG(NWRAP_LOG_ERROR
,
2130 "lstchg -- Invalid line[%s]: '%s' - %s",
2131 line
, c
, strerror(errno
));
2135 NWRAP_LOG(NWRAP_LOG_ERROR
,
2136 "lstchg -- Invalid line[%s]: '%s' - %s",
2137 line
, c
, strerror(errno
));
2141 NWRAP_LOG(NWRAP_LOG_ERROR
,
2142 "lstchg -- Invalid line[%s]: '%s' - %s",
2143 line
, c
, strerror(errno
));
2156 NWRAP_LOG(NWRAP_LOG_ERROR
,
2157 "min -- Invalid line[%s]: '%s'",
2164 sp
->sp_min
= strtol(c
, &e
, 10);
2166 NWRAP_LOG(NWRAP_LOG_ERROR
,
2167 "min -- Invalid line[%s]: '%s' - %s",
2168 line
, c
, strerror(errno
));
2172 NWRAP_LOG(NWRAP_LOG_ERROR
,
2173 "min -- Invalid line[%s]: '%s' - %s",
2174 line
, c
, strerror(errno
));
2178 NWRAP_LOG(NWRAP_LOG_ERROR
,
2179 "min -- Invalid line[%s]: '%s' - %s",
2180 line
, c
, strerror(errno
));
2193 NWRAP_LOG(NWRAP_LOG_ERROR
,
2194 "max -- Invalid line[%s]: '%s'",
2201 sp
->sp_max
= strtol(c
, &e
, 10);
2203 NWRAP_LOG(NWRAP_LOG_ERROR
,
2204 "max -- Invalid line[%s]: '%s' - %s",
2205 line
, c
, strerror(errno
));
2209 NWRAP_LOG(NWRAP_LOG_ERROR
,
2210 "max -- Invalid line[%s]: '%s' - %s",
2211 line
, c
, strerror(errno
));
2215 NWRAP_LOG(NWRAP_LOG_ERROR
,
2216 "max -- Invalid line[%s]: '%s' - %s",
2217 line
, c
, strerror(errno
));
2230 NWRAP_LOG(NWRAP_LOG_ERROR
,
2231 "warn -- Invalid line[%s]: '%s'",
2238 sp
->sp_warn
= strtol(c
, &e
, 10);
2240 NWRAP_LOG(NWRAP_LOG_ERROR
,
2241 "warn -- Invalid line[%s]: '%s' - %s",
2242 line
, c
, strerror(errno
));
2246 NWRAP_LOG(NWRAP_LOG_ERROR
,
2247 "warn -- Invalid line[%s]: '%s' - %s",
2248 line
, c
, strerror(errno
));
2252 NWRAP_LOG(NWRAP_LOG_ERROR
,
2253 "warn -- Invalid line[%s]: '%s' - %s",
2254 line
, c
, strerror(errno
));
2267 NWRAP_LOG(NWRAP_LOG_ERROR
,
2268 "inact -- Invalid line[%s]: '%s'",
2275 sp
->sp_inact
= strtol(c
, &e
, 10);
2277 NWRAP_LOG(NWRAP_LOG_ERROR
,
2278 "inact -- Invalid line[%s]: '%s' - %s",
2279 line
, c
, strerror(errno
));
2283 NWRAP_LOG(NWRAP_LOG_ERROR
,
2284 "inact -- Invalid line[%s]: '%s' - %s",
2285 line
, c
, strerror(errno
));
2289 NWRAP_LOG(NWRAP_LOG_ERROR
,
2290 "inact -- Invalid line[%s]: '%s' - %s",
2291 line
, c
, strerror(errno
));
2304 NWRAP_LOG(NWRAP_LOG_ERROR
,
2305 "expire -- Invalid line[%s]: '%s'",
2312 sp
->sp_expire
= strtol(c
, &e
, 10);
2314 NWRAP_LOG(NWRAP_LOG_ERROR
,
2315 "expire -- Invalid line[%s]: '%s' - %s",
2316 line
, c
, strerror(errno
));
2320 NWRAP_LOG(NWRAP_LOG_ERROR
,
2321 "expire -- Invalid line[%s]: '%s' - %s",
2322 line
, c
, strerror(errno
));
2326 NWRAP_LOG(NWRAP_LOG_ERROR
,
2327 "expire -- Invalid line[%s]: '%s' - %s",
2328 line
, c
, strerror(errno
));
2338 static void nwrap_sp_unload(struct nwrap_cache
*nwrap
)
2340 struct nwrap_sp
*nwrap_sp
;
2341 nwrap_sp
= (struct nwrap_sp
*)nwrap
->private_data
;
2343 SAFE_FREE(nwrap_sp
->list
);
2347 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2350 * the caller has to call nwrap_unload() on failure
2352 static bool nwrap_gr_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2354 struct nwrap_gr
*nwrap_gr
;
2362 nwrap_gr
= (struct nwrap_gr
*)nwrap
->private_data
;
2364 list_size
= sizeof(*nwrap_gr
->list
) * (nwrap_gr
->num
+1);
2365 gr
= (struct group
*)realloc(nwrap_gr
->list
, list_size
);
2367 NWRAP_LOG(NWRAP_LOG_ERROR
, "realloc failed");
2370 nwrap_gr
->list
= gr
;
2372 gr
= &nwrap_gr
->list
[nwrap_gr
->num
];
2379 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2387 NWRAP_LOG(NWRAP_LOG_TRACE
, "name[%s]", gr
->gr_name
);
2392 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2400 NWRAP_LOG(NWRAP_LOG_TRACE
, "password[%s]", gr
->gr_passwd
);
2405 NWRAP_LOG(NWRAP_LOG_ERROR
, "Invalid line[%s]: '%s'", line
, c
);
2411 gr
->gr_gid
= (gid_t
)strtoul(c
, &e
, 10);
2413 NWRAP_LOG(NWRAP_LOG_ERROR
,
2414 "Invalid line[%s]: '%s' - %s",
2415 line
, c
, strerror(errno
));
2419 NWRAP_LOG(NWRAP_LOG_ERROR
,
2420 "Invalid line[%s]: '%s' - %s",
2421 line
, c
, strerror(errno
));
2425 NWRAP_LOG(NWRAP_LOG_ERROR
,
2426 "Invalid line[%s]: '%s' - %s",
2427 line
, c
, strerror(errno
));
2432 NWRAP_LOG(NWRAP_LOG_TRACE
, "gid[%u]", gr
->gr_gid
);
2435 gr
->gr_mem
= (char **)malloc(sizeof(char *));
2437 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
2440 gr
->gr_mem
[0] = NULL
;
2442 for(nummem
=0; p
; nummem
++) {
2452 if (strlen(c
) == 0) {
2456 m_size
= sizeof(char *) * (nummem
+2);
2457 m
= (char **)realloc(gr
->gr_mem
, m_size
);
2459 NWRAP_LOG(NWRAP_LOG_ERROR
,
2460 "realloc(%zd) failed",
2465 gr
->gr_mem
[nummem
] = c
;
2466 gr
->gr_mem
[nummem
+1] = NULL
;
2468 NWRAP_LOG(NWRAP_LOG_TRACE
,
2470 nummem
, gr
->gr_mem
[nummem
]);
2473 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2474 "Added group[%s:%s:%u:] with %u members",
2475 gr
->gr_name
, gr
->gr_passwd
, gr
->gr_gid
, nummem
);
2481 static void nwrap_gr_unload(struct nwrap_cache
*nwrap
)
2484 struct nwrap_gr
*nwrap_gr
;
2485 nwrap_gr
= (struct nwrap_gr
*)nwrap
->private_data
;
2487 if (nwrap_gr
->list
) {
2488 for (i
=0; i
< nwrap_gr
->num
; i
++) {
2489 SAFE_FREE(nwrap_gr
->list
[i
].gr_mem
);
2491 SAFE_FREE(nwrap_gr
->list
);
2498 static int nwrap_gr_copy_r(const struct group
*src
, struct group
*dst
,
2499 char *buf
, size_t buflen
, struct group
**dstp
)
2509 first
= src
->gr_name
;
2511 lastm
= src
->gr_mem
;
2518 last
= src
->gr_passwd
;
2520 while (*last
) last
++;
2522 ofsb
= PTR_DIFF(last
+ 1, first
);
2523 ofsm
= PTR_DIFF(lastm
+ 1, src
->gr_mem
);
2525 if ((ofsb
+ ofsm
) > (off_t
) buflen
) {
2529 memcpy(buf
, first
, ofsb
);
2530 memcpy(buf
+ ofsb
, src
->gr_mem
, ofsm
);
2532 ofs
= PTR_DIFF(src
->gr_name
, first
);
2533 dst
->gr_name
= buf
+ ofs
;
2534 ofs
= PTR_DIFF(src
->gr_passwd
, first
);
2535 dst
->gr_passwd
= buf
+ ofs
;
2536 dst
->gr_gid
= src
->gr_gid
;
2538 dst
->gr_mem
= (char **)(buf
+ ofsb
);
2539 for (i
=0; src
->gr_mem
[i
]; i
++) {
2540 ofs
= PTR_DIFF(src
->gr_mem
[i
], first
);
2541 dst
->gr_mem
[i
] = buf
+ ofs
;
2551 static struct nwrap_entlist
*nwrap_entlist_init(struct nwrap_entdata
*ed
)
2553 struct nwrap_entlist
*el
;
2556 NWRAP_LOG(NWRAP_LOG_ERROR
,
2557 "entry is NULL, can't create list item");
2561 el
= (struct nwrap_entlist
*)malloc(sizeof(struct nwrap_entlist
));
2563 NWRAP_LOG(NWRAP_LOG_ERROR
, "malloc failed");
2573 static bool nwrap_ed_inventarize_add_new(char *const h_name
,
2574 struct nwrap_entdata
*const ed
)
2578 struct nwrap_entlist
*el
;
2581 if (h_name
== NULL
) {
2582 NWRAP_LOG(NWRAP_LOG_ERROR
, "h_name NULL - can't add");
2586 el
= nwrap_entlist_init(ed
);
2592 e
.data
= (void *)el
;
2594 p
= hsearch(e
, ENTER
);
2596 NWRAP_LOG(NWRAP_LOG_ERROR
, "Hash table is full!");
2600 ok
= nwrap_vector_add_item(&(nwrap_he_global
.lists
), (void *)el
);
2602 NWRAP_LOG(NWRAP_LOG_ERROR
,
2603 "Failed to add list entry to vector.");
2610 static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata
*const ed
,
2611 struct nwrap_entlist
*const el
)
2613 struct nwrap_entlist
*cursor
;
2614 struct nwrap_entlist
*el_new
;
2617 NWRAP_LOG(NWRAP_LOG_ERROR
, "list is NULL, can not add");
2622 for (cursor
= el
; cursor
->next
!= NULL
; cursor
= cursor
->next
)
2624 if (cursor
->ed
== ed
) {
2625 /* The entry already exists in this list. */
2630 if (cursor
->ed
== ed
) {
2631 /* The entry already exists in this list. */
2635 el_new
= nwrap_entlist_init(ed
);
2636 if (el_new
== NULL
) {
2640 cursor
->next
= el_new
;
2644 static bool nwrap_ed_inventarize(char *const name
,
2645 struct nwrap_entdata
*const ed
)
2654 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching name: %s", e
.key
);
2656 p
= hsearch(e
, FIND
);
2658 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found. Adding...", name
);
2659 ok
= nwrap_ed_inventarize_add_new(name
, ed
);
2661 struct nwrap_entlist
*el
= (struct nwrap_entlist
*)p
->data
;
2663 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s found. Add record to list.", name
);
2664 ok
= nwrap_ed_inventarize_add_to_existing(ed
, el
);
2670 static bool nwrap_add_hname(struct nwrap_entdata
*const ed
)
2672 char *const h_name
= (char *const)(ed
->ht
.h_name
);
2676 ok
= nwrap_ed_inventarize(h_name
, ed
);
2681 if (ed
->ht
.h_aliases
== NULL
) {
2685 /* Itemize aliases */
2686 for (i
= 0; ed
->ht
.h_aliases
[i
] != NULL
; ++i
) {
2689 h_name_alias
= ed
->ht
.h_aliases
[i
];
2691 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Add alias: %s", h_name_alias
);
2693 if (!nwrap_ed_inventarize(h_name_alias
, ed
)) {
2694 NWRAP_LOG(NWRAP_LOG_ERROR
,
2695 "Unable to add alias: %s", h_name_alias
);
2703 static bool nwrap_he_parse_line(struct nwrap_cache
*nwrap
, char *line
)
2705 struct nwrap_he
*nwrap_he
= (struct nwrap_he
*)nwrap
->private_data
;
2706 bool do_aliases
= true;
2707 ssize_t aliases_count
= 0;
2715 struct nwrap_entdata
*ed
= (struct nwrap_entdata
*)
2716 malloc(sizeof(struct nwrap_entdata
));
2718 NWRAP_LOG(NWRAP_LOG_ERROR
,
2719 "Unable to allocate memory for nwrap_entdata");
2730 /* Walk to first char */
2731 for (p
= i
; *p
!= '.' && *p
!= ':' && !isxdigit((int) *p
); p
++) {
2733 NWRAP_LOG(NWRAP_LOG_ERROR
,
2734 "Invalid line[%s]: '%s'",
2741 for (i
= p
; !isspace((int)*p
); p
++) {
2743 NWRAP_LOG(NWRAP_LOG_ERROR
,
2744 "Invalid line[%s]: '%s'",
2753 if (inet_pton(AF_INET
, i
, ed
->addr
.host_addr
)) {
2754 ed
->ht
.h_addrtype
= AF_INET
;
2755 ed
->ht
.h_length
= 4;
2757 } else if (inet_pton(AF_INET6
, i
, ed
->addr
.host_addr
)) {
2758 ed
->ht
.h_addrtype
= AF_INET6
;
2759 ed
->ht
.h_length
= 16;
2762 NWRAP_LOG(NWRAP_LOG_ERROR
,
2763 "Invalid line[%s]: '%s'",
2771 ok
= nwrap_vector_add_item(&(ed
->nwrap_addrdata
),
2772 (void *const)ed
->addr
.host_addr
);
2774 NWRAP_LOG(NWRAP_LOG_ERROR
, "Unable to add addrdata to vector");
2778 ed
->ht
.h_addr_list
= nwrap_vector_head(&ed
->nwrap_addrdata
);
2786 /* Walk to first char */
2787 for (n
= p
; *p
!= '_' && !isalnum((int) *p
); p
++) {
2789 NWRAP_LOG(NWRAP_LOG_ERROR
,
2790 "Invalid line[%s]: '%s'",
2798 for (n
= p
; !isspace((int)*p
); p
++) {
2807 /* Convert to lowercase. This operate on same memory region */
2811 /* glib's getent always dereferences he->h_aliases */
2812 ed
->ht
.h_aliases
= malloc(sizeof(char *));
2813 if (ed
->ht
.h_aliases
== NULL
) {
2817 ed
->ht
.h_aliases
[0] = NULL
;
2822 while (do_aliases
) {
2828 /* Walk to first char */
2829 for (a
= p
; *p
!= '_' && !isalnum((int) *p
); p
++) {
2835 /* Only trailing spaces are left */
2840 for (a
= p
; !isspace((int)*p
); p
++) {
2849 aliases
= realloc(ed
->ht
.h_aliases
, sizeof(char *) * (aliases_count
+ 2));
2850 if (aliases
== NULL
) {
2854 ed
->ht
.h_aliases
= aliases
;
2857 aliases
[aliases_count
] = a
;
2858 aliases
[aliases_count
+ 1] = NULL
;
2863 ok
= nwrap_vector_add_item(&(nwrap_he
->entries
), (void *const)ed
);
2865 NWRAP_LOG(NWRAP_LOG_ERROR
, "Unable to add entry to vector");
2870 ed
->aliases_count
= aliases_count
;
2871 /* Inventarize item */
2872 ok
= nwrap_add_hname(ed
);
2877 ok
= nwrap_ed_inventarize(ip
, ed
);
2886 static void nwrap_he_unload(struct nwrap_cache
*nwrap
)
2888 struct nwrap_he
*nwrap_he
=
2889 (struct nwrap_he
*)nwrap
->private_data
;
2890 struct nwrap_entdata
*ed
;
2891 struct nwrap_entlist
*el
;
2895 nwrap_vector_foreach (ed
, nwrap_he
->entries
, i
)
2897 SAFE_FREE(ed
->nwrap_addrdata
.items
);
2898 SAFE_FREE(ed
->ht
.h_aliases
);
2901 SAFE_FREE(nwrap_he
->entries
.items
);
2902 nwrap_he
->entries
.count
= nwrap_he
->entries
.capacity
= 0;
2904 nwrap_vector_foreach(el
, nwrap_he
->lists
, i
)
2906 while (el
!= NULL
) {
2907 struct nwrap_entlist
*el_next
;
2914 SAFE_FREE(nwrap_he
->lists
.items
);
2915 nwrap_he
->lists
.count
= nwrap_he
->lists
.capacity
= 0;
2921 * If we unload the file, the pointers in the hash table point to
2922 * invalid memory. So we need to destroy the hash table and recreate
2926 rc
= hcreate(max_hostents
);
2928 NWRAP_LOG(NWRAP_LOG_ERROR
, "Failed to initialize hash table");
2934 /* user functions */
2935 static struct passwd
*nwrap_files_getpwnam(struct nwrap_backend
*b
,
2941 (void) b
; /* unused */
2943 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Lookup user %s in files", name
);
2945 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
2947 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
2951 for (i
=0; i
<nwrap_pw_global
.num
; i
++) {
2952 if (strcmp(nwrap_pw_global
.list
[i
].pw_name
, name
) == 0) {
2953 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] found", name
);
2954 return &nwrap_pw_global
.list
[i
];
2956 NWRAP_LOG(NWRAP_LOG_DEBUG
,
2957 "user[%s] does not match [%s]",
2959 nwrap_pw_global
.list
[i
].pw_name
);
2962 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] not found\n", name
);
2968 static int nwrap_files_getpwnam_r(struct nwrap_backend
*b
,
2969 const char *name
, struct passwd
*pwdst
,
2970 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
2974 pw
= nwrap_files_getpwnam(b
, name
);
2982 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
2985 static struct passwd
*nwrap_files_getpwuid(struct nwrap_backend
*b
,
2991 (void) b
; /* unused */
2993 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
2995 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
2999 for (i
=0; i
<nwrap_pw_global
.num
; i
++) {
3000 if (nwrap_pw_global
.list
[i
].pw_uid
== uid
) {
3001 NWRAP_LOG(NWRAP_LOG_DEBUG
, "uid[%u] found", uid
);
3002 return &nwrap_pw_global
.list
[i
];
3004 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3005 "uid[%u] does not match [%u]",
3007 nwrap_pw_global
.list
[i
].pw_uid
);
3010 NWRAP_LOG(NWRAP_LOG_DEBUG
, "uid[%u] not found\n", uid
);
3016 static int nwrap_files_getpwuid_r(struct nwrap_backend
*b
,
3017 uid_t uid
, struct passwd
*pwdst
,
3018 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
3022 pw
= nwrap_files_getpwuid(b
, uid
);
3030 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
3033 /* user enum functions */
3034 static void nwrap_files_setpwent(struct nwrap_backend
*b
)
3036 (void) b
; /* unused */
3038 nwrap_pw_global
.idx
= 0;
3041 static struct passwd
*nwrap_files_getpwent(struct nwrap_backend
*b
)
3045 (void) b
; /* unused */
3047 if (nwrap_pw_global
.idx
== 0) {
3049 ok
= nwrap_files_cache_reload(nwrap_pw_global
.cache
);
3051 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading passwd file");
3056 if (nwrap_pw_global
.idx
>= nwrap_pw_global
.num
) {
3061 pw
= &nwrap_pw_global
.list
[nwrap_pw_global
.idx
++];
3063 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3064 "return user[%s] uid[%u]",
3065 pw
->pw_name
, pw
->pw_uid
);
3070 static int nwrap_files_getpwent_r(struct nwrap_backend
*b
,
3071 struct passwd
*pwdst
, char *buf
,
3072 size_t buflen
, struct passwd
**pwdstp
)
3076 pw
= nwrap_files_getpwent(b
);
3084 return nwrap_pw_copy_r(pw
, pwdst
, buf
, buflen
, pwdstp
);
3087 static void nwrap_files_endpwent(struct nwrap_backend
*b
)
3089 (void) b
; /* unused */
3091 nwrap_pw_global
.idx
= 0;
3096 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
3098 #ifdef HAVE_SETSPENT
3099 static void nwrap_files_setspent(void)
3101 nwrap_sp_global
.idx
= 0;
3104 static struct spwd
*nwrap_files_getspent(void)
3108 if (nwrap_sp_global
.idx
== 0) {
3111 ok
= nwrap_files_cache_reload(nwrap_sp_global
.cache
);
3113 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading shadow file");
3118 if (nwrap_sp_global
.idx
>= nwrap_sp_global
.num
) {
3123 sp
= &nwrap_sp_global
.list
[nwrap_sp_global
.idx
++];
3125 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3132 static void nwrap_files_endspent(void)
3134 nwrap_sp_global
.idx
= 0;
3136 #endif /* HAVE_SETSPENT */
3138 static struct spwd
*nwrap_files_getspnam(const char *name
)
3143 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Lookup user %s in files", name
);
3145 ok
= nwrap_files_cache_reload(nwrap_sp_global
.cache
);
3147 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading shadow file");
3151 for (i
=0; i
<nwrap_sp_global
.num
; i
++) {
3152 if (strcmp(nwrap_sp_global
.list
[i
].sp_namp
, name
) == 0) {
3153 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] found", name
);
3154 return &nwrap_sp_global
.list
[i
];
3156 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3157 "user[%s] does not match [%s]",
3159 nwrap_sp_global
.list
[i
].sp_namp
);
3162 NWRAP_LOG(NWRAP_LOG_DEBUG
, "user[%s] not found\n", name
);
3167 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
3169 /* misc functions */
3170 static int nwrap_files_initgroups(struct nwrap_backend
*b
,
3179 groups
= (gid_t
*)malloc(size
* sizeof(gid_t
));
3180 if (groups
== NULL
) {
3181 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
3187 nwrap_files_setgrent(b
);
3188 while ((grp
= nwrap_files_getgrent(b
)) != NULL
) {
3191 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3192 "Inspecting %s for group membership",
3195 for (i
=0; grp
->gr_mem
&& grp
->gr_mem
[i
] != NULL
; i
++) {
3196 if (group
!= grp
->gr_gid
&&
3197 (strcmp(user
, grp
->gr_mem
[i
]) == 0)) {
3198 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3199 "%s is member of %s",
3203 groups
= (gid_t
*)realloc(groups
,
3204 (size
+ 1) * sizeof(gid_t
));
3205 if (groups
== NULL
) {
3206 NWRAP_LOG(NWRAP_LOG_ERROR
,
3212 groups
[size
] = grp
->gr_gid
;
3218 nwrap_files_endgrent(b
);
3220 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3221 "%s is member of %d groups",
3224 /* This really only works if uid_wrapper is loaded */
3225 rc
= setgroups(size
, groups
);
3232 /* group functions */
3233 static struct group
*nwrap_files_getgrnam(struct nwrap_backend
*b
,
3239 (void) b
; /* unused */
3241 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3243 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3247 for (i
=0; i
<nwrap_gr_global
.num
; i
++) {
3248 if (strcmp(nwrap_gr_global
.list
[i
].gr_name
, name
) == 0) {
3249 NWRAP_LOG(NWRAP_LOG_DEBUG
, "group[%s] found", name
);
3250 return &nwrap_gr_global
.list
[i
];
3252 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3253 "group[%s] does not match [%s]",
3255 nwrap_gr_global
.list
[i
].gr_name
);
3258 NWRAP_LOG(NWRAP_LOG_DEBUG
, "group[%s] not found", name
);
3264 static int nwrap_files_getgrnam_r(struct nwrap_backend
*b
,
3265 const char *name
, struct group
*grdst
,
3266 char *buf
, size_t buflen
, struct group
**grdstp
)
3270 gr
= nwrap_files_getgrnam(b
, name
);
3278 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3281 static struct group
*nwrap_files_getgrgid(struct nwrap_backend
*b
,
3287 (void) b
; /* unused */
3289 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3291 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3295 for (i
=0; i
<nwrap_gr_global
.num
; i
++) {
3296 if (nwrap_gr_global
.list
[i
].gr_gid
== gid
) {
3297 NWRAP_LOG(NWRAP_LOG_DEBUG
, "gid[%u] found", gid
);
3298 return &nwrap_gr_global
.list
[i
];
3300 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3301 "gid[%u] does not match [%u]",
3303 nwrap_gr_global
.list
[i
].gr_gid
);
3306 NWRAP_LOG(NWRAP_LOG_DEBUG
, "gid[%u] not found", gid
);
3312 static int nwrap_files_getgrgid_r(struct nwrap_backend
*b
,
3313 gid_t gid
, struct group
*grdst
,
3314 char *buf
, size_t buflen
, struct group
**grdstp
)
3318 gr
= nwrap_files_getgrgid(b
, gid
);
3326 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3329 /* group enum functions */
3330 static void nwrap_files_setgrent(struct nwrap_backend
*b
)
3332 (void) b
; /* unused */
3334 nwrap_gr_global
.idx
= 0;
3337 static struct group
*nwrap_files_getgrent(struct nwrap_backend
*b
)
3341 (void) b
; /* unused */
3343 if (nwrap_gr_global
.idx
== 0) {
3346 ok
= nwrap_files_cache_reload(nwrap_gr_global
.cache
);
3348 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading group file");
3353 if (nwrap_gr_global
.idx
>= nwrap_gr_global
.num
) {
3358 gr
= &nwrap_gr_global
.list
[nwrap_gr_global
.idx
++];
3360 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3361 "return group[%s] gid[%u]",
3362 gr
->gr_name
, gr
->gr_gid
);
3367 static int nwrap_files_getgrent_r(struct nwrap_backend
*b
,
3368 struct group
*grdst
, char *buf
,
3369 size_t buflen
, struct group
**grdstp
)
3373 gr
= nwrap_files_getgrent(b
);
3381 return nwrap_gr_copy_r(gr
, grdst
, buf
, buflen
, grdstp
);
3384 static void nwrap_files_endgrent(struct nwrap_backend
*b
)
3386 (void) b
; /* unused */
3388 nwrap_gr_global
.idx
= 0;
3391 /* hosts functions */
3392 static int nwrap_files_gethostbyname(const char *name
, int af
,
3393 struct hostent
*result
,
3394 struct nwrap_vector
*addr_list
)
3396 struct nwrap_entlist
*el
;
3401 char canon_name
[DNS_NAME_MAX
] = { 0 };
3403 bool he_found
= false;
3406 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
3408 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
3412 name_len
= strlen(name
);
3413 if (name_len
< sizeof(canon_name
) && name
[name_len
- 1] == '.') {
3414 strncpy(canon_name
, name
, name_len
- 1);
3418 if (!str_tolower_copy(&h_name_lower
, name
)) {
3419 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3420 "Out of memory while converting to lower case");
3424 /* Look at hash table for element */
3425 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching for name: %s", h_name_lower
);
3426 e
.key
= h_name_lower
;
3428 e_p
= hsearch(e
, FIND
);
3430 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found.", h_name_lower
);
3431 SAFE_FREE(h_name_lower
);
3434 SAFE_FREE(h_name_lower
);
3436 /* Always cleanup vector and results */
3437 if (!nwrap_vector_is_initialized(addr_list
)) {
3438 if (!nwrap_vector_init(addr_list
)) {
3439 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3440 "Unable to initialize memory for addr_list vector");
3444 /* When vector is initialized data are valid no more.
3445 * Quick way how to free vector is: */
3446 addr_list
->count
= 0;
3449 /* Iterate through results */
3450 for (el
= (struct nwrap_entlist
*)e_p
->data
; el
!= NULL
; el
= el
->next
)
3454 /* Filter by address familiy if provided */
3455 if (af
!= AF_UNSPEC
&& he
->h_addrtype
!= af
) {
3461 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
3463 if (af
== AF_UNSPEC
&& he
->h_addrtype
!= AF_INET
) {
3468 memcpy(result
, he
, sizeof(struct hostent
));
3469 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3470 "Name found. Returning record for %s",
3474 nwrap_vector_merge(addr_list
, &el
->ed
->nwrap_addrdata
);
3475 result
->h_addr_list
= nwrap_vector_head(addr_list
);
3481 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3482 "Name found in database. No records matches type.");
3489 #ifdef HAVE_GETHOSTBYNAME_R
3490 static int nwrap_gethostbyname_r(const char *name
,
3491 struct hostent
*ret
,
3492 char *buf
, size_t buflen
,
3493 struct hostent
**result
, int *h_errnop
)
3495 struct nwrap_vector
*addr_list
= malloc(sizeof(struct nwrap_vector
));
3498 if (addr_list
== NULL
) {
3499 NWRAP_LOG(NWRAP_LOG_ERROR
,
3500 "Unable to allocate memory for address list");
3505 ZERO_STRUCTP(addr_list
);
3507 rc
= nwrap_files_gethostbyname(name
, AF_UNSPEC
, ret
, addr_list
);
3509 *h_errnop
= h_errno
;
3510 if (addr_list
->items
!= NULL
) {
3511 free(addr_list
->items
);
3513 SAFE_FREE(addr_list
);
3518 if (buflen
< (addr_list
->count
* sizeof(void *))) {
3519 SAFE_FREE(addr_list
->items
);
3520 SAFE_FREE(addr_list
);
3524 /* Copy all to user provided buffer and change
3525 * pointers in returned structure.
3526 * +1 is for ending NULL pointer. */
3527 memcpy(buf
, addr_list
->items
, (addr_list
->count
+ 1) * sizeof(void *));
3529 free(addr_list
->items
);
3532 ret
->h_addr_list
= (char **)buf
;
3537 int gethostbyname_r(const char *name
,
3538 struct hostent
*ret
,
3539 char *buf
, size_t buflen
,
3540 struct hostent
**result
, int *h_errnop
)
3542 if (!nss_wrapper_hosts_enabled()) {
3543 return libc_gethostbyname_r(name
,
3551 return nwrap_gethostbyname_r(name
, ret
, buf
, buflen
, result
, h_errnop
);
3555 static int nwrap_files_getaddrinfo(const char *name
,
3556 unsigned short port
,
3557 const struct addrinfo
*hints
,
3558 struct addrinfo
**ai
)
3560 struct nwrap_entlist
*el
;
3562 struct addrinfo
*ai_head
= NULL
;
3563 struct addrinfo
*ai_cur
= NULL
;
3566 char canon_name
[DNS_NAME_MAX
] = { 0 };
3567 bool skip_canonname
= false;
3575 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
3577 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
3581 name_len
= strlen(name
);
3582 if (name_len
< DNS_NAME_MAX
&& name
[name_len
- 1] == '.') {
3583 strncpy(canon_name
, name
, name_len
- 1);
3587 if (!str_tolower_copy(&h_name_lower
, name
)) {
3588 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3589 "Out of memory while converting to lower case");
3593 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Searching for name: %s", h_name_lower
);
3594 e
.key
= h_name_lower
;
3596 e_p
= hsearch(e
, FIND
);
3598 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name %s not found.", h_name_lower
);
3599 SAFE_FREE(h_name_lower
);
3603 NWRAP_LOG(NWRAP_LOG_DEBUG
, "Name: %s found.", h_name_lower
);
3604 SAFE_FREE(h_name_lower
);
3607 for (el
= (struct nwrap_entlist
*)e_p
->data
; el
!= NULL
; el
= el
->next
)
3610 struct addrinfo
*ai_new
= NULL
;
3614 if (hints
->ai_family
!= AF_UNSPEC
&&
3615 he
->h_addrtype
!= hints
->ai_family
)
3617 NWRAP_LOG(NWRAP_LOG_DEBUG
,
3618 "Entry found but with wrong AF - "
3619 "remembering EAI_ADDRINFO.");
3620 rc
= EAI_ADDRFAMILY
;
3624 /* Function allocates memory and returns it in ai. */
3625 rc2
= nwrap_convert_he_ai(he
,
3631 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error converting he to ai");
3632 if (ai_head
!= NULL
) {
3633 freeaddrinfo(ai_head
);
3637 skip_canonname
= true;
3639 if (ai_head
== NULL
) {
3642 if (ai_cur
!= NULL
) {
3643 ai_cur
->ai_next
= ai_new
;
3648 if (ai_head
!= NULL
) {
3657 static struct hostent
*nwrap_files_gethostbyaddr(const void *addr
,
3658 socklen_t len
, int type
)
3661 char ip
[NWRAP_INET_ADDRSTRLEN
] = {0};
3662 struct nwrap_entdata
*ed
;
3667 (void) len
; /* unused */
3669 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
3671 NWRAP_LOG(NWRAP_LOG_ERROR
, "error loading hosts file");
3675 a
= inet_ntop(type
, addr
, ip
, sizeof(ip
));
3681 nwrap_vector_foreach(ed
, nwrap_he_global
.entries
, i
)
3684 if (he
->h_addrtype
!= type
) {
3688 if (memcmp(addr
, he
->h_addr_list
[0], he
->h_length
) == 0) {
3697 #ifdef HAVE_GETHOSTBYADDR_R
3698 static int nwrap_gethostbyaddr_r(const void *addr
, socklen_t len
, int type
,
3699 struct hostent
*ret
,
3700 char *buf
, size_t buflen
,
3701 struct hostent
**result
, int *h_errnop
)
3703 *result
= nwrap_files_gethostbyaddr(addr
, len
, type
);
3704 if (*result
!= NULL
) {
3705 memset(buf
, '\0', buflen
);
3709 *h_errnop
= h_errno
;
3714 int gethostbyaddr_r(const void *addr
, socklen_t len
, int type
,
3715 struct hostent
*ret
,
3716 char *buf
, size_t buflen
,
3717 struct hostent
**result
, int *h_errnop
)
3719 if (!nss_wrapper_hosts_enabled()) {
3720 return libc_gethostbyaddr_r(addr
,
3730 return nwrap_gethostbyaddr_r(addr
, len
, type
, ret
, buf
, buflen
, result
, h_errnop
);
3734 /* hosts enum functions */
3735 static void nwrap_files_sethostent(void)
3737 nwrap_he_global
.idx
= 0;
3740 static struct hostent
*nwrap_files_gethostent(void)
3744 if (nwrap_he_global
.idx
== 0) {
3747 ok
= nwrap_files_cache_reload(nwrap_he_global
.cache
);
3749 NWRAP_LOG(NWRAP_LOG_ERROR
, "Error loading hosts file");
3754 if (nwrap_he_global
.idx
>= nwrap_he_global
.num
) {
3759 he
= &((struct nwrap_entdata
*)nwrap_he_global
.entries
.items
[nwrap_he_global
.idx
++])->ht
;
3761 NWRAP_LOG(NWRAP_LOG_DEBUG
, "return hosts[%s]", he
->h_name
);
3766 static void nwrap_files_endhostent(void)
3768 nwrap_he_global
.idx
= 0;
3776 static struct passwd
*nwrap_module_getpwnam(struct nwrap_backend
*b
,
3779 static struct passwd pwd
;
3780 static char buf
[1000];
3783 if (!b
->fns
->_nss_getpwnam_r
) {
3787 status
= b
->fns
->_nss_getpwnam_r(name
, &pwd
, buf
, sizeof(buf
), &errno
);
3788 if (status
== NSS_STATUS_NOTFOUND
) {
3791 if (status
!= NSS_STATUS_SUCCESS
) {
3798 static int nwrap_module_getpwnam_r(struct nwrap_backend
*b
,
3799 const char *name
, struct passwd
*pwdst
,
3800 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
3804 (void) b
; /* unused */
3805 (void) pwdst
; /* unused */
3806 (void) pwdstp
; /* unused */
3808 if (!b
->fns
->_nss_getpwnam_r
) {
3809 return NSS_STATUS_NOTFOUND
;
3812 ret
= b
->fns
->_nss_getpwnam_r(name
, pwdst
, buf
, buflen
, &errno
);
3814 case NSS_STATUS_SUCCESS
:
3816 case NSS_STATUS_NOTFOUND
:
3821 case NSS_STATUS_TRYAGAIN
:
3834 static struct passwd
*nwrap_module_getpwuid(struct nwrap_backend
*b
,
3837 static struct passwd pwd
;
3838 static char buf
[1000];
3841 if (!b
->fns
->_nss_getpwuid_r
) {
3845 status
= b
->fns
->_nss_getpwuid_r(uid
, &pwd
, buf
, sizeof(buf
), &errno
);
3846 if (status
== NSS_STATUS_NOTFOUND
) {
3849 if (status
!= NSS_STATUS_SUCCESS
) {
3855 static int nwrap_module_getpwuid_r(struct nwrap_backend
*b
,
3856 uid_t uid
, struct passwd
*pwdst
,
3857 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
3861 (void) pwdstp
; /* unused */
3863 if (!b
->fns
->_nss_getpwuid_r
) {
3867 ret
= b
->fns
->_nss_getpwuid_r(uid
, pwdst
, buf
, buflen
, &errno
);
3869 case NSS_STATUS_SUCCESS
:
3871 case NSS_STATUS_NOTFOUND
:
3876 case NSS_STATUS_TRYAGAIN
:
3889 static void nwrap_module_setpwent(struct nwrap_backend
*b
)
3891 if (!b
->fns
->_nss_setpwent
) {
3895 b
->fns
->_nss_setpwent();
3898 static struct passwd
*nwrap_module_getpwent(struct nwrap_backend
*b
)
3900 static struct passwd pwd
;
3901 static char buf
[1000];
3904 if (!b
->fns
->_nss_getpwent_r
) {
3908 status
= b
->fns
->_nss_getpwent_r(&pwd
, buf
, sizeof(buf
), &errno
);
3909 if (status
== NSS_STATUS_NOTFOUND
) {
3912 if (status
!= NSS_STATUS_SUCCESS
) {
3918 static int nwrap_module_getpwent_r(struct nwrap_backend
*b
,
3919 struct passwd
*pwdst
, char *buf
,
3920 size_t buflen
, struct passwd
**pwdstp
)
3924 (void) pwdstp
; /* unused */
3926 if (!b
->fns
->_nss_getpwent_r
) {
3930 ret
= b
->fns
->_nss_getpwent_r(pwdst
, buf
, buflen
, &errno
);
3932 case NSS_STATUS_SUCCESS
:
3934 case NSS_STATUS_NOTFOUND
:
3939 case NSS_STATUS_TRYAGAIN
:
3952 static void nwrap_module_endpwent(struct nwrap_backend
*b
)
3954 if (!b
->fns
->_nss_endpwent
) {
3958 b
->fns
->_nss_endpwent();
3961 static int nwrap_module_initgroups(struct nwrap_backend
*b
,
3962 const char *user
, gid_t group
)
3968 if (!b
->fns
->_nss_initgroups
) {
3969 return NSS_STATUS_UNAVAIL
;
3972 return b
->fns
->_nss_initgroups(user
, group
, &start
, &size
, &groups
, 0, &errno
);
3975 static struct group
*nwrap_module_getgrnam(struct nwrap_backend
*b
,
3978 static struct group grp
;
3980 static int buflen
= 1000;
3983 if (!b
->fns
->_nss_getgrnam_r
) {
3988 buf
= (char *)malloc(buflen
);
3991 status
= b
->fns
->_nss_getgrnam_r(name
, &grp
, buf
, buflen
, &errno
);
3992 if (status
== NSS_STATUS_TRYAGAIN
) {
3994 buf
= (char *)realloc(buf
, buflen
);
4000 if (status
== NSS_STATUS_NOTFOUND
) {
4004 if (status
!= NSS_STATUS_SUCCESS
) {
4011 static int nwrap_module_getgrnam_r(struct nwrap_backend
*b
,
4012 const char *name
, struct group
*grdst
,
4013 char *buf
, size_t buflen
, struct group
**grdstp
)
4017 (void) grdstp
; /* unused */
4019 if (!b
->fns
->_nss_getgrnam_r
) {
4023 ret
= b
->fns
->_nss_getgrnam_r(name
, grdst
, buf
, buflen
, &errno
);
4025 case NSS_STATUS_SUCCESS
:
4027 case NSS_STATUS_NOTFOUND
:
4032 case NSS_STATUS_TRYAGAIN
:
4045 static struct group
*nwrap_module_getgrgid(struct nwrap_backend
*b
,
4048 static struct group grp
;
4050 static int buflen
= 1000;
4053 if (!b
->fns
->_nss_getgrgid_r
) {
4058 buf
= (char *)malloc(buflen
);
4062 status
= b
->fns
->_nss_getgrgid_r(gid
, &grp
, buf
, buflen
, &errno
);
4063 if (status
== NSS_STATUS_TRYAGAIN
) {
4065 buf
= (char *)realloc(buf
, buflen
);
4071 if (status
== NSS_STATUS_NOTFOUND
) {
4075 if (status
!= NSS_STATUS_SUCCESS
) {
4082 static int nwrap_module_getgrgid_r(struct nwrap_backend
*b
,
4083 gid_t gid
, struct group
*grdst
,
4084 char *buf
, size_t buflen
, struct group
**grdstp
)
4088 (void) grdstp
; /* unused */
4090 if (!b
->fns
->_nss_getgrgid_r
) {
4094 ret
= b
->fns
->_nss_getgrgid_r(gid
, grdst
, buf
, buflen
, &errno
);
4096 case NSS_STATUS_SUCCESS
:
4098 case NSS_STATUS_NOTFOUND
:
4103 case NSS_STATUS_TRYAGAIN
:
4116 static void nwrap_module_setgrent(struct nwrap_backend
*b
)
4118 if (!b
->fns
->_nss_setgrent
) {
4122 b
->fns
->_nss_setgrent();
4125 static struct group
*nwrap_module_getgrent(struct nwrap_backend
*b
)
4127 static struct group grp
;
4129 static int buflen
= 1024;
4132 if (!b
->fns
->_nss_getgrent_r
) {
4137 buf
= (char *)malloc(buflen
);
4141 status
= b
->fns
->_nss_getgrent_r(&grp
, buf
, buflen
, &errno
);
4142 if (status
== NSS_STATUS_TRYAGAIN
) {
4144 buf
= (char *)realloc(buf
, buflen
);
4150 if (status
== NSS_STATUS_NOTFOUND
) {
4154 if (status
!= NSS_STATUS_SUCCESS
) {
4161 static int nwrap_module_getgrent_r(struct nwrap_backend
*b
,
4162 struct group
*grdst
, char *buf
,
4163 size_t buflen
, struct group
**grdstp
)
4167 (void) grdstp
; /* unused */
4169 if (!b
->fns
->_nss_getgrent_r
) {
4173 ret
= b
->fns
->_nss_getgrent_r(grdst
, buf
, buflen
, &errno
);
4175 case NSS_STATUS_SUCCESS
:
4177 case NSS_STATUS_NOTFOUND
:
4182 case NSS_STATUS_TRYAGAIN
:
4195 static void nwrap_module_endgrent(struct nwrap_backend
*b
)
4197 if (!b
->fns
->_nss_endgrent
) {
4201 b
->fns
->_nss_endgrent();
4204 /****************************************************************************
4206 ***************************************************************************/
4208 static struct passwd
*nwrap_getpwnam(const char *name
)
4213 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4214 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4215 pwd
= b
->ops
->nw_getpwnam(b
, name
);
4224 struct passwd
*getpwnam(const char *name
)
4226 if (!nss_wrapper_enabled()) {
4227 return libc_getpwnam(name
);
4230 return nwrap_getpwnam(name
);
4233 /****************************************************************************
4235 ***************************************************************************/
4237 static int nwrap_getpwnam_r(const char *name
, struct passwd
*pwdst
,
4238 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4242 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4243 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4244 ret
= b
->ops
->nw_getpwnam_r(b
, name
, pwdst
, buf
, buflen
, pwdstp
);
4245 if (ret
== ENOENT
) {
4254 #ifdef HAVE_GETPWNAM_R
4255 # ifdef HAVE_SOLARIS_GETPWNAM_R
4256 int getpwnam_r(const char *name
, struct passwd
*pwdst
,
4257 char *buf
, int buflen
, struct passwd
**pwdstp
)
4258 # else /* HAVE_SOLARIS_GETPWNAM_R */
4259 int getpwnam_r(const char *name
, struct passwd
*pwdst
,
4260 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4261 # endif /* HAVE_SOLARIS_GETPWNAM_R */
4263 if (!nss_wrapper_enabled()) {
4264 return libc_getpwnam_r(name
, pwdst
, buf
, buflen
, pwdstp
);
4267 return nwrap_getpwnam_r(name
, pwdst
, buf
, buflen
, pwdstp
);
4271 /****************************************************************************
4273 ***************************************************************************/
4275 static struct passwd
*nwrap_getpwuid(uid_t uid
)
4280 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4281 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4282 pwd
= b
->ops
->nw_getpwuid(b
, uid
);
4291 struct passwd
*getpwuid(uid_t uid
)
4293 if (!nss_wrapper_enabled()) {
4294 return libc_getpwuid(uid
);
4297 return nwrap_getpwuid(uid
);
4300 /****************************************************************************
4302 ***************************************************************************/
4304 static int nwrap_getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
4305 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4309 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4310 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4311 ret
= b
->ops
->nw_getpwuid_r(b
, uid
, pwdst
, buf
, buflen
, pwdstp
);
4312 if (ret
== ENOENT
) {
4321 #ifdef HAVE_SOLARIS_GETPWUID_R
4322 int getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
4323 char *buf
, int buflen
, struct passwd
**pwdstp
)
4325 int getpwuid_r(uid_t uid
, struct passwd
*pwdst
,
4326 char *buf
, size_t buflen
, struct passwd
**pwdstp
)
4329 if (!nss_wrapper_enabled()) {
4330 return libc_getpwuid_r(uid
, pwdst
, buf
, buflen
, pwdstp
);
4333 return nwrap_getpwuid_r(uid
, pwdst
, buf
, buflen
, pwdstp
);
4336 /****************************************************************************
4338 ***************************************************************************/
4340 static void nwrap_setpwent(void)
4344 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4345 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4346 b
->ops
->nw_setpwent(b
);
4352 if (!nss_wrapper_enabled()) {
4360 /****************************************************************************
4362 ***************************************************************************/
4364 static struct passwd
*nwrap_getpwent(void)
4369 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4370 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4371 pwd
= b
->ops
->nw_getpwent(b
);
4380 struct passwd
*getpwent(void)
4382 if (!nss_wrapper_enabled()) {
4383 return libc_getpwent();
4386 return nwrap_getpwent();
4389 /****************************************************************************
4391 ***************************************************************************/
4393 static int nwrap_getpwent_r(struct passwd
*pwdst
, char *buf
,
4394 size_t buflen
, struct passwd
**pwdstp
)
4398 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4399 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4400 ret
= b
->ops
->nw_getpwent_r(b
, pwdst
, buf
, buflen
, pwdstp
);
4401 if (ret
== ENOENT
) {
4410 #ifdef HAVE_SOLARIS_GETPWENT_R
4411 struct passwd
*getpwent_r(struct passwd
*pwdst
, char *buf
, int buflen
)
4413 struct passwd
*pwdstp
= NULL
;
4416 if (!nss_wrapper_enabled()) {
4417 return libc_getpwent_r(pwdst
, buf
, buflen
);
4419 rc
= nwrap_getpwent_r(pwdst
, buf
, buflen
, &pwdstp
);
4426 #else /* HAVE_SOLARIS_GETPWENT_R */
4427 int getpwent_r(struct passwd
*pwdst
, char *buf
,
4428 size_t buflen
, struct passwd
**pwdstp
)
4430 if (!nss_wrapper_enabled()) {
4431 return libc_getpwent_r(pwdst
, buf
, buflen
, pwdstp
);
4434 return nwrap_getpwent_r(pwdst
, buf
, buflen
, pwdstp
);
4436 #endif /* HAVE_SOLARIS_GETPWENT_R */
4438 /****************************************************************************
4440 ***************************************************************************/
4442 static void nwrap_endpwent(void)
4446 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4447 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4448 b
->ops
->nw_endpwent(b
);
4454 if (!nss_wrapper_enabled()) {
4462 /****************************************************************************
4464 ***************************************************************************/
4466 static int nwrap_initgroups(const char *user
, gid_t group
)
4470 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4471 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4474 rc
= b
->ops
->nw_initgroups(b
, user
, group
);
4484 int initgroups(const char *user
, gid_t group
)
4486 if (!nss_wrapper_enabled()) {
4487 return libc_initgroups(user
, group
);
4490 return nwrap_initgroups(user
, group
);
4493 /****************************************************************************
4495 ***************************************************************************/
4497 static struct group
*nwrap_getgrnam(const char *name
)
4502 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4503 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4504 grp
= b
->ops
->nw_getgrnam(b
, name
);
4513 struct group
*getgrnam(const char *name
)
4515 if (!nss_wrapper_enabled()) {
4516 return libc_getgrnam(name
);
4519 return nwrap_getgrnam(name
);
4522 /****************************************************************************
4524 ***************************************************************************/
4526 static int nwrap_getgrnam_r(const char *name
, struct group
*grdst
,
4527 char *buf
, size_t buflen
, struct group
**grdstp
)
4531 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4532 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4533 ret
= b
->ops
->nw_getgrnam_r(b
, name
, grdst
, buf
, buflen
, grdstp
);
4534 if (ret
== ENOENT
) {
4543 #ifdef HAVE_GETGRNAM_R
4544 # ifdef HAVE_SOLARIS_GETGRNAM_R
4545 int getgrnam_r(const char *name
, struct group
*grp
,
4546 char *buf
, int buflen
, struct group
**pgrp
)
4547 # else /* HAVE_SOLARIS_GETGRNAM_R */
4548 int getgrnam_r(const char *name
, struct group
*grp
,
4549 char *buf
, size_t buflen
, struct group
**pgrp
)
4550 # endif /* HAVE_SOLARIS_GETGRNAM_R */
4552 if (!nss_wrapper_enabled()) {
4553 return libc_getgrnam_r(name
,
4560 return nwrap_getgrnam_r(name
, grp
, buf
, buflen
, pgrp
);
4562 #endif /* HAVE_GETGRNAM_R */
4564 /****************************************************************************
4566 ***************************************************************************/
4568 static struct group
*nwrap_getgrgid(gid_t gid
)
4573 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4574 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4575 grp
= b
->ops
->nw_getgrgid(b
, gid
);
4584 struct group
*getgrgid(gid_t gid
)
4586 if (!nss_wrapper_enabled()) {
4587 return libc_getgrgid(gid
);
4590 return nwrap_getgrgid(gid
);
4593 /****************************************************************************
4595 ***************************************************************************/
4597 static int nwrap_getgrgid_r(gid_t gid
, struct group
*grdst
,
4598 char *buf
, size_t buflen
, struct group
**grdstp
)
4602 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4603 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4604 ret
= b
->ops
->nw_getgrgid_r(b
, gid
, grdst
, buf
, buflen
, grdstp
);
4605 if (ret
== ENOENT
) {
4614 #ifdef HAVE_GETGRGID_R
4615 # ifdef HAVE_SOLARIS_GETGRGID_R
4616 int getgrgid_r(gid_t gid
, struct group
*grdst
,
4617 char *buf
, int buflen
, struct group
**grdstp
)
4618 # else /* HAVE_SOLARIS_GETGRGID_R */
4619 int getgrgid_r(gid_t gid
, struct group
*grdst
,
4620 char *buf
, size_t buflen
, struct group
**grdstp
)
4621 # endif /* HAVE_SOLARIS_GETGRGID_R */
4623 if (!nss_wrapper_enabled()) {
4624 return libc_getgrgid_r(gid
, grdst
, buf
, buflen
, grdstp
);
4627 return nwrap_getgrgid_r(gid
, grdst
, buf
, buflen
, grdstp
);
4631 /****************************************************************************
4633 ***************************************************************************/
4635 static void nwrap_setgrent(void)
4639 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4640 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4641 b
->ops
->nw_setgrent(b
);
4645 #ifdef HAVE_BSD_SETGRENT
4651 if (!nss_wrapper_enabled()) {
4659 #ifdef HAVE_BSD_SETGRENT
4666 /****************************************************************************
4668 ***************************************************************************/
4670 static struct group
*nwrap_getgrent(void)
4675 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4676 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4677 grp
= b
->ops
->nw_getgrent(b
);
4686 struct group
*getgrent(void)
4688 if (!nss_wrapper_enabled()) {
4689 return libc_getgrent();
4692 return nwrap_getgrent();
4695 /****************************************************************************
4697 ***************************************************************************/
4699 static int nwrap_getgrent_r(struct group
*grdst
, char *buf
,
4700 size_t buflen
, struct group
**grdstp
)
4704 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4705 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4706 ret
= b
->ops
->nw_getgrent_r(b
, grdst
, buf
, buflen
, grdstp
);
4707 if (ret
== ENOENT
) {
4716 #ifdef HAVE_SOLARIS_GETGRENT_R
4717 struct group
*getgrent_r(struct group
*src
, char *buf
, int buflen
)
4719 struct group
*grdstp
= NULL
;
4722 if (!nss_wrapper_enabled()) {
4723 return libc_getgrent_r(src
, buf
, buflen
);
4726 rc
= nwrap_getgrent_r(src
, buf
, buflen
, &grdstp
);
4733 #else /* HAVE_SOLARIS_GETGRENT_R */
4734 int getgrent_r(struct group
*src
, char *buf
,
4735 size_t buflen
, struct group
**grdstp
)
4737 if (!nss_wrapper_enabled()) {
4738 return libc_getgrent_r(src
, buf
, buflen
, grdstp
);
4741 return nwrap_getgrent_r(src
, buf
, buflen
, grdstp
);
4743 #endif /* HAVE_SOLARIS_GETGRENT_R */
4745 /****************************************************************************
4747 ***************************************************************************/
4749 static void nwrap_endgrent(void)
4753 for (i
=0; i
< nwrap_main_global
->num_backends
; i
++) {
4754 struct nwrap_backend
*b
= &nwrap_main_global
->backends
[i
];
4755 b
->ops
->nw_endgrent(b
);
4761 if (!nss_wrapper_enabled()) {
4769 /****************************************************************************
4771 ***************************************************************************/
4773 #ifdef HAVE_GETGROUPLIST
4774 static int nwrap_getgrouplist(const char *user
, gid_t group
,
4775 gid_t
*groups
, int *ngroups
)
4781 NWRAP_LOG(NWRAP_LOG_DEBUG
, "getgrouplist called for %s", user
);
4783 groups_tmp
= (gid_t
*)malloc(count
* sizeof(gid_t
));
4785 NWRAP_LOG(NWRAP_LOG_ERROR
, "Out of memory");
4789 groups_tmp
[0] = group
;
4792 while ((grp
= nwrap_getgrent()) != NULL
) {
4795 NWRAP_LOG(NWRAP_LOG_DEBUG
,
4796 "Inspecting %s for group membership",
4799 for (i
=0; grp
->gr_mem
&& grp
->gr_mem
[i
] != NULL
; i
++) {
4801 if (group
!= grp
->gr_gid
&&
4802 (strcmp(user
, grp
->gr_mem
[i
]) == 0)) {
4804 NWRAP_LOG(NWRAP_LOG_DEBUG
,
4805 "%s is member of %s",
4809 groups_tmp
= (gid_t
*)realloc(groups_tmp
, (count
+ 1) * sizeof(gid_t
));
4811 NWRAP_LOG(NWRAP_LOG_ERROR
,
4816 groups_tmp
[count
] = grp
->gr_gid
;
4825 NWRAP_LOG(NWRAP_LOG_DEBUG
,
4826 "%s is member of %d groups",
4829 if (*ngroups
< count
) {
4836 memcpy(groups
, groups_tmp
, count
* sizeof(gid_t
));
4842 int getgrouplist(const char *user
, gid_t group
, gid_t
*groups
, int *ngroups
)
4844 if (!nss_wrapper_enabled()) {
4845 return libc_getgrouplist(user
, group
, groups
, ngroups
);
4848 return nwrap_getgrouplist(user
, group
, groups
, ngroups
);
4852 /**********************************************************
4854 **********************************************************/
4856 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
4858 #ifdef HAVE_SETSPENT
4859 static void nwrap_setspent(void)
4861 nwrap_files_setspent();
4866 if (!nss_wrapper_shadow_enabled()) {
4873 static struct spwd
*nwrap_getspent(void)
4875 return nwrap_files_getspent();
4878 struct spwd
*getspent(void)
4880 if (!nss_wrapper_shadow_enabled()) {
4884 return nwrap_getspent();
4887 static void nwrap_endspent(void)
4889 nwrap_files_endspent();
4894 if (!nss_wrapper_shadow_enabled()) {
4900 #endif /* HAVE_SETSPENT */
4902 static struct spwd
*nwrap_getspnam(const char *name
)
4904 return nwrap_files_getspnam(name
);
4907 struct spwd
*getspnam(const char *name
)
4909 if (!nss_wrapper_shadow_enabled()) {
4913 return nwrap_getspnam(name
);
4916 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
4918 /**********************************************************
4920 **********************************************************/
4922 static void nwrap_sethostent(int stayopen
) {
4923 (void) stayopen
; /* ignored */
4925 nwrap_files_sethostent();
4928 #ifdef HAVE_SOLARIS_SETHOSTENT
4929 int sethostent(int stayopen
)
4931 if (!nss_wrapper_hosts_enabled()) {
4932 libc_sethostent(stayopen
);
4936 nwrap_sethostent(stayopen
);
4940 #else /* HAVE_SOLARIS_SETHOSTENT */
4941 void sethostent(int stayopen
)
4943 if (!nss_wrapper_hosts_enabled()) {
4944 libc_sethostent(stayopen
);
4948 nwrap_sethostent(stayopen
);
4950 #endif /* HAVE_SOLARIS_SETHOSTENT */
4952 static struct hostent
*nwrap_gethostent(void)
4954 return nwrap_files_gethostent();
4957 struct hostent
*gethostent(void) {
4958 if (!nss_wrapper_hosts_enabled()) {
4959 return libc_gethostent();
4962 return nwrap_gethostent();
4965 static void nwrap_endhostent(void) {
4966 nwrap_files_endhostent();
4969 #ifdef HAVE_SOLARIS_ENDHOSTENT
4970 int endhostent(void)
4972 if (!nss_wrapper_hosts_enabled()) {
4981 #else /* HAVE_SOLARIS_ENDHOSTENT */
4982 void endhostent(void)
4984 if (!nss_wrapper_hosts_enabled()) {
4991 #endif /* HAVE_SOLARIS_ENDHOSTENT */
4994 /* BSD implementation stores data in thread local storage but GLIBC does not */
4995 static __thread
struct hostent user_he
;
4996 static __thread
struct nwrap_vector user_addrlist
;
4998 static struct hostent user_he
;
4999 static struct nwrap_vector user_addrlist
;
5001 static struct hostent
*nwrap_gethostbyname(const char *name
)
5003 if (nwrap_files_gethostbyname(name
, AF_UNSPEC
, &user_he
, &user_addrlist
) == -1) {
5009 struct hostent
*gethostbyname(const char *name
)
5011 if (!nss_wrapper_hosts_enabled()) {
5012 return libc_gethostbyname(name
);
5015 return nwrap_gethostbyname(name
);
5018 /* This is a GNU extension - Also can be found on BSD systems */
5019 #ifdef HAVE_GETHOSTBYNAME2
5021 /* BSD implementation stores data in thread local storage but GLIBC not */
5022 static __thread
struct hostent user_he2
;
5023 static __thread
struct nwrap_vector user_addrlist2
;
5025 static struct hostent user_he2
;
5026 static struct nwrap_vector user_addrlist2
;
5028 static struct hostent
*nwrap_gethostbyname2(const char *name
, int af
)
5030 if (nwrap_files_gethostbyname(name
, af
, &user_he2
, &user_addrlist2
) == -1) {
5036 struct hostent
*gethostbyname2(const char *name
, int af
)
5038 if (!nss_wrapper_hosts_enabled()) {
5039 return libc_gethostbyname2(name
, af
);
5042 return nwrap_gethostbyname2(name
, af
);
5046 static struct hostent
*nwrap_gethostbyaddr(const void *addr
,
5047 socklen_t len
, int type
)
5049 return nwrap_files_gethostbyaddr(addr
, len
, type
);
5052 struct hostent
*gethostbyaddr(const void *addr
,
5053 socklen_t len
, int type
)
5055 if (!nss_wrapper_hosts_enabled()) {
5056 return libc_gethostbyaddr(addr
, len
, type
);
5059 return nwrap_gethostbyaddr(addr
, len
, type
);
5062 static const struct addrinfo default_hints
=
5064 .ai_flags
= AI_ADDRCONFIG
|AI_V4MAPPED
,
5065 .ai_family
= AF_UNSPEC
,
5070 .ai_canonname
= NULL
,
5074 static int nwrap_convert_he_ai(const struct hostent
*he
,
5075 unsigned short port
,
5076 const struct addrinfo
*hints
,
5077 struct addrinfo
**pai
,
5078 bool skip_canonname
)
5080 struct addrinfo
*ai
;
5087 switch (he
->h_addrtype
) {
5089 socklen
= sizeof(struct sockaddr_in
);
5093 socklen
= sizeof(struct sockaddr_in6
);
5100 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
) + socklen
);
5105 ai
->ai_flags
= hints
->ai_flags
;
5106 ai
->ai_family
= he
->h_addrtype
;
5107 ai
->ai_socktype
= hints
->ai_socktype
;
5108 ai
->ai_protocol
= hints
->ai_protocol
;
5109 ai
->ai_canonname
= NULL
;
5111 if (ai
->ai_socktype
== 0) {
5112 ai
->ai_socktype
= SOCK_DGRAM
;
5114 if (ai
->ai_protocol
== 0) {
5115 if (ai
->ai_socktype
== SOCK_DGRAM
) {
5116 ai
->ai_protocol
= IPPROTO_UDP
;
5117 } else if (ai
->ai_socktype
== SOCK_STREAM
) {
5118 ai
->ai_protocol
= IPPROTO_TCP
;
5122 ai
->ai_addrlen
= socklen
;
5123 ai
->ai_addr
= (void *)(ai
+ 1);
5125 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
5126 ai
->ai_addr
->sa_len
= socklen
;
5128 ai
->ai_addr
->sa_family
= he
->h_addrtype
;
5130 switch (he
->h_addrtype
) {
5133 struct sockaddr_in
*sinp
=
5134 (struct sockaddr_in
*) ai
->ai_addr
;
5136 memset(sinp
, 0, sizeof(struct sockaddr_in
));
5138 sinp
->sin_port
= htons(port
);
5139 sinp
->sin_family
= AF_INET
;
5141 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
5142 memcpy(&sinp
->sin_addr
, he
->h_addr_list
[0], he
->h_length
);
5149 struct sockaddr_in6
*sin6p
=
5150 (struct sockaddr_in6
*) ai
->ai_addr
;
5152 memset(sin6p
, 0, sizeof(struct sockaddr_in6
));
5154 sin6p
->sin6_port
= htons(port
);
5155 sin6p
->sin6_family
= AF_INET6
;
5157 memcpy(&sin6p
->sin6_addr
,
5167 if (he
->h_name
&& !skip_canonname
) {
5168 ai
->ai_canonname
= strdup(he
->h_name
);
5169 if (ai
->ai_canonname
== NULL
) {
5179 static int nwrap_getaddrinfo(const char *node
,
5180 const char *service
,
5181 const struct addrinfo
*hints
,
5182 struct addrinfo
**res
)
5184 struct addrinfo
*ai
= NULL
;
5185 unsigned short port
= 0;
5195 .family
= AF_UNSPEC
,
5199 if (node
== NULL
&& service
== NULL
) {
5203 if (hints
== NULL
) {
5204 hints
= &default_hints
;
5208 hints.ai_flags contains invalid flags; or, hints.ai_flags
5209 included AI_CANONNAME and name was NULL.
5211 if ((hints
->ai_flags
& AI_CANONNAME
) && (node
== NULL
)) {
5212 return EAI_BADFLAGS
;
5215 /* If no node has been specified, let glibc deal with it */
5218 struct addrinfo
*p
= NULL
;
5220 ret
= libc_getaddrinfo(node
, service
, hints
, &p
);
5228 if (service
!= NULL
&& service
[0] != '\0') {
5229 const char *proto
= NULL
;
5235 sl
= strtol(service
, &end_ptr
, 10);
5237 if (*end_ptr
== '\0') {
5240 } else if (hints
->ai_flags
& AI_NUMERICSERV
) {
5244 if (hints
->ai_protocol
!= 0) {
5245 struct protoent
*pent
;
5247 pent
= getprotobynumber(hints
->ai_protocol
);
5249 proto
= pent
->p_name
;
5253 s
= getservbyname(service
, proto
);
5257 port
= ntohs(s
->s_port
);
5262 rc
= inet_pton(AF_INET
, node
, &addr
.in
.v4
);
5264 addr
.family
= AF_INET
;
5267 if (addr
.family
== AF_UNSPEC
) {
5268 rc
= inet_pton(AF_INET6
, node
, &addr
.in
.v6
);
5270 addr
.family
= AF_INET6
;
5275 if (addr
.family
== AF_UNSPEC
) {
5276 if (hints
->ai_flags
& AI_NUMERICHOST
) {
5279 } else if ((hints
->ai_family
!= AF_UNSPEC
) &&
5280 (hints
->ai_family
!= addr
.family
))
5282 return EAI_ADDRFAMILY
;
5285 rc
= nwrap_files_getaddrinfo(node
, port
, hints
, &ai
);
5288 struct addrinfo
*p
= NULL
;
5290 ret
= libc_getaddrinfo(node
, service
, hints
, &p
);
5294 * nwrap_files_getaddrinfo failed, but libc was
5295 * successful -- use the result from libc.
5305 * If the socktype was not specified, duplicate
5306 * each ai returned, so that we have variants for
5309 if (hints
->ai_socktype
== 0) {
5310 struct addrinfo
*ai_cur
;
5312 /* freeaddrinfo() frees ai_canonname and ai so allocate them */
5313 for (ai_cur
= ai
; ai_cur
!= NULL
; ai_cur
= ai_cur
->ai_next
) {
5314 struct addrinfo
*ai_new
;
5316 /* duplicate the current entry */
5318 ai_new
= malloc(sizeof(struct addrinfo
));
5319 if (ai_new
== NULL
) {
5324 memcpy(ai_new
, ai_cur
, sizeof(struct addrinfo
));
5325 ai_new
->ai_next
= NULL
;
5327 /* We need a deep copy or freeaddrinfo() will blow up */
5328 if (ai_cur
->ai_canonname
!= NULL
) {
5329 ai_new
->ai_canonname
=
5330 strdup(ai_cur
->ai_canonname
);
5333 if (ai_cur
->ai_socktype
== SOCK_DGRAM
) {
5334 ai_new
->ai_socktype
= SOCK_STREAM
;
5335 } else if (ai_cur
->ai_socktype
== SOCK_STREAM
) {
5336 ai_new
->ai_socktype
= SOCK_DGRAM
;
5338 if (ai_cur
->ai_protocol
== IPPROTO_TCP
) {
5339 ai_new
->ai_protocol
= IPPROTO_UDP
;
5340 } else if (ai_cur
->ai_protocol
== IPPROTO_UDP
) {
5341 ai_new
->ai_protocol
= IPPROTO_TCP
;
5344 /* now insert the new entry */
5346 ai_new
->ai_next
= ai_cur
->ai_next
;
5347 ai_cur
->ai_next
= ai_new
;
5349 /* and move on (don't duplicate the new entry) */
5360 int getaddrinfo(const char *node
, const char *service
,
5361 const struct addrinfo
*hints
,
5362 struct addrinfo
**res
)
5364 if (!nss_wrapper_hosts_enabled()) {
5365 return libc_getaddrinfo(node
, service
, hints
, res
);
5368 return nwrap_getaddrinfo(node
, service
, hints
, res
);
5371 static int nwrap_getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
5372 char *host
, size_t hostlen
,
5373 char *serv
, size_t servlen
,
5377 struct servent
*service
;
5384 if (sa
== NULL
|| salen
< sizeof(sa_family_t
)) {
5388 if ((flags
& NI_NAMEREQD
) && host
== NULL
&& serv
== NULL
) {
5392 type
= sa
->sa_family
;
5395 if (salen
< sizeof(struct sockaddr_in
))
5397 addr
= &((const struct sockaddr_in
*)sa
)->sin_addr
;
5398 addrlen
= sizeof(((const struct sockaddr_in
*)sa
)->sin_addr
);
5399 port
= ntohs(((const struct sockaddr_in
*)sa
)->sin_port
);
5403 if (salen
< sizeof(struct sockaddr_in6
))
5405 addr
= &((const struct sockaddr_in6
*)sa
)->sin6_addr
;
5406 addrlen
= sizeof(((const struct sockaddr_in6
*)sa
)->sin6_addr
);
5407 port
= ntohs(((const struct sockaddr_in6
*)sa
)->sin6_port
);
5416 if ((flags
& NI_NUMERICHOST
) == 0) {
5417 he
= nwrap_files_gethostbyaddr(addr
, addrlen
, type
);
5418 if ((flags
& NI_NAMEREQD
) && (he
== NULL
|| he
->h_name
== NULL
))
5421 if (he
!= NULL
&& he
->h_name
!= NULL
) {
5422 if (strlen(he
->h_name
) >= hostlen
)
5423 return EAI_OVERFLOW
;
5424 strcpy(host
, he
->h_name
);
5425 if (flags
& NI_NOFQDN
)
5426 host
[strcspn(host
, ".")] = '\0';
5428 if (inet_ntop(type
, addr
, host
, hostlen
) == NULL
)
5429 return (errno
== ENOSPC
) ? EAI_OVERFLOW
: EAI_FAIL
;
5435 if ((flags
& NI_NUMERICSERV
) == 0) {
5436 proto
= (flags
& NI_DGRAM
) ? "udp" : "tcp";
5437 service
= getservbyport(htons(port
), proto
);
5439 if (service
!= NULL
) {
5440 if (strlen(service
->s_name
) >= servlen
)
5441 return EAI_OVERFLOW
;
5442 strcpy(serv
, service
->s_name
);
5444 if (snprintf(serv
, servlen
, "%u", port
) >= (int) servlen
)
5445 return EAI_OVERFLOW
;
5452 #ifdef HAVE_LINUX_GETNAMEINFO
5453 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
5454 char *host
, socklen_t hostlen
,
5455 char *serv
, socklen_t servlen
,
5457 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
5458 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
5459 char *host
, socklen_t hostlen
,
5460 char *serv
, socklen_t servlen
,
5463 int getnameinfo(const struct sockaddr
*sa
, socklen_t salen
,
5464 char *host
, size_t hostlen
,
5465 char *serv
, size_t servlen
,
5469 if (!nss_wrapper_hosts_enabled()) {
5470 return libc_getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
5473 return nwrap_getnameinfo(sa
, salen
, host
, hostlen
, serv
, servlen
, flags
);
5476 static int nwrap_gethostname(char *name
, size_t len
)
5478 const char *hostname
= getenv("NSS_WRAPPER_HOSTNAME");
5480 if (strlen(hostname
) >= len
) {
5481 errno
= ENAMETOOLONG
;
5484 snprintf(name
, len
, "%s", hostname
);
5489 #ifdef HAVE_SOLARIS_GETHOSTNAME
5490 int gethostname(char *name
, int len
)
5491 #else /* HAVE_SOLARIS_GETHOSTNAME */
5492 int gethostname(char *name
, size_t len
)
5493 #endif /* HAVE_SOLARIS_GETHOSTNAME */
5495 if (!nwrap_hostname_enabled()) {
5496 return libc_gethostname(name
, len
);
5499 return nwrap_gethostname(name
, len
);
5502 /****************************
5504 ***************************/
5507 * This function is called when the library is unloaded and makes sure that
5508 * sockets get closed and the unix file for the socket are unlinked.
5510 void nwrap_destructor(void)
5515 if (nwrap_main_global
!= NULL
) {
5516 struct nwrap_main
*m
= nwrap_main_global
;
5519 SAFE_FREE(m
->libc
->fns
);
5520 if (m
->libc
->handle
!= NULL
) {
5521 dlclose(m
->libc
->handle
);
5523 if (m
->libc
->nsl_handle
!= NULL
) {
5524 dlclose(m
->libc
->nsl_handle
);
5526 if (m
->libc
->sock_handle
!= NULL
) {
5527 dlclose(m
->libc
->sock_handle
);
5532 for (i
= 0; i
< m
->num_backends
; i
++) {
5533 struct nwrap_backend
*b
= &(m
->backends
[i
]);
5535 if (b
->so_handle
!= NULL
) {
5536 dlclose(b
->so_handle
);
5540 SAFE_FREE(m
->backends
);
5543 if (nwrap_pw_global
.cache
!= NULL
) {
5544 struct nwrap_cache
*c
= nwrap_pw_global
.cache
;
5546 nwrap_files_cache_unload(c
);
5552 SAFE_FREE(nwrap_pw_global
.list
);
5553 nwrap_pw_global
.num
= 0;
5556 if (nwrap_gr_global
.cache
!= NULL
) {
5557 struct nwrap_cache
*c
= nwrap_gr_global
.cache
;
5559 nwrap_files_cache_unload(c
);
5565 SAFE_FREE(nwrap_gr_global
.list
);
5566 nwrap_pw_global
.num
= 0;
5569 #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
5570 if (nwrap_sp_global
.cache
!= NULL
) {
5571 struct nwrap_cache
*c
= nwrap_sp_global
.cache
;
5573 nwrap_files_cache_unload(c
);
5579 nwrap_sp_global
.num
= 0;
5581 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
5583 if (nwrap_he_global
.cache
!= NULL
) {
5584 struct nwrap_cache
*c
= nwrap_he_global
.cache
;
5586 nwrap_files_cache_unload(c
);
5592 nwrap_he_global
.num
= 0;
5595 free(user_addrlist
.items
);
5596 #ifdef HAVE_GETHOSTBYNAME2
5597 free(user_addrlist2
.items
);