smbd: Simplify validate_lock_entries
[Samba.git] / lib / nss_wrapper / nss_wrapper.c
bloba012cbd84b9431a6e3e74f42b48c3a065fbc0529
1 /*
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>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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
33 * SUCH DAMAGE.
36 #include "config.h"
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/socket.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdarg.h>
44 #include <stdbool.h>
45 #include <stddef.h>
46 #include <stdio.h>
47 #include <stdint.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <ctype.h>
54 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us
55 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
56 * Solaris
58 #ifndef _POSIX_PTHREAD_SEMANTICS
59 #define _POSIX_PTHREAD_SEMANTICS
60 #endif
62 #include <pwd.h>
63 #include <grp.h>
65 #include <netdb.h>
66 #include <arpa/inet.h>
67 #include <netinet/in.h>
69 #include <dlfcn.h>
71 #if defined(HAVE_NSS_H)
72 /* Linux and BSD */
73 #include <nss.h>
75 typedef enum nss_status NSS_STATUS;
76 #elif defined(HAVE_NSS_COMMON_H)
77 /* Solaris */
78 #include <nss_common.h>
79 #include <nss_dbdefs.h>
80 #include <nsswitch.h>
82 typedef nss_status_t NSS_STATUS;
84 # define NSS_STATUS_SUCCESS NSS_SUCCESS
85 # define NSS_STATUS_NOTFOUND NSS_NOTFOUND
86 # define NSS_STATUS_UNAVAIL NSS_UNAVAIL
87 # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN
88 #else
89 # error "No nsswitch support detected"
90 #endif
92 #ifndef PTR_DIFF
93 #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
94 #endif
96 #ifndef _PUBLIC_
97 #define _PUBLIC_
98 #endif
100 #ifndef EAI_NODATA
101 #define EAI_NODATA EAI_NONAME
102 #endif
104 #ifndef EAI_ADDRFAMILY
105 #define EAI_ADDRFAMILY EAI_FAMILY
106 #endif
108 #ifndef __STRING
109 #define __STRING(x) #x
110 #endif
112 #ifndef __STRINGSTRING
113 #define __STRINGSTRING(x) __STRING(x)
114 #endif
116 #ifndef __LINESTR__
117 #define __LINESTR__ __STRINGSTRING(__LINE__)
118 #endif
120 #ifndef __location__
121 #define __location__ __FILE__ ":" __LINESTR__
122 #endif
124 /* GCC have printf type attribute check. */
125 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
126 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
127 #else
128 #define PRINTF_ATTRIBUTE(a,b)
129 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
131 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
132 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
133 #else
134 #define DESTRUCTOR_ATTRIBUTE
135 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
137 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
139 enum nwrap_dbglvl_e {
140 NWRAP_LOG_ERROR = 0,
141 NWRAP_LOG_WARN,
142 NWRAP_LOG_DEBUG,
143 NWRAP_LOG_TRACE
146 #ifdef NDEBUG
147 # define NWRAP_LOG(...)
148 #else
150 static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
151 # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
153 static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
154 const char *func,
155 const char *format, ...)
157 char buffer[1024];
158 va_list va;
159 const char *d;
160 unsigned int lvl = 0;
161 int pid = getpid();
163 d = getenv("NSS_WRAPPER_DEBUGLEVEL");
164 if (d != NULL) {
165 lvl = atoi(d);
168 va_start(va, format);
169 vsnprintf(buffer, sizeof(buffer), format, va);
170 va_end(va);
172 if (lvl >= dbglvl) {
173 switch (dbglvl) {
174 case NWRAP_LOG_ERROR:
175 fprintf(stderr,
176 "NWRAP_ERROR(%d) - %s: %s\n",
177 pid, func, buffer);
178 break;
179 case NWRAP_LOG_WARN:
180 fprintf(stderr,
181 "NWRAP_WARN(%d) - %s: %s\n",
182 pid, func, buffer);
183 break;
184 case NWRAP_LOG_DEBUG:
185 fprintf(stderr,
186 "NWRAP_DEBUG(%d) - %s: %s\n",
187 pid, func, buffer);
188 break;
189 case NWRAP_LOG_TRACE:
190 fprintf(stderr,
191 "NWRAP_TRACE(%d) - %s: %s\n",
192 pid, func, buffer);
193 break;
197 #endif /* NDEBUG NWRAP_LOG */
199 struct nwrap_libc_fns {
200 struct passwd *(*_libc_getpwnam)(const char *name);
201 int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
202 char *buf, size_t buflen, struct passwd **result);
203 struct passwd *(*_libc_getpwuid)(uid_t uid);
204 int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
205 void (*_libc_setpwent)(void);
206 struct passwd *(*_libc_getpwent)(void);
207 #ifdef HAVE_SOLARIS_GETPWENT_R
208 struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
209 #else
210 int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
211 #endif
212 void (*_libc_endpwent)(void);
213 int (*_libc_initgroups)(const char *user, gid_t gid);
214 struct group *(*_libc_getgrnam)(const char *name);
215 int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
216 struct group *(*_libc_getgrgid)(gid_t gid);
217 int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
218 void (*_libc_setgrent)(void);
219 struct group *(*_libc_getgrent)(void);
220 #ifdef HAVE_SOLARIS_GETGRENT_R
221 struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
222 #else
223 int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
224 #endif
225 void (*_libc_endgrent)(void);
226 int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
228 void (*_libc_sethostent)(int stayopen);
229 struct hostent *(*_libc_gethostent)(void);
230 void (*_libc_endhostent)(void);
232 struct hostent *(*_libc_gethostbyname)(const char *name);
233 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
234 struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
235 #endif
236 struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
238 int (*_libc_getaddrinfo)(const char *node, const char *service,
239 const struct addrinfo *hints,
240 struct addrinfo **res);
241 int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
242 char *host, size_t hostlen,
243 char *serv, size_t servlen,
244 int flags);
245 int (*_libc_gethostname)(char *name, size_t len);
246 #ifdef HAVE_GETHOSTBYNAME_R
247 int (*_libc_gethostbyname_r)(const char *name,
248 struct hostent *ret,
249 char *buf, size_t buflen,
250 struct hostent **result, int *h_errnop);
251 #endif
252 #ifdef HAVE_GETHOSTBYADDR_R
253 int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
254 struct hostent *ret,
255 char *buf, size_t buflen,
256 struct hostent **result, int *h_errnop);
257 #endif
260 struct nwrap_module_nss_fns {
261 NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer,
262 size_t buflen, int *errnop);
263 NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer,
264 size_t buflen, int *errnop);
265 NSS_STATUS (*_nss_setpwent)(void);
266 NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer,
267 size_t buflen, int *errnop);
268 NSS_STATUS (*_nss_endpwent)(void);
269 NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start,
270 long int *size, gid_t **groups, long int limit, int *errnop);
271 NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer,
272 size_t buflen, int *errnop);
273 NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer,
274 size_t buflen, int *errnop);
275 NSS_STATUS (*_nss_setgrent)(void);
276 NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer,
277 size_t buflen, int *errnop);
278 NSS_STATUS (*_nss_endgrent)(void);
281 struct nwrap_backend {
282 const char *name;
283 const char *so_path;
284 void *so_handle;
285 struct nwrap_ops *ops;
286 struct nwrap_module_nss_fns *fns;
289 struct nwrap_ops {
290 struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
291 const char *name);
292 int (*nw_getpwnam_r)(struct nwrap_backend *b,
293 const char *name, struct passwd *pwdst,
294 char *buf, size_t buflen, struct passwd **pwdstp);
295 struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
296 uid_t uid);
297 int (*nw_getpwuid_r)(struct nwrap_backend *b,
298 uid_t uid, struct passwd *pwdst,
299 char *buf, size_t buflen, struct passwd **pwdstp);
300 void (*nw_setpwent)(struct nwrap_backend *b);
301 struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
302 int (*nw_getpwent_r)(struct nwrap_backend *b,
303 struct passwd *pwdst, char *buf,
304 size_t buflen, struct passwd **pwdstp);
305 void (*nw_endpwent)(struct nwrap_backend *b);
306 int (*nw_initgroups)(struct nwrap_backend *b,
307 const char *user, gid_t group);
308 struct group * (*nw_getgrnam)(struct nwrap_backend *b,
309 const char *name);
310 int (*nw_getgrnam_r)(struct nwrap_backend *b,
311 const char *name, struct group *grdst,
312 char *buf, size_t buflen, struct group **grdstp);
313 struct group * (*nw_getgrgid)(struct nwrap_backend *b,
314 gid_t gid);
315 int (*nw_getgrgid_r)(struct nwrap_backend *b,
316 gid_t gid, struct group *grdst,
317 char *buf, size_t buflen, struct group **grdstp);
318 void (*nw_setgrent)(struct nwrap_backend *b);
319 struct group * (*nw_getgrent)(struct nwrap_backend *b);
320 int (*nw_getgrent_r)(struct nwrap_backend *b,
321 struct group *grdst, char *buf,
322 size_t buflen, struct group **grdstp);
323 void (*nw_endgrent)(struct nwrap_backend *b);
326 /* Public prototypes */
328 bool nss_wrapper_enabled(void);
329 bool nss_wrapper_hosts_enabled(void);
331 /* prototypes for files backend */
334 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
335 const char *name);
336 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
337 const char *name, struct passwd *pwdst,
338 char *buf, size_t buflen, struct passwd **pwdstp);
339 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
340 uid_t uid);
341 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
342 uid_t uid, struct passwd *pwdst,
343 char *buf, size_t buflen, struct passwd **pwdstp);
344 static void nwrap_files_setpwent(struct nwrap_backend *b);
345 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
346 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
347 struct passwd *pwdst, char *buf,
348 size_t buflen, struct passwd **pwdstp);
349 static void nwrap_files_endpwent(struct nwrap_backend *b);
350 static int nwrap_files_initgroups(struct nwrap_backend *b,
351 const char *user, gid_t group);
352 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
353 const char *name);
354 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
355 const char *name, struct group *grdst,
356 char *buf, size_t buflen, struct group **grdstp);
357 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
358 gid_t gid);
359 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
360 gid_t gid, struct group *grdst,
361 char *buf, size_t buflen, struct group **grdstp);
362 static void nwrap_files_setgrent(struct nwrap_backend *b);
363 static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
364 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
365 struct group *grdst, char *buf,
366 size_t buflen, struct group **grdstp);
367 static void nwrap_files_endgrent(struct nwrap_backend *b);
369 /* prototypes for module backend */
371 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
372 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
373 struct passwd *pwdst, char *buf,
374 size_t buflen, struct passwd **pwdstp);
375 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
376 const char *name);
377 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
378 const char *name, struct passwd *pwdst,
379 char *buf, size_t buflen, struct passwd **pwdstp);
380 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
381 uid_t uid);
382 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
383 uid_t uid, struct passwd *pwdst,
384 char *buf, size_t buflen, struct passwd **pwdstp);
385 static void nwrap_module_setpwent(struct nwrap_backend *b);
386 static void nwrap_module_endpwent(struct nwrap_backend *b);
387 static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
388 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
389 struct group *grdst, char *buf,
390 size_t buflen, struct group **grdstp);
391 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
392 const char *name);
393 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
394 const char *name, struct group *grdst,
395 char *buf, size_t buflen, struct group **grdstp);
396 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
397 gid_t gid);
398 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
399 gid_t gid, struct group *grdst,
400 char *buf, size_t buflen, struct group **grdstp);
401 static void nwrap_module_setgrent(struct nwrap_backend *b);
402 static void nwrap_module_endgrent(struct nwrap_backend *b);
403 static int nwrap_module_initgroups(struct nwrap_backend *b,
404 const char *user, gid_t group);
406 struct nwrap_ops nwrap_files_ops = {
407 .nw_getpwnam = nwrap_files_getpwnam,
408 .nw_getpwnam_r = nwrap_files_getpwnam_r,
409 .nw_getpwuid = nwrap_files_getpwuid,
410 .nw_getpwuid_r = nwrap_files_getpwuid_r,
411 .nw_setpwent = nwrap_files_setpwent,
412 .nw_getpwent = nwrap_files_getpwent,
413 .nw_getpwent_r = nwrap_files_getpwent_r,
414 .nw_endpwent = nwrap_files_endpwent,
415 .nw_initgroups = nwrap_files_initgroups,
416 .nw_getgrnam = nwrap_files_getgrnam,
417 .nw_getgrnam_r = nwrap_files_getgrnam_r,
418 .nw_getgrgid = nwrap_files_getgrgid,
419 .nw_getgrgid_r = nwrap_files_getgrgid_r,
420 .nw_setgrent = nwrap_files_setgrent,
421 .nw_getgrent = nwrap_files_getgrent,
422 .nw_getgrent_r = nwrap_files_getgrent_r,
423 .nw_endgrent = nwrap_files_endgrent,
426 struct nwrap_ops nwrap_module_ops = {
427 .nw_getpwnam = nwrap_module_getpwnam,
428 .nw_getpwnam_r = nwrap_module_getpwnam_r,
429 .nw_getpwuid = nwrap_module_getpwuid,
430 .nw_getpwuid_r = nwrap_module_getpwuid_r,
431 .nw_setpwent = nwrap_module_setpwent,
432 .nw_getpwent = nwrap_module_getpwent,
433 .nw_getpwent_r = nwrap_module_getpwent_r,
434 .nw_endpwent = nwrap_module_endpwent,
435 .nw_initgroups = nwrap_module_initgroups,
436 .nw_getgrnam = nwrap_module_getgrnam,
437 .nw_getgrnam_r = nwrap_module_getgrnam_r,
438 .nw_getgrgid = nwrap_module_getgrgid,
439 .nw_getgrgid_r = nwrap_module_getgrgid_r,
440 .nw_setgrent = nwrap_module_setgrent,
441 .nw_getgrent = nwrap_module_getgrent,
442 .nw_getgrent_r = nwrap_module_getgrent_r,
443 .nw_endgrent = nwrap_module_endgrent,
446 struct nwrap_libc {
447 void *handle;
448 void *nsl_handle;
449 void *sock_handle;
450 struct nwrap_libc_fns *fns;
453 struct nwrap_main {
454 const char *nwrap_switch;
455 int num_backends;
456 struct nwrap_backend *backends;
457 struct nwrap_libc *libc;
460 struct nwrap_main *nwrap_main_global;
461 struct nwrap_main __nwrap_main_global;
463 struct nwrap_cache {
464 const char *path;
465 int fd;
466 struct stat st;
467 uint8_t *buf;
468 void *private_data;
469 bool (*parse_line)(struct nwrap_cache *, char *line);
470 void (*unload)(struct nwrap_cache *);
473 struct nwrap_pw {
474 struct nwrap_cache *cache;
476 struct passwd *list;
477 int num;
478 int idx;
481 struct nwrap_cache __nwrap_cache_pw;
482 struct nwrap_pw nwrap_pw_global;
484 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
485 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
487 struct nwrap_gr {
488 struct nwrap_cache *cache;
490 struct group *list;
491 int num;
492 int idx;
495 struct nwrap_cache __nwrap_cache_gr;
496 struct nwrap_gr nwrap_gr_global;
498 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
499 static void nwrap_he_unload(struct nwrap_cache *nwrap);
501 struct nwrap_addrdata {
502 unsigned char host_addr[16]; /* IPv4 or IPv6 address */
503 char *h_addr_ptrs[2]; /* host_addr pointer + NULL */
506 struct nwrap_entdata {
507 struct nwrap_addrdata *addr;
508 struct hostent ht;
511 struct nwrap_he {
512 struct nwrap_cache *cache;
514 struct nwrap_entdata *list;
515 int num;
516 int idx;
519 struct nwrap_cache __nwrap_cache_he;
520 struct nwrap_he nwrap_he_global;
523 /*********************************************************
524 * NWRAP PROTOTYPES
525 *********************************************************/
527 static void nwrap_init(void);
528 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
529 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
530 void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
532 /*********************************************************
533 * NWRAP LIBC LOADER FUNCTIONS
534 *********************************************************/
536 enum nwrap_lib {
537 NWRAP_LIBC,
538 NWRAP_LIBNSL,
539 NWRAP_LIBSOCKET,
542 #ifndef NDEBUG
543 static const char *nwrap_str_lib(enum nwrap_lib lib)
545 switch (lib) {
546 case NWRAP_LIBC:
547 return "libc";
548 case NWRAP_LIBNSL:
549 return "libnsl";
550 case NWRAP_LIBSOCKET:
551 return "libsocket";
554 /* Compiler would warn us about unhandled enum value if we get here */
555 return "unknown";
557 #endif
559 static void *nwrap_load_lib_handle(enum nwrap_lib lib)
561 int flags = RTLD_LAZY;
562 void *handle = NULL;
563 int i;
565 #ifdef HAVE_APPLE
566 return RTLD_NEXT;
567 #endif
569 #ifdef RTLD_DEEPBIND
570 flags |= RTLD_DEEPBIND;
571 #endif
573 switch (lib) {
574 case NWRAP_LIBNSL:
575 #ifdef HAVE_LIBNSL
576 handle = nwrap_main_global->libc->nsl_handle;
577 if (handle == NULL) {
578 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
579 char soname[256] = {0};
581 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
582 handle = dlopen(soname, flags);
585 nwrap_main_global->libc->nsl_handle = handle;
587 break;
588 #endif
589 /* FALL TROUGH */
590 case NWRAP_LIBSOCKET:
591 #ifdef HAVE_LIBSOCKET
592 handle = nwrap_main_global->libc->sock_handle;
593 if (handle == NULL) {
594 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
595 char soname[256] = {0};
597 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
598 handle = dlopen(soname, flags);
601 nwrap_main_global->libc->sock_handle = handle;
603 break;
604 #endif
605 /* FALL TROUGH */
606 case NWRAP_LIBC:
607 handle = nwrap_main_global->libc->handle;
608 if (handle == NULL) {
609 for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
610 char soname[256] = {0};
612 snprintf(soname, sizeof(soname), "libc.so.%d", i);
613 handle = dlopen(soname, flags);
616 nwrap_main_global->libc->handle = handle;
618 break;
621 if (handle == NULL) {
622 NWRAP_LOG(NWRAP_LOG_ERROR,
623 "Failed to dlopen library: %s\n",
624 dlerror());
625 exit(-1);
628 return handle;
631 static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
633 void *handle;
634 void *func;
636 nwrap_init();
638 handle = nwrap_load_lib_handle(lib);
640 func = dlsym(handle, fn_name);
641 if (func == NULL) {
642 NWRAP_LOG(NWRAP_LOG_ERROR,
643 "Failed to find %s: %s\n",
644 fn_name, dlerror());
645 exit(-1);
648 NWRAP_LOG(NWRAP_LOG_TRACE,
649 "Loaded %s from %s",
650 fn_name, nwrap_str_lib(lib));
651 return func;
654 #define nwrap_load_lib_function(lib, fn_name) \
655 if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
656 *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
657 _nwrap_load_lib_function(lib, #fn_name); \
661 * IMPORTANT
663 * Functions expeciall from libc need to be loaded individually, you can't load
664 * all at once or gdb will segfault at startup. The same applies to valgrind and
665 * has probably something todo with with the linker.
666 * So we need load each function at the point it is called the first time.
668 static struct passwd *libc_getpwnam(const char *name)
670 nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
672 return nwrap_main_global->libc->fns->_libc_getpwnam(name);
675 #ifdef HAVE_GETPWNAM_R
676 static int libc_getpwnam_r(const char *name,
677 struct passwd *pwd,
678 char *buf,
679 size_t buflen,
680 struct passwd **result)
682 #ifdef HAVE___POSIX_GETPWNAM_R
683 if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
684 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
685 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
687 #else
688 nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
689 #endif
691 return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
692 pwd,
693 buf,
694 buflen,
695 result);
697 #endif
699 static struct passwd *libc_getpwuid(uid_t uid)
701 nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
703 return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
706 #ifdef HAVE_GETPWUID_R
707 static int libc_getpwuid_r(uid_t uid,
708 struct passwd *pwd,
709 char *buf,
710 size_t buflen,
711 struct passwd **result)
713 #ifdef HAVE___POSIX_GETPWUID_R
714 if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
715 *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
716 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
718 #else
719 nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
720 #endif
722 return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
723 pwd,
724 buf,
725 buflen,
726 result);
728 #endif
730 static void libc_setpwent(void)
732 nwrap_load_lib_function(NWRAP_LIBC, setpwent);
734 nwrap_main_global->libc->fns->_libc_setpwent();
737 static struct passwd *libc_getpwent(void)
739 nwrap_load_lib_function(NWRAP_LIBC, getpwent);
741 return nwrap_main_global->libc->fns->_libc_getpwent();
744 #ifdef HAVE_SOLARIS_GETPWENT_R
745 static struct passwd *libc_getpwent_r(struct passwd *pwdst,
746 char *buf,
747 int buflen)
749 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
751 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
752 buf,
753 buflen);
755 #else /* HAVE_SOLARIS_GETPWENT_R */
756 static int libc_getpwent_r(struct passwd *pwdst,
757 char *buf,
758 size_t buflen,
759 struct passwd **pwdstp)
761 nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
763 return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
764 buf,
765 buflen,
766 pwdstp);
768 #endif /* HAVE_SOLARIS_GETPWENT_R */
770 static void libc_endpwent(void)
772 nwrap_load_lib_function(NWRAP_LIBC, endpwent);
774 nwrap_main_global->libc->fns->_libc_endpwent();
777 static int libc_initgroups(const char *user, gid_t gid)
779 nwrap_load_lib_function(NWRAP_LIBC, initgroups);
781 return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
784 static struct group *libc_getgrnam(const char *name)
786 nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
788 return nwrap_main_global->libc->fns->_libc_getgrnam(name);
791 #ifdef HAVE_GETGRNAM_R
792 static int libc_getgrnam_r(const char *name,
793 struct group *grp,
794 char *buf,
795 size_t buflen,
796 struct group **result)
798 #ifdef HAVE___POSIX_GETGRNAM_R
799 if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
800 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
801 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
803 #else
804 nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
805 #endif
807 return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
808 grp,
809 buf,
810 buflen,
811 result);
813 #endif
815 static struct group *libc_getgrgid(gid_t gid)
817 nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
819 return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
822 #ifdef HAVE_GETGRGID_R
823 static int libc_getgrgid_r(gid_t gid,
824 struct group *grp,
825 char *buf,
826 size_t buflen,
827 struct group **result)
829 #ifdef HAVE___POSIX_GETGRGID_R
830 if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
831 *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
832 _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
834 #else
835 nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
836 #endif
838 return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
839 grp,
840 buf,
841 buflen,
842 result);
844 #endif
846 static void libc_setgrent(void)
848 nwrap_load_lib_function(NWRAP_LIBC, setgrent);
850 nwrap_main_global->libc->fns->_libc_setgrent();
853 static struct group *libc_getgrent(void)
855 nwrap_load_lib_function(NWRAP_LIBC, getgrent);
857 return nwrap_main_global->libc->fns->_libc_getgrent();
860 #ifdef HAVE_GETGRENT_R
861 #ifdef HAVE_SOLARIS_GETGRENT_R
862 static struct group *libc_getgrent_r(struct group *group,
863 char *buf,
864 size_t buflen)
866 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
868 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
869 buf,
870 buflen);
872 #else /* !HAVE_SOLARIS_GETGRENT_R */
873 static int libc_getgrent_r(struct group *group,
874 char *buf,
875 size_t buflen,
876 struct group **result)
878 nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
880 return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
881 buf,
882 buflen,
883 result);
885 #endif /* HAVE_SOLARIS_GETGRENT_R */
886 #endif /* HAVE_GETGRENT_R */
888 static void libc_endgrent(void)
890 nwrap_load_lib_function(NWRAP_LIBC, endgrent);
892 nwrap_main_global->libc->fns->_libc_endgrent();
895 #ifdef HAVE_GETGROUPLIST
896 static int libc_getgrouplist(const char *user,
897 gid_t group,
898 gid_t *groups,
899 int *ngroups)
901 nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
903 return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
904 group,
905 groups,
906 ngroups);
908 #endif
910 static void libc_sethostent(int stayopen)
912 nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
914 nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
917 static struct hostent *libc_gethostent(void)
919 nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
921 return nwrap_main_global->libc->fns->_libc_gethostent();
924 static void libc_endhostent(void)
926 nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
928 nwrap_main_global->libc->fns->_libc_endhostent();
931 static struct hostent *libc_gethostbyname(const char *name)
933 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
935 return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
938 #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
939 static struct hostent *libc_gethostbyname2(const char *name, int af)
941 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
943 return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
945 #endif
947 static struct hostent *libc_gethostbyaddr(const void *addr,
948 socklen_t len,
949 int type)
951 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
953 return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
954 len,
955 type);
958 static int libc_gethostname(char *name, size_t len)
960 nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
962 return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
965 #ifdef HAVE_GETHOSTBYNAME_R
966 static int libc_gethostbyname_r(const char *name,
967 struct hostent *ret,
968 char *buf,
969 size_t buflen,
970 struct hostent **result,
971 int *h_errnop)
973 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
975 return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
976 ret,
977 buf,
978 buflen,
979 result,
980 h_errnop);
982 #endif
984 #ifdef HAVE_GETHOSTBYADDR_R
985 static int libc_gethostbyaddr_r(const void *addr,
986 socklen_t len,
987 int type,
988 struct hostent *ret,
989 char *buf,
990 size_t buflen,
991 struct hostent **result,
992 int *h_errnop)
994 nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
996 return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
997 len,
998 type,
999 ret,
1000 buf,
1001 buflen,
1002 result,
1003 h_errnop);
1005 #endif
1007 static int libc_getaddrinfo(const char *node,
1008 const char *service,
1009 const struct addrinfo *hints,
1010 struct addrinfo **res)
1012 nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
1014 return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
1015 service,
1016 hints,
1017 res);
1020 static int libc_getnameinfo(const struct sockaddr *sa,
1021 socklen_t salen,
1022 char *host,
1023 size_t hostlen,
1024 char *serv,
1025 size_t servlen,
1026 int flags)
1028 nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
1030 return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
1031 salen,
1032 host,
1033 hostlen,
1034 serv,
1035 servlen,
1036 flags);
1039 /*********************************************************
1040 * NWRAP NSS MODULE LOADER FUNCTIONS
1041 *********************************************************/
1043 static void *nwrap_load_module_fn(struct nwrap_backend *b,
1044 const char *fn_name)
1046 void *res;
1047 char *s;
1049 if (!b->so_handle) {
1050 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
1051 return NULL;
1054 if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
1055 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1056 return NULL;
1059 res = dlsym(b->so_handle, s);
1060 if (!res) {
1061 NWRAP_LOG(NWRAP_LOG_ERROR,
1062 "Cannot find function %s in %s",
1063 s, b->so_path);
1065 free(s);
1066 s = NULL;
1067 return res;
1070 static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b)
1072 struct nwrap_module_nss_fns *fns;
1074 if (!b->so_handle) {
1075 return NULL;
1078 fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns));
1079 if (!fns) {
1080 return NULL;
1083 *(void **)(&fns->_nss_getpwnam_r) =
1084 nwrap_load_module_fn(b, "getpwnam_r");
1085 *(void **)(&fns->_nss_getpwuid_r) =
1086 nwrap_load_module_fn(b, "getpwuid_r");
1087 *(void **)(&fns->_nss_setpwent) =
1088 nwrap_load_module_fn(b, "setpwent");
1089 *(void **)(&fns->_nss_getpwent_r) =
1090 nwrap_load_module_fn(b, "getpwent_r");
1091 *(void **)(&fns->_nss_endpwent) =
1092 nwrap_load_module_fn(b, "endpwent");
1093 *(void **)(&fns->_nss_initgroups) =
1094 nwrap_load_module_fn(b, "initgroups_dyn");
1095 *(void **)(&fns->_nss_getgrnam_r) =
1096 nwrap_load_module_fn(b, "getgrnam_r");
1097 *(void **)(&fns->_nss_getgrgid_r)=
1098 nwrap_load_module_fn(b, "getgrgid_r");
1099 *(void **)(&fns->_nss_setgrent) =
1100 nwrap_load_module_fn(b, "setgrent");
1101 *(void **)(&fns->_nss_getgrent_r) =
1102 nwrap_load_module_fn(b, "getgrent_r");
1103 *(void **)(&fns->_nss_endgrent) =
1104 nwrap_load_module_fn(b, "endgrent");
1106 return fns;
1109 static void *nwrap_load_module(const char *so_path)
1111 void *h;
1113 if (!so_path || !strlen(so_path)) {
1114 return NULL;
1117 h = dlopen(so_path, RTLD_LAZY);
1118 if (!h) {
1119 NWRAP_LOG(NWRAP_LOG_ERROR,
1120 "Cannot open shared library %s",
1121 so_path);
1122 return NULL;
1125 return h;
1128 static bool nwrap_module_init(const char *name,
1129 struct nwrap_ops *ops,
1130 const char *so_path,
1131 int *num_backends,
1132 struct nwrap_backend **backends)
1134 struct nwrap_backend *b;
1136 *backends = (struct nwrap_backend *)realloc(*backends,
1137 sizeof(struct nwrap_backend) * ((*num_backends) + 1));
1138 if (!*backends) {
1139 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1140 return false;
1143 b = &((*backends)[*num_backends]);
1145 b->name = name;
1146 b->ops = ops;
1147 b->so_path = so_path;
1149 if (so_path != NULL) {
1150 b->so_handle = nwrap_load_module(so_path);
1151 b->fns = nwrap_load_module_fns(b);
1152 if (b->fns == NULL) {
1153 return false;
1155 } else {
1156 b->so_handle = NULL;
1157 b->fns = NULL;
1160 (*num_backends)++;
1162 return true;
1165 static void nwrap_libc_init(struct nwrap_main *r)
1167 r->libc = malloc(sizeof(struct nwrap_libc));
1168 if (r->libc == NULL) {
1169 printf("Failed to allocate memory for libc");
1170 exit(-1);
1172 ZERO_STRUCTP(r->libc);
1174 r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
1175 if (r->libc->fns == NULL) {
1176 printf("Failed to allocate memory for libc functions");
1177 exit(-1);
1179 ZERO_STRUCTP(r->libc->fns);
1182 static void nwrap_backend_init(struct nwrap_main *r)
1184 const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
1185 const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
1187 r->num_backends = 0;
1188 r->backends = NULL;
1190 if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
1191 &r->num_backends,
1192 &r->backends)) {
1193 NWRAP_LOG(NWRAP_LOG_ERROR,
1194 "Failed to initialize 'files' backend");
1195 return;
1198 if (module_so_path != NULL &&
1199 module_so_path[0] != '\0' &&
1200 module_fn_name != NULL &&
1201 module_fn_name[0] != '\0') {
1202 if (!nwrap_module_init(module_fn_name,
1203 &nwrap_module_ops,
1204 module_so_path,
1205 &r->num_backends,
1206 &r->backends)) {
1207 NWRAP_LOG(NWRAP_LOG_ERROR,
1208 "Failed to initialize '%s' backend",
1209 module_fn_name);
1210 return;
1215 static void nwrap_init(void)
1217 static bool initialized;
1219 if (initialized) return;
1220 initialized = true;
1222 nwrap_main_global = &__nwrap_main_global;
1224 nwrap_libc_init(nwrap_main_global);
1226 nwrap_backend_init(nwrap_main_global);
1228 nwrap_pw_global.cache = &__nwrap_cache_pw;
1230 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
1231 nwrap_pw_global.cache->fd = -1;
1232 nwrap_pw_global.cache->private_data = &nwrap_pw_global;
1233 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
1234 nwrap_pw_global.cache->unload = nwrap_pw_unload;
1236 nwrap_gr_global.cache = &__nwrap_cache_gr;
1238 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
1239 nwrap_gr_global.cache->fd = -1;
1240 nwrap_gr_global.cache->private_data = &nwrap_gr_global;
1241 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
1242 nwrap_gr_global.cache->unload = nwrap_gr_unload;
1244 nwrap_he_global.cache = &__nwrap_cache_he;
1246 nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
1247 nwrap_he_global.cache->fd = -1;
1248 nwrap_he_global.cache->private_data = &nwrap_he_global;
1249 nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
1250 nwrap_he_global.cache->unload = nwrap_he_unload;
1253 bool nss_wrapper_enabled(void)
1255 nwrap_init();
1257 if (nwrap_pw_global.cache->path == NULL ||
1258 nwrap_pw_global.cache->path[0] == '\0') {
1259 return false;
1261 if (nwrap_gr_global.cache->path == NULL ||
1262 nwrap_gr_global.cache->path[0] == '\0') {
1263 return false;
1266 return true;
1269 bool nss_wrapper_hosts_enabled(void)
1271 nwrap_init();
1273 if (nwrap_he_global.cache->path == NULL ||
1274 nwrap_he_global.cache->path[0] == '\0') {
1275 return false;
1278 return true;
1281 static bool nwrap_hostname_enabled(void)
1283 nwrap_init();
1285 if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
1286 return false;
1289 return true;
1292 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
1294 int ret;
1295 uint8_t *buf = NULL;
1296 char *nline;
1298 if (nwrap->st.st_size == 0) {
1299 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
1300 goto done;
1303 if (nwrap->st.st_size > INT32_MAX) {
1304 NWRAP_LOG(NWRAP_LOG_ERROR,
1305 "Size[%u] larger than INT32_MAX",
1306 (unsigned)nwrap->st.st_size);
1307 goto failed;
1310 ret = lseek(nwrap->fd, 0, SEEK_SET);
1311 if (ret != 0) {
1312 NWRAP_LOG(NWRAP_LOG_ERROR, "lseek - rc=%d\n", ret);
1313 goto failed;
1316 buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
1317 if (!buf) {
1318 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1319 goto failed;
1322 ret = read(nwrap->fd, buf, nwrap->st.st_size);
1323 if (ret != nwrap->st.st_size) {
1324 NWRAP_LOG(NWRAP_LOG_ERROR,
1325 "read(%u) rc=%d\n",
1326 (unsigned)nwrap->st.st_size, ret);
1327 goto failed;
1330 buf[nwrap->st.st_size] = '\0';
1332 nline = (char *)buf;
1333 while (nline != NULL && nline[0] != '\0') {
1334 char *line;
1335 char *e;
1336 bool ok;
1338 line = nline;
1339 nline = NULL;
1341 e = strchr(line, '\n');
1342 if (e) {
1343 e[0] = '\0';
1344 e++;
1345 if (e[0] == '\r') {
1346 e[0] = '\0';
1347 e++;
1349 nline = e;
1352 if (strlen(line) == 0) {
1353 continue;
1356 ok = nwrap->parse_line(nwrap, line);
1357 if (!ok) {
1358 goto failed;
1362 done:
1363 nwrap->buf = buf;
1364 return true;
1366 failed:
1367 if (buf) free(buf);
1368 return false;
1371 static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
1373 nwrap->unload(nwrap);
1375 if (nwrap->buf) free(nwrap->buf);
1377 nwrap->buf = NULL;
1380 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
1382 struct stat st;
1383 int ret;
1384 bool ok;
1385 bool retried = false;
1387 reopen:
1388 if (nwrap->fd < 0) {
1389 nwrap->fd = open(nwrap->path, O_RDONLY);
1390 if (nwrap->fd < 0) {
1391 NWRAP_LOG(NWRAP_LOG_ERROR,
1392 "Unable to open '%s' readonly %d:%s",
1393 nwrap->path, nwrap->fd,
1394 strerror(errno));
1395 return;
1397 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
1400 ret = fstat(nwrap->fd, &st);
1401 if (ret != 0) {
1402 NWRAP_LOG(NWRAP_LOG_ERROR,
1403 "fstat(%s) - %d:%s",
1404 nwrap->path,
1405 ret,
1406 strerror(errno));
1407 return;
1410 if (retried == false && st.st_nlink == 0) {
1411 /* maybe someone has replaced the file... */
1412 NWRAP_LOG(NWRAP_LOG_TRACE,
1413 "st_nlink == 0, reopen %s",
1414 nwrap->path);
1415 retried = true;
1416 memset(&nwrap->st, 0, sizeof(nwrap->st));
1417 close(nwrap->fd);
1418 nwrap->fd = -1;
1419 goto reopen;
1422 if (st.st_mtime == nwrap->st.st_mtime) {
1423 NWRAP_LOG(NWRAP_LOG_TRACE,
1424 "st_mtime[%u] hasn't changed, skip reload",
1425 (unsigned)st.st_mtime);
1426 return;
1429 NWRAP_LOG(NWRAP_LOG_TRACE,
1430 "st_mtime has changed [%u] => [%u], start reload",
1431 (unsigned)st.st_mtime,
1432 (unsigned)nwrap->st.st_mtime);
1434 nwrap->st = st;
1436 nwrap_files_cache_unload(nwrap);
1438 ok = nwrap_parse_file(nwrap);
1439 if (!ok) {
1440 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
1441 nwrap_files_cache_unload(nwrap);
1444 NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
1448 * the caller has to call nwrap_unload() on failure
1450 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
1452 struct nwrap_pw *nwrap_pw;
1453 char *c;
1454 char *p;
1455 char *e;
1456 struct passwd *pw;
1457 size_t list_size;
1459 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1461 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
1462 pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
1463 if (!pw) {
1464 NWRAP_LOG(NWRAP_LOG_ERROR,
1465 "realloc(%u) failed",
1466 (unsigned)list_size);
1467 return false;
1469 nwrap_pw->list = pw;
1471 pw = &nwrap_pw->list[nwrap_pw->num];
1473 c = line;
1475 /* name */
1476 p = strchr(c, ':');
1477 if (!p) {
1478 NWRAP_LOG(NWRAP_LOG_ERROR,
1479 "Invalid line[%s]: '%s'",
1480 line,
1482 return false;
1484 *p = '\0';
1485 p++;
1486 pw->pw_name = c;
1487 c = p;
1489 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
1491 /* password */
1492 p = strchr(c, ':');
1493 if (!p) {
1494 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1495 return false;
1497 *p = '\0';
1498 p++;
1499 pw->pw_passwd = c;
1500 c = p;
1502 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
1504 /* uid */
1505 p = strchr(c, ':');
1506 if (!p) {
1507 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1508 return false;
1510 *p = '\0';
1511 p++;
1512 e = NULL;
1513 pw->pw_uid = (uid_t)strtoul(c, &e, 10);
1514 if (c == e) {
1515 NWRAP_LOG(NWRAP_LOG_ERROR,
1516 "Invalid line[%s]: '%s' - %s",
1517 line, c, strerror(errno));
1518 return false;
1520 if (e == NULL) {
1521 NWRAP_LOG(NWRAP_LOG_ERROR,
1522 "Invalid line[%s]: '%s' - %s",
1523 line, c, strerror(errno));
1524 return false;
1526 if (e[0] != '\0') {
1527 NWRAP_LOG(NWRAP_LOG_ERROR,
1528 "Invalid line[%s]: '%s' - %s",
1529 line, c, strerror(errno));
1530 return false;
1532 c = p;
1534 NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
1536 /* gid */
1537 p = strchr(c, ':');
1538 if (!p) {
1539 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1540 return false;
1542 *p = '\0';
1543 p++;
1544 e = NULL;
1545 pw->pw_gid = (gid_t)strtoul(c, &e, 10);
1546 if (c == e) {
1547 NWRAP_LOG(NWRAP_LOG_ERROR,
1548 "Invalid line[%s]: '%s' - %s",
1549 line, c, strerror(errno));
1550 return false;
1552 if (e == NULL) {
1553 NWRAP_LOG(NWRAP_LOG_ERROR,
1554 "Invalid line[%s]: '%s' - %s",
1555 line, c, strerror(errno));
1556 return false;
1558 if (e[0] != '\0') {
1559 NWRAP_LOG(NWRAP_LOG_ERROR,
1560 "Invalid line[%s]: '%s' - %s",
1561 line, c, strerror(errno));
1562 return false;
1564 c = p;
1566 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
1568 /* gecos */
1569 p = strchr(c, ':');
1570 if (!p) {
1571 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
1572 return false;
1574 *p = '\0';
1575 p++;
1576 pw->pw_gecos = c;
1577 c = p;
1579 NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
1581 /* dir */
1582 p = strchr(c, ':');
1583 if (!p) {
1584 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
1585 return false;
1587 *p = '\0';
1588 p++;
1589 pw->pw_dir = c;
1590 c = p;
1592 NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
1594 /* shell */
1595 pw->pw_shell = c;
1596 NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
1598 NWRAP_LOG(NWRAP_LOG_DEBUG,
1599 "Added user[%s:%s:%u:%u:%s:%s:%s]",
1600 pw->pw_name, pw->pw_passwd,
1601 pw->pw_uid, pw->pw_gid,
1602 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
1604 nwrap_pw->num++;
1605 return true;
1608 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
1610 struct nwrap_pw *nwrap_pw;
1611 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
1613 if (nwrap_pw->list) free(nwrap_pw->list);
1615 nwrap_pw->list = NULL;
1616 nwrap_pw->num = 0;
1617 nwrap_pw->idx = 0;
1620 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
1621 char *buf, size_t buflen, struct passwd **dstp)
1623 char *first;
1624 char *last;
1625 off_t ofs;
1627 first = src->pw_name;
1629 last = src->pw_shell;
1630 while (*last) last++;
1632 ofs = PTR_DIFF(last + 1, first);
1634 if (ofs > (off_t) buflen) {
1635 return ERANGE;
1638 memcpy(buf, first, ofs);
1640 ofs = PTR_DIFF(src->pw_name, first);
1641 dst->pw_name = buf + ofs;
1642 ofs = PTR_DIFF(src->pw_passwd, first);
1643 dst->pw_passwd = buf + ofs;
1644 dst->pw_uid = src->pw_uid;
1645 dst->pw_gid = src->pw_gid;
1646 ofs = PTR_DIFF(src->pw_gecos, first);
1647 dst->pw_gecos = buf + ofs;
1648 ofs = PTR_DIFF(src->pw_dir, first);
1649 dst->pw_dir = buf + ofs;
1650 ofs = PTR_DIFF(src->pw_shell, first);
1651 dst->pw_shell = buf + ofs;
1653 if (dstp) {
1654 *dstp = dst;
1657 return 0;
1661 * the caller has to call nwrap_unload() on failure
1663 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
1665 struct nwrap_gr *nwrap_gr;
1666 char *c;
1667 char *p;
1668 char *e;
1669 struct group *gr;
1670 size_t list_size;
1671 unsigned nummem;
1673 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
1675 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
1676 gr = (struct group *)realloc(nwrap_gr->list, list_size);
1677 if (!gr) {
1678 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
1679 return false;
1681 nwrap_gr->list = gr;
1683 gr = &nwrap_gr->list[nwrap_gr->num];
1685 c = line;
1687 /* name */
1688 p = strchr(c, ':');
1689 if (!p) {
1690 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1691 return false;
1693 *p = '\0';
1694 p++;
1695 gr->gr_name = c;
1696 c = p;
1698 NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
1700 /* password */
1701 p = strchr(c, ':');
1702 if (!p) {
1703 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1704 return false;
1706 *p = '\0';
1707 p++;
1708 gr->gr_passwd = c;
1709 c = p;
1711 NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
1713 /* gid */
1714 p = strchr(c, ':');
1715 if (!p) {
1716 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
1717 return false;
1719 *p = '\0';
1720 p++;
1721 e = NULL;
1722 gr->gr_gid = (gid_t)strtoul(c, &e, 10);
1723 if (c == e) {
1724 NWRAP_LOG(NWRAP_LOG_ERROR,
1725 "Invalid line[%s]: '%s' - %s",
1726 line, c, strerror(errno));
1727 return false;
1729 if (e == NULL) {
1730 NWRAP_LOG(NWRAP_LOG_ERROR,
1731 "Invalid line[%s]: '%s' - %s",
1732 line, c, strerror(errno));
1733 return false;
1735 if (e[0] != '\0') {
1736 NWRAP_LOG(NWRAP_LOG_ERROR,
1737 "Invalid line[%s]: '%s' - %s",
1738 line, c, strerror(errno));
1739 return false;
1741 c = p;
1743 NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
1745 /* members */
1746 gr->gr_mem = (char **)malloc(sizeof(char *));
1747 if (!gr->gr_mem) {
1748 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
1749 return false;
1751 gr->gr_mem[0] = NULL;
1753 for(nummem=0; p; nummem++) {
1754 char **m;
1755 size_t m_size;
1756 c = p;
1757 p = strchr(c, ',');
1758 if (p) {
1759 *p = '\0';
1760 p++;
1763 if (strlen(c) == 0) {
1764 break;
1767 m_size = sizeof(char *) * (nummem+2);
1768 m = (char **)realloc(gr->gr_mem, m_size);
1769 if (!m) {
1770 NWRAP_LOG(NWRAP_LOG_ERROR,
1771 "realloc(%zd) failed",
1772 m_size);
1773 return false;
1775 gr->gr_mem = m;
1776 gr->gr_mem[nummem] = c;
1777 gr->gr_mem[nummem+1] = NULL;
1779 NWRAP_LOG(NWRAP_LOG_TRACE,
1780 "member[%u]: '%s'",
1781 nummem, gr->gr_mem[nummem]);
1784 NWRAP_LOG(NWRAP_LOG_DEBUG,
1785 "Added group[%s:%s:%u:] with %u members",
1786 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
1788 nwrap_gr->num++;
1789 return true;
1792 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
1794 int i;
1795 struct nwrap_gr *nwrap_gr;
1796 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
1798 if (nwrap_gr->list) {
1799 for (i=0; i < nwrap_gr->num; i++) {
1800 if (nwrap_gr->list[i].gr_mem) {
1801 free(nwrap_gr->list[i].gr_mem);
1804 free(nwrap_gr->list);
1807 nwrap_gr->list = NULL;
1808 nwrap_gr->num = 0;
1809 nwrap_gr->idx = 0;
1812 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
1813 char *buf, size_t buflen, struct group **dstp)
1815 char *first;
1816 char **lastm;
1817 char *last = NULL;
1818 off_t ofsb;
1819 off_t ofsm;
1820 off_t ofs;
1821 unsigned i;
1823 first = src->gr_name;
1825 lastm = src->gr_mem;
1826 while (*lastm) {
1827 last = *lastm;
1828 lastm++;
1831 if (last == NULL) {
1832 last = src->gr_passwd;
1834 while (*last) last++;
1836 ofsb = PTR_DIFF(last + 1, first);
1837 ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
1839 if ((ofsb + ofsm) > (off_t) buflen) {
1840 return ERANGE;
1843 memcpy(buf, first, ofsb);
1844 memcpy(buf + ofsb, src->gr_mem, ofsm);
1846 ofs = PTR_DIFF(src->gr_name, first);
1847 dst->gr_name = buf + ofs;
1848 ofs = PTR_DIFF(src->gr_passwd, first);
1849 dst->gr_passwd = buf + ofs;
1850 dst->gr_gid = src->gr_gid;
1852 dst->gr_mem = (char **)(buf + ofsb);
1853 for (i=0; src->gr_mem[i]; i++) {
1854 ofs = PTR_DIFF(src->gr_mem[i], first);
1855 dst->gr_mem[i] = buf + ofs;
1858 if (dstp) {
1859 *dstp = dst;
1862 return 0;
1865 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
1867 struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
1868 struct nwrap_entdata *ed;
1869 size_t list_size;
1870 bool do_aliases = true;
1871 int aliases_count = 0;
1872 char *p;
1873 char *i;
1874 char *n;
1876 list_size = sizeof(struct nwrap_entdata) * (nwrap_he->num + 1);
1878 ed = (struct nwrap_entdata *)realloc(nwrap_he->list, list_size);
1879 if (ed == NULL) {
1880 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
1881 return false;
1883 nwrap_he->list = ed;
1885 /* set it to the last element */
1886 ed = &(nwrap_he->list[nwrap_he->num]);
1888 ed->addr = malloc(sizeof(struct nwrap_addrdata));
1889 if (ed->addr == NULL) {
1890 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
1891 return false;
1894 i = line;
1897 * IP
1900 /* Walk to first char */
1901 for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
1902 if (*p == '\0') {
1903 NWRAP_LOG(NWRAP_LOG_ERROR,
1904 "Invalid line[%s]: '%s'",
1905 line, i);
1906 return false;
1910 for (i = p; !isspace((int)*p); p++) {
1911 if (*p == '\0') {
1912 NWRAP_LOG(NWRAP_LOG_ERROR,
1913 "Invalid line[%s]: '%s'",
1914 line, i);
1915 return false;
1919 *p = '\0';
1921 if (inet_pton(AF_INET, i, ed->addr->host_addr)) {
1922 ed->ht.h_addrtype = AF_INET;
1923 ed->ht.h_length = 4;
1924 #ifdef HAVE_IPV6
1925 } else if (inet_pton(AF_INET6, i, ed->addr->host_addr)) {
1926 ed->ht.h_addrtype = AF_INET6;
1927 ed->ht.h_length = 16;
1928 #endif
1929 } else {
1930 NWRAP_LOG(NWRAP_LOG_ERROR,
1931 "Invalid line[%s]: '%s'",
1932 line, i);
1934 return false;
1937 ed->addr->h_addr_ptrs[0] = (char *)ed->addr->host_addr;
1938 ed->addr->h_addr_ptrs[1] = NULL;
1940 ed->ht.h_addr_list = ed->addr->h_addr_ptrs;
1942 p++;
1945 * FQDN
1948 /* Walk to first char */
1949 for (n = p; *p != '_' && !isalnum((int) *p); p++) {
1950 if (*p == '\0') {
1951 NWRAP_LOG(NWRAP_LOG_ERROR,
1952 "Invalid line[%s]: '%s'",
1953 line, n);
1955 return false;
1959 for (n = p; !isspace((int)*p); p++) {
1960 if (*p == '\0') {
1961 do_aliases = false;
1962 break;
1966 *p = '\0';
1968 ed->ht.h_name = n;
1970 /* glib's getent always dereferences he->h_aliases */
1971 ed->ht.h_aliases = malloc(sizeof(char *));
1972 if (ed->ht.h_aliases == NULL) {
1973 return false;
1975 ed->ht.h_aliases[0] = NULL;
1978 * Aliases
1980 while (do_aliases) {
1981 char **aliases;
1982 char *a;
1984 p++;
1986 /* Walk to first char */
1987 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
1988 if (*p == '\0') {
1989 do_aliases = false;
1990 break;
1993 /* Only trailing spaces are left */
1994 if (!do_aliases) {
1995 break;
1998 for (a = p; !isspace((int)*p); p++) {
1999 if (*p == '\0') {
2000 do_aliases = false;
2001 break;
2005 *p = '\0';
2007 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
2008 if (aliases == NULL) {
2009 return false;
2011 ed->ht.h_aliases = aliases;
2013 aliases[aliases_count] = a;
2014 aliases[aliases_count + 1] = NULL;
2016 aliases_count++;
2019 nwrap_he->num++;
2020 return true;
2023 static void nwrap_he_unload(struct nwrap_cache *nwrap)
2025 struct nwrap_he *nwrap_he =
2026 (struct nwrap_he *)nwrap->private_data;
2027 int i;
2029 if (nwrap_he->list != NULL) {
2030 for (i = 0; i < nwrap_he->num; i++) {
2031 if (nwrap_he->list[i].ht.h_aliases != NULL) {
2032 free(nwrap_he->list[i].ht.h_aliases);
2034 if (nwrap_he->list[i].addr != NULL) {
2035 free(nwrap_he->list[i].addr);
2038 free(nwrap_he->list);
2041 nwrap_he->list = NULL;
2042 nwrap_he->num = 0;
2043 nwrap_he->idx = 0;
2047 /* user functions */
2048 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
2049 const char *name)
2051 int i;
2053 (void) b; /* unused */
2055 NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
2057 nwrap_files_cache_reload(nwrap_pw_global.cache);
2059 for (i=0; i<nwrap_pw_global.num; i++) {
2060 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
2061 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
2062 return &nwrap_pw_global.list[i];
2064 NWRAP_LOG(NWRAP_LOG_DEBUG,
2065 "user[%s] does not match [%s]",
2066 name,
2067 nwrap_pw_global.list[i].pw_name);
2070 NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
2072 errno = ENOENT;
2073 return NULL;
2076 static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
2077 const char *name, struct passwd *pwdst,
2078 char *buf, size_t buflen, struct passwd **pwdstp)
2080 struct passwd *pw;
2082 pw = nwrap_files_getpwnam(b, name);
2083 if (!pw) {
2084 if (errno == 0) {
2085 return ENOENT;
2087 return errno;
2090 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2093 static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
2094 uid_t uid)
2096 int i;
2098 (void) b; /* unused */
2100 nwrap_files_cache_reload(nwrap_pw_global.cache);
2102 for (i=0; i<nwrap_pw_global.num; i++) {
2103 if (nwrap_pw_global.list[i].pw_uid == uid) {
2104 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
2105 return &nwrap_pw_global.list[i];
2107 NWRAP_LOG(NWRAP_LOG_DEBUG,
2108 "uid[%u] does not match [%u]",
2109 uid,
2110 nwrap_pw_global.list[i].pw_uid);
2113 NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
2115 errno = ENOENT;
2116 return NULL;
2119 static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
2120 uid_t uid, struct passwd *pwdst,
2121 char *buf, size_t buflen, struct passwd **pwdstp)
2123 struct passwd *pw;
2125 pw = nwrap_files_getpwuid(b, uid);
2126 if (!pw) {
2127 if (errno == 0) {
2128 return ENOENT;
2130 return errno;
2133 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2136 /* user enum functions */
2137 static void nwrap_files_setpwent(struct nwrap_backend *b)
2139 (void) b; /* unused */
2141 nwrap_pw_global.idx = 0;
2144 static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
2146 struct passwd *pw;
2148 (void) b; /* unused */
2150 if (nwrap_pw_global.idx == 0) {
2151 nwrap_files_cache_reload(nwrap_pw_global.cache);
2154 if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
2155 errno = ENOENT;
2156 return NULL;
2159 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
2161 NWRAP_LOG(NWRAP_LOG_DEBUG,
2162 "return user[%s] uid[%u]",
2163 pw->pw_name, pw->pw_uid);
2165 return pw;
2168 static int nwrap_files_getpwent_r(struct nwrap_backend *b,
2169 struct passwd *pwdst, char *buf,
2170 size_t buflen, struct passwd **pwdstp)
2172 struct passwd *pw;
2174 pw = nwrap_files_getpwent(b);
2175 if (!pw) {
2176 if (errno == 0) {
2177 return ENOENT;
2179 return errno;
2182 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
2185 static void nwrap_files_endpwent(struct nwrap_backend *b)
2187 (void) b; /* unused */
2189 nwrap_pw_global.idx = 0;
2192 /* misc functions */
2193 static int nwrap_files_initgroups(struct nwrap_backend *b,
2194 const char *user, gid_t group)
2196 (void) b; /* unused */
2197 (void) user; /* unused */
2198 (void) group; /* used */
2200 /* TODO: maybe we should also fake this... */
2201 return EPERM;
2204 /* group functions */
2205 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
2206 const char *name)
2208 int i;
2210 (void) b; /* unused */
2212 nwrap_files_cache_reload(nwrap_gr_global.cache);
2214 for (i=0; i<nwrap_gr_global.num; i++) {
2215 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
2216 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
2217 return &nwrap_gr_global.list[i];
2219 NWRAP_LOG(NWRAP_LOG_DEBUG,
2220 "group[%s] does not match [%s]",
2221 name,
2222 nwrap_gr_global.list[i].gr_name);
2225 NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
2227 errno = ENOENT;
2228 return NULL;
2231 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
2232 const char *name, struct group *grdst,
2233 char *buf, size_t buflen, struct group **grdstp)
2235 struct group *gr;
2237 gr = nwrap_files_getgrnam(b, name);
2238 if (!gr) {
2239 if (errno == 0) {
2240 return ENOENT;
2242 return errno;
2245 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2248 static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
2249 gid_t gid)
2251 int i;
2253 (void) b; /* unused */
2255 nwrap_files_cache_reload(nwrap_gr_global.cache);
2257 for (i=0; i<nwrap_gr_global.num; i++) {
2258 if (nwrap_gr_global.list[i].gr_gid == gid) {
2259 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
2260 return &nwrap_gr_global.list[i];
2262 NWRAP_LOG(NWRAP_LOG_DEBUG,
2263 "gid[%u] does not match [%u]",
2264 gid,
2265 nwrap_gr_global.list[i].gr_gid);
2268 NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
2270 errno = ENOENT;
2271 return NULL;
2274 static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
2275 gid_t gid, struct group *grdst,
2276 char *buf, size_t buflen, struct group **grdstp)
2278 struct group *gr;
2280 gr = nwrap_files_getgrgid(b, gid);
2281 if (!gr) {
2282 if (errno == 0) {
2283 return ENOENT;
2285 return errno;
2288 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2291 /* group enum functions */
2292 static void nwrap_files_setgrent(struct nwrap_backend *b)
2294 (void) b; /* unused */
2296 nwrap_gr_global.idx = 0;
2299 static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
2301 struct group *gr;
2303 (void) b; /* unused */
2305 if (nwrap_gr_global.idx == 0) {
2306 nwrap_files_cache_reload(nwrap_gr_global.cache);
2309 if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
2310 errno = ENOENT;
2311 return NULL;
2314 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
2316 NWRAP_LOG(NWRAP_LOG_DEBUG,
2317 "return group[%s] gid[%u]",
2318 gr->gr_name, gr->gr_gid);
2320 return gr;
2323 static int nwrap_files_getgrent_r(struct nwrap_backend *b,
2324 struct group *grdst, char *buf,
2325 size_t buflen, struct group **grdstp)
2327 struct group *gr;
2329 gr = nwrap_files_getgrent(b);
2330 if (!gr) {
2331 if (errno == 0) {
2332 return ENOENT;
2334 return errno;
2337 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
2340 static void nwrap_files_endgrent(struct nwrap_backend *b)
2342 (void) b; /* unused */
2344 nwrap_gr_global.idx = 0;
2347 /* hosts functions */
2348 static struct hostent *nwrap_files_gethostbyname(const char *name, int af)
2350 struct hostent *he;
2351 int i;
2353 nwrap_files_cache_reload(nwrap_he_global.cache);
2355 for (i = 0; i < nwrap_he_global.num; i++) {
2356 int j;
2358 he = &nwrap_he_global.list[i].ht;
2360 /* Filter by address familiy if provided */
2361 if (af != AF_UNSPEC && he->h_addrtype != af) {
2362 continue;
2365 if (strcasecmp(he->h_name, name) == 0) {
2366 NWRAP_LOG(NWRAP_LOG_DEBUG, "name[%s] found", name);
2367 return he;
2370 if (he->h_aliases == NULL) {
2371 continue;
2374 for (j = 0; he->h_aliases[j] != NULL; j++) {
2375 if (strcasecmp(he->h_aliases[j], name) == 0) {
2376 NWRAP_LOG(NWRAP_LOG_DEBUG,
2377 "name[%s] found",
2378 name);
2379 return he;
2384 errno = ENOENT;
2385 return NULL;
2388 #ifdef HAVE_GETHOSTBYNAME_R
2389 static int nwrap_gethostbyname_r(const char *name,
2390 struct hostent *ret,
2391 char *buf, size_t buflen,
2392 struct hostent **result, int *h_errnop)
2394 *result = nwrap_files_gethostbyname(name, AF_UNSPEC);
2395 if (*result != NULL) {
2396 memset(buf, '\0', buflen);
2397 *ret = **result;
2398 return 0;
2399 } else {
2400 *h_errnop = h_errno;
2401 return -1;
2405 int gethostbyname_r(const char *name,
2406 struct hostent *ret,
2407 char *buf, size_t buflen,
2408 struct hostent **result, int *h_errnop)
2410 if (!nss_wrapper_hosts_enabled()) {
2411 return libc_gethostbyname_r(name,
2412 ret,
2413 buf,
2414 buflen,
2415 result,
2416 h_errnop);
2419 return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
2421 #endif
2423 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
2424 socklen_t len, int type)
2426 struct hostent *he;
2427 char ip[INET6_ADDRSTRLEN] = {0};
2428 const char *a;
2429 int i;
2431 (void) len; /* unused */
2433 nwrap_files_cache_reload(nwrap_he_global.cache);
2435 a = inet_ntop(type, addr, ip, sizeof(ip));
2436 if (a == NULL) {
2437 errno = EINVAL;
2438 return NULL;
2441 for (i = 0; i < nwrap_he_global.num; i++) {
2442 he = &nwrap_he_global.list[i].ht;
2444 if (he->h_addrtype != type) {
2445 continue;
2448 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
2449 return he;
2453 errno = ENOENT;
2454 return NULL;
2457 #ifdef HAVE_GETHOSTBYADDR_R
2458 static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
2459 struct hostent *ret,
2460 char *buf, size_t buflen,
2461 struct hostent **result, int *h_errnop)
2463 *result = nwrap_files_gethostbyaddr(addr, len, type);
2464 if (*result != NULL) {
2465 memset(buf, '\0', buflen);
2466 *ret = **result;
2467 return 0;
2468 } else {
2469 *h_errnop = h_errno;
2470 return -1;
2474 int gethostbyaddr_r(const void *addr, socklen_t len, int type,
2475 struct hostent *ret,
2476 char *buf, size_t buflen,
2477 struct hostent **result, int *h_errnop)
2479 if (!nss_wrapper_hosts_enabled()) {
2480 return libc_gethostbyaddr_r(addr,
2481 len,
2482 type,
2483 ret,
2484 buf,
2485 buflen,
2486 result,
2487 h_errnop);
2490 return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
2492 #endif
2494 /* hosts enum functions */
2495 static void nwrap_files_sethostent(void)
2497 nwrap_he_global.idx = 0;
2500 static struct hostent *nwrap_files_gethostent(void)
2502 struct hostent *he;
2504 if (nwrap_he_global.idx == 0) {
2505 nwrap_files_cache_reload(nwrap_he_global.cache);
2508 if (nwrap_he_global.idx >= nwrap_he_global.num) {
2509 errno = ENOENT;
2510 return NULL;
2513 he = &nwrap_he_global.list[nwrap_he_global.idx++].ht;
2515 NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
2517 return he;
2520 static void nwrap_files_endhostent(void)
2522 nwrap_he_global.idx = 0;
2526 * module backend
2529 #ifndef SAFE_FREE
2530 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
2531 #endif
2533 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
2534 const char *name)
2536 static struct passwd pwd;
2537 static char buf[1000];
2538 NSS_STATUS status;
2540 if (!b->fns->_nss_getpwnam_r) {
2541 return NULL;
2544 status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno);
2545 if (status == NSS_STATUS_NOTFOUND) {
2546 return NULL;
2548 if (status != NSS_STATUS_SUCCESS) {
2549 return NULL;
2552 return &pwd;
2555 static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
2556 const char *name, struct passwd *pwdst,
2557 char *buf, size_t buflen, struct passwd **pwdstp)
2559 int ret;
2561 (void) b; /* unused */
2562 (void) pwdst; /* unused */
2563 (void) pwdstp; /* unused */
2565 if (!b->fns->_nss_getpwnam_r) {
2566 return NSS_STATUS_NOTFOUND;
2569 ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno);
2570 switch (ret) {
2571 case NSS_STATUS_SUCCESS:
2572 return 0;
2573 case NSS_STATUS_NOTFOUND:
2574 if (errno != 0) {
2575 return errno;
2577 return ENOENT;
2578 case NSS_STATUS_TRYAGAIN:
2579 if (errno != 0) {
2580 return errno;
2582 return ERANGE;
2583 default:
2584 if (errno != 0) {
2585 return errno;
2587 return ret;
2591 static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
2592 uid_t uid)
2594 static struct passwd pwd;
2595 static char buf[1000];
2596 NSS_STATUS status;
2598 if (!b->fns->_nss_getpwuid_r) {
2599 return NULL;
2602 status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno);
2603 if (status == NSS_STATUS_NOTFOUND) {
2604 return NULL;
2606 if (status != NSS_STATUS_SUCCESS) {
2607 return NULL;
2609 return &pwd;
2612 static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
2613 uid_t uid, struct passwd *pwdst,
2614 char *buf, size_t buflen, struct passwd **pwdstp)
2616 int ret;
2618 (void) pwdstp; /* unused */
2620 if (!b->fns->_nss_getpwuid_r) {
2621 return ENOENT;
2624 ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno);
2625 switch (ret) {
2626 case NSS_STATUS_SUCCESS:
2627 return 0;
2628 case NSS_STATUS_NOTFOUND:
2629 if (errno != 0) {
2630 return errno;
2632 return ENOENT;
2633 case NSS_STATUS_TRYAGAIN:
2634 if (errno != 0) {
2635 return errno;
2637 return ERANGE;
2638 default:
2639 if (errno != 0) {
2640 return errno;
2642 return ret;
2646 static void nwrap_module_setpwent(struct nwrap_backend *b)
2648 if (!b->fns->_nss_setpwent) {
2649 return;
2652 b->fns->_nss_setpwent();
2655 static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
2657 static struct passwd pwd;
2658 static char buf[1000];
2659 NSS_STATUS status;
2661 if (!b->fns->_nss_getpwent_r) {
2662 return NULL;
2665 status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno);
2666 if (status == NSS_STATUS_NOTFOUND) {
2667 return NULL;
2669 if (status != NSS_STATUS_SUCCESS) {
2670 return NULL;
2672 return &pwd;
2675 static int nwrap_module_getpwent_r(struct nwrap_backend *b,
2676 struct passwd *pwdst, char *buf,
2677 size_t buflen, struct passwd **pwdstp)
2679 int ret;
2681 (void) pwdstp; /* unused */
2683 if (!b->fns->_nss_getpwent_r) {
2684 return ENOENT;
2687 ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno);
2688 switch (ret) {
2689 case NSS_STATUS_SUCCESS:
2690 return 0;
2691 case NSS_STATUS_NOTFOUND:
2692 if (errno != 0) {
2693 return errno;
2695 return ENOENT;
2696 case NSS_STATUS_TRYAGAIN:
2697 if (errno != 0) {
2698 return errno;
2700 return ERANGE;
2701 default:
2702 if (errno != 0) {
2703 return errno;
2705 return ret;
2709 static void nwrap_module_endpwent(struct nwrap_backend *b)
2711 if (!b->fns->_nss_endpwent) {
2712 return;
2715 b->fns->_nss_endpwent();
2718 static int nwrap_module_initgroups(struct nwrap_backend *b,
2719 const char *user, gid_t group)
2721 gid_t *groups;
2722 long int start;
2723 long int size;
2725 if (!b->fns->_nss_initgroups) {
2726 return NSS_STATUS_UNAVAIL;
2729 return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno);
2732 static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
2733 const char *name)
2735 static struct group grp;
2736 static char *buf;
2737 static int buflen = 1000;
2738 NSS_STATUS status;
2740 if (!b->fns->_nss_getgrnam_r) {
2741 return NULL;
2744 if (!buf) {
2745 buf = (char *)malloc(buflen);
2747 again:
2748 status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno);
2749 if (status == NSS_STATUS_TRYAGAIN) {
2750 buflen *= 2;
2751 buf = (char *)realloc(buf, buflen);
2752 if (!buf) {
2753 return NULL;
2755 goto again;
2757 if (status == NSS_STATUS_NOTFOUND) {
2758 SAFE_FREE(buf);
2759 return NULL;
2761 if (status != NSS_STATUS_SUCCESS) {
2762 SAFE_FREE(buf);
2763 return NULL;
2765 return &grp;
2768 static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
2769 const char *name, struct group *grdst,
2770 char *buf, size_t buflen, struct group **grdstp)
2772 int ret;
2774 (void) grdstp; /* unused */
2776 if (!b->fns->_nss_getgrnam_r) {
2777 return ENOENT;
2780 ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno);
2781 switch (ret) {
2782 case NSS_STATUS_SUCCESS:
2783 return 0;
2784 case NSS_STATUS_NOTFOUND:
2785 if (errno != 0) {
2786 return errno;
2788 return ENOENT;
2789 case NSS_STATUS_TRYAGAIN:
2790 if (errno != 0) {
2791 return errno;
2793 return ERANGE;
2794 default:
2795 if (errno != 0) {
2796 return errno;
2798 return ret;
2802 static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
2803 gid_t gid)
2805 static struct group grp;
2806 static char *buf;
2807 static int buflen = 1000;
2808 NSS_STATUS status;
2810 if (!b->fns->_nss_getgrgid_r) {
2811 return NULL;
2814 if (!buf) {
2815 buf = (char *)malloc(buflen);
2818 again:
2819 status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno);
2820 if (status == NSS_STATUS_TRYAGAIN) {
2821 buflen *= 2;
2822 buf = (char *)realloc(buf, buflen);
2823 if (!buf) {
2824 return NULL;
2826 goto again;
2828 if (status == NSS_STATUS_NOTFOUND) {
2829 SAFE_FREE(buf);
2830 return NULL;
2832 if (status != NSS_STATUS_SUCCESS) {
2833 SAFE_FREE(buf);
2834 return NULL;
2836 return &grp;
2839 static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
2840 gid_t gid, struct group *grdst,
2841 char *buf, size_t buflen, struct group **grdstp)
2843 int ret;
2845 (void) grdstp; /* unused */
2847 if (!b->fns->_nss_getgrgid_r) {
2848 return ENOENT;
2851 ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno);
2852 switch (ret) {
2853 case NSS_STATUS_SUCCESS:
2854 return 0;
2855 case NSS_STATUS_NOTFOUND:
2856 if (errno != 0) {
2857 return errno;
2859 return ENOENT;
2860 case NSS_STATUS_TRYAGAIN:
2861 if (errno != 0) {
2862 return errno;
2864 return ERANGE;
2865 default:
2866 if (errno != 0) {
2867 return errno;
2869 return ret;
2873 static void nwrap_module_setgrent(struct nwrap_backend *b)
2875 if (!b->fns->_nss_setgrent) {
2876 return;
2879 b->fns->_nss_setgrent();
2882 static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
2884 static struct group grp;
2885 static char *buf;
2886 static int buflen = 1024;
2887 NSS_STATUS status;
2889 if (!b->fns->_nss_getgrent_r) {
2890 return NULL;
2893 if (!buf) {
2894 buf = (char *)malloc(buflen);
2897 again:
2898 status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno);
2899 if (status == NSS_STATUS_TRYAGAIN) {
2900 buflen *= 2;
2901 buf = (char *)realloc(buf, buflen);
2902 if (!buf) {
2903 return NULL;
2905 goto again;
2907 if (status == NSS_STATUS_NOTFOUND) {
2908 SAFE_FREE(buf);
2909 return NULL;
2911 if (status != NSS_STATUS_SUCCESS) {
2912 SAFE_FREE(buf);
2913 return NULL;
2915 return &grp;
2918 static int nwrap_module_getgrent_r(struct nwrap_backend *b,
2919 struct group *grdst, char *buf,
2920 size_t buflen, struct group **grdstp)
2922 int ret;
2924 (void) grdstp; /* unused */
2926 if (!b->fns->_nss_getgrent_r) {
2927 return ENOENT;
2930 ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno);
2931 switch (ret) {
2932 case NSS_STATUS_SUCCESS:
2933 return 0;
2934 case NSS_STATUS_NOTFOUND:
2935 if (errno != 0) {
2936 return errno;
2938 return ENOENT;
2939 case NSS_STATUS_TRYAGAIN:
2940 if (errno != 0) {
2941 return errno;
2943 return ERANGE;
2944 default:
2945 if (errno != 0) {
2946 return errno;
2948 return ret;
2952 static void nwrap_module_endgrent(struct nwrap_backend *b)
2954 if (!b->fns->_nss_endgrent) {
2955 return;
2958 b->fns->_nss_endgrent();
2961 /****************************************************************************
2962 * GETPWNAM
2963 ***************************************************************************/
2965 static struct passwd *nwrap_getpwnam(const char *name)
2967 int i;
2968 struct passwd *pwd;
2970 for (i=0; i < nwrap_main_global->num_backends; i++) {
2971 struct nwrap_backend *b = &nwrap_main_global->backends[i];
2972 pwd = b->ops->nw_getpwnam(b, name);
2973 if (pwd) {
2974 return pwd;
2978 return NULL;
2981 struct passwd *getpwnam(const char *name)
2983 if (!nss_wrapper_enabled()) {
2984 return libc_getpwnam(name);
2987 return nwrap_getpwnam(name);
2990 /****************************************************************************
2991 * GETPWNAM_R
2992 ***************************************************************************/
2994 static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
2995 char *buf, size_t buflen, struct passwd **pwdstp)
2997 int i,ret;
2999 for (i=0; i < nwrap_main_global->num_backends; i++) {
3000 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3001 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
3002 if (ret == ENOENT) {
3003 continue;
3005 return ret;
3008 return ENOENT;
3011 #ifdef HAVE_GETPWNAM_R
3012 # ifdef HAVE_SOLARIS_GETPWNAM_R
3013 int getpwnam_r(const char *name, struct passwd *pwdst,
3014 char *buf, int buflen, struct passwd **pwdstp)
3015 # else /* HAVE_SOLARIS_GETPWNAM_R */
3016 int getpwnam_r(const char *name, struct passwd *pwdst,
3017 char *buf, size_t buflen, struct passwd **pwdstp)
3018 # endif /* HAVE_SOLARIS_GETPWNAM_R */
3020 if (!nss_wrapper_enabled()) {
3021 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
3024 return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
3026 #endif
3028 /****************************************************************************
3029 * GETPWUID
3030 ***************************************************************************/
3032 static struct passwd *nwrap_getpwuid(uid_t uid)
3034 int i;
3035 struct passwd *pwd;
3037 for (i=0; i < nwrap_main_global->num_backends; i++) {
3038 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3039 pwd = b->ops->nw_getpwuid(b, uid);
3040 if (pwd) {
3041 return pwd;
3045 return NULL;
3048 struct passwd *getpwuid(uid_t uid)
3050 if (!nss_wrapper_enabled()) {
3051 return libc_getpwuid(uid);
3054 return nwrap_getpwuid(uid);
3057 /****************************************************************************
3058 * GETPWUID_R
3059 ***************************************************************************/
3061 static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
3062 char *buf, size_t buflen, struct passwd **pwdstp)
3064 int i,ret;
3066 for (i=0; i < nwrap_main_global->num_backends; i++) {
3067 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3068 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
3069 if (ret == ENOENT) {
3070 continue;
3072 return ret;
3075 return ENOENT;
3078 #ifdef HAVE_SOLARIS_GETPWUID_R
3079 int getpwuid_r(uid_t uid, struct passwd *pwdst,
3080 char *buf, int buflen, struct passwd **pwdstp)
3081 #else
3082 int getpwuid_r(uid_t uid, struct passwd *pwdst,
3083 char *buf, size_t buflen, struct passwd **pwdstp)
3084 #endif
3086 if (!nss_wrapper_enabled()) {
3087 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
3090 return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
3093 /****************************************************************************
3094 * SETPWENT
3095 ***************************************************************************/
3097 static void nwrap_setpwent(void)
3099 int i;
3101 for (i=0; i < nwrap_main_global->num_backends; i++) {
3102 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3103 b->ops->nw_setpwent(b);
3107 void setpwent(void)
3109 if (!nss_wrapper_enabled()) {
3110 libc_setpwent();
3111 return;
3114 nwrap_setpwent();
3117 /****************************************************************************
3118 * GETPWENT
3119 ***************************************************************************/
3121 static struct passwd *nwrap_getpwent(void)
3123 int i;
3124 struct passwd *pwd;
3126 for (i=0; i < nwrap_main_global->num_backends; i++) {
3127 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3128 pwd = b->ops->nw_getpwent(b);
3129 if (pwd) {
3130 return pwd;
3134 return NULL;
3137 struct passwd *getpwent(void)
3139 if (!nss_wrapper_enabled()) {
3140 return libc_getpwent();
3143 return nwrap_getpwent();
3146 /****************************************************************************
3147 * GETPWENT_R
3148 ***************************************************************************/
3150 static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
3151 size_t buflen, struct passwd **pwdstp)
3153 int i,ret;
3155 for (i=0; i < nwrap_main_global->num_backends; i++) {
3156 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3157 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
3158 if (ret == ENOENT) {
3159 continue;
3161 return ret;
3164 return ENOENT;
3167 #ifdef HAVE_SOLARIS_GETPWENT_R
3168 struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
3170 struct passwd *pwdstp = NULL;
3171 int rc;
3173 if (!nss_wrapper_enabled()) {
3174 return libc_getpwent_r(pwdst, buf, buflen);
3176 rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
3177 if (rc < 0) {
3178 return NULL;
3181 return pwdstp;
3183 #else /* HAVE_SOLARIS_GETPWENT_R */
3184 int getpwent_r(struct passwd *pwdst, char *buf,
3185 size_t buflen, struct passwd **pwdstp)
3187 if (!nss_wrapper_enabled()) {
3188 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
3191 return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
3193 #endif /* HAVE_SOLARIS_GETPWENT_R */
3195 /****************************************************************************
3196 * ENDPWENT
3197 ***************************************************************************/
3199 static void nwrap_endpwent(void)
3201 int i;
3203 for (i=0; i < nwrap_main_global->num_backends; i++) {
3204 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3205 b->ops->nw_endpwent(b);
3209 void endpwent(void)
3211 if (!nss_wrapper_enabled()) {
3212 libc_endpwent();
3213 return;
3216 nwrap_endpwent();
3219 /****************************************************************************
3220 * INITGROUPS
3221 ***************************************************************************/
3223 static int nwrap_initgroups(const char *user, gid_t group)
3225 int i;
3227 for (i=0; i < nwrap_main_global->num_backends; i++) {
3228 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3229 int rc;
3231 rc = b->ops->nw_initgroups(b, user, group);
3232 if (rc == 0) {
3233 return 0;
3237 errno = ENOENT;
3238 return -1;
3241 int initgroups(const char *user, gid_t group)
3243 if (!nss_wrapper_enabled()) {
3244 return libc_initgroups(user, group);
3247 return nwrap_initgroups(user, group);
3250 /****************************************************************************
3251 * GETGRNAM
3252 ***************************************************************************/
3254 static struct group *nwrap_getgrnam(const char *name)
3256 int i;
3257 struct group *grp;
3259 for (i=0; i < nwrap_main_global->num_backends; i++) {
3260 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3261 grp = b->ops->nw_getgrnam(b, name);
3262 if (grp) {
3263 return grp;
3267 return NULL;
3270 struct group *getgrnam(const char *name)
3272 if (!nss_wrapper_enabled()) {
3273 return libc_getgrnam(name);
3276 return nwrap_getgrnam(name);
3279 /****************************************************************************
3280 * GETGRNAM_R
3281 ***************************************************************************/
3283 static int nwrap_getgrnam_r(const char *name, struct group *grdst,
3284 char *buf, size_t buflen, struct group **grdstp)
3286 int i, ret;
3288 for (i=0; i < nwrap_main_global->num_backends; i++) {
3289 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3290 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
3291 if (ret == ENOENT) {
3292 continue;
3294 return ret;
3297 return ENOENT;
3300 #ifdef HAVE_GETGRNAM_R
3301 # ifdef HAVE_SOLARIS_GETGRNAM_R
3302 int getgrnam_r(const char *name, struct group *grp,
3303 char *buf, int buflen, struct group **pgrp)
3304 # else /* HAVE_SOLARIS_GETGRNAM_R */
3305 int getgrnam_r(const char *name, struct group *grp,
3306 char *buf, size_t buflen, struct group **pgrp)
3307 # endif /* HAVE_SOLARIS_GETGRNAM_R */
3309 if (!nss_wrapper_enabled()) {
3310 return libc_getgrnam_r(name,
3311 grp,
3312 buf,
3313 buflen,
3314 pgrp);
3317 return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
3319 #endif /* HAVE_GETGRNAM_R */
3321 /****************************************************************************
3322 * GETGRGID
3323 ***************************************************************************/
3325 static struct group *nwrap_getgrgid(gid_t gid)
3327 int i;
3328 struct group *grp;
3330 for (i=0; i < nwrap_main_global->num_backends; i++) {
3331 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3332 grp = b->ops->nw_getgrgid(b, gid);
3333 if (grp) {
3334 return grp;
3338 return NULL;
3341 struct group *getgrgid(gid_t gid)
3343 if (!nss_wrapper_enabled()) {
3344 return libc_getgrgid(gid);
3347 return nwrap_getgrgid(gid);
3350 /****************************************************************************
3351 * GETGRGID_R
3352 ***************************************************************************/
3354 static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
3355 char *buf, size_t buflen, struct group **grdstp)
3357 int i,ret;
3359 for (i=0; i < nwrap_main_global->num_backends; i++) {
3360 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3361 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
3362 if (ret == ENOENT) {
3363 continue;
3365 return ret;
3368 return ENOENT;
3371 #ifdef HAVE_GETGRGID_R
3372 # ifdef HAVE_SOLARIS_GETGRGID_R
3373 int getgrgid_r(gid_t gid, struct group *grdst,
3374 char *buf, int buflen, struct group **grdstp)
3375 # else /* HAVE_SOLARIS_GETGRGID_R */
3376 int getgrgid_r(gid_t gid, struct group *grdst,
3377 char *buf, size_t buflen, struct group **grdstp)
3378 # endif /* HAVE_SOLARIS_GETGRGID_R */
3380 if (!nss_wrapper_enabled()) {
3381 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
3384 return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
3386 #endif
3388 /****************************************************************************
3389 * SETGRENT
3390 ***************************************************************************/
3392 static void nwrap_setgrent(void)
3394 int i;
3396 for (i=0; i < nwrap_main_global->num_backends; i++) {
3397 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3398 b->ops->nw_setgrent(b);
3402 #ifdef HAVE_BSD_SETGRENT
3403 int setgrent(void)
3404 #else
3405 void setgrent(void)
3406 #endif
3408 if (!nss_wrapper_enabled()) {
3409 libc_setgrent();
3410 goto out;
3413 nwrap_setgrent();
3415 out:
3416 #ifdef HAVE_BSD_SETGRENT
3417 return 0;
3418 #else
3419 return;
3420 #endif
3423 /****************************************************************************
3424 * GETGRENT
3425 ***************************************************************************/
3427 static struct group *nwrap_getgrent(void)
3429 int i;
3430 struct group *grp;
3432 for (i=0; i < nwrap_main_global->num_backends; i++) {
3433 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3434 grp = b->ops->nw_getgrent(b);
3435 if (grp) {
3436 return grp;
3440 return NULL;
3443 struct group *getgrent(void)
3445 if (!nss_wrapper_enabled()) {
3446 return libc_getgrent();
3449 return nwrap_getgrent();
3452 /****************************************************************************
3453 * GETGRENT_R
3454 ***************************************************************************/
3456 static int nwrap_getgrent_r(struct group *grdst, char *buf,
3457 size_t buflen, struct group **grdstp)
3459 int i,ret;
3461 for (i=0; i < nwrap_main_global->num_backends; i++) {
3462 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3463 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
3464 if (ret == ENOENT) {
3465 continue;
3467 return ret;
3470 return ENOENT;
3473 #ifdef HAVE_SOLARIS_GETGRENT_R
3474 struct group *getgrent_r(struct group *src, char *buf, int buflen)
3476 struct group *grdstp = NULL;
3477 int rc;
3479 if (!nss_wrapper_enabled()) {
3480 return libc_getgrent_r(src, buf, buflen);
3483 rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
3484 if (rc < 0) {
3485 return NULL;
3488 return grdstp;
3490 #else /* HAVE_SOLARIS_GETGRENT_R */
3491 int getgrent_r(struct group *src, char *buf,
3492 size_t buflen, struct group **grdstp)
3494 if (!nss_wrapper_enabled()) {
3495 return libc_getgrent_r(src, buf, buflen, grdstp);
3498 return nwrap_getgrent_r(src, buf, buflen, grdstp);
3500 #endif /* HAVE_SOLARIS_GETGRENT_R */
3502 /****************************************************************************
3503 * ENDGRENT
3504 ***************************************************************************/
3506 static void nwrap_endgrent(void)
3508 int i;
3510 for (i=0; i < nwrap_main_global->num_backends; i++) {
3511 struct nwrap_backend *b = &nwrap_main_global->backends[i];
3512 b->ops->nw_endgrent(b);
3516 void endgrent(void)
3518 if (!nss_wrapper_enabled()) {
3519 libc_endgrent();
3520 return;
3523 nwrap_endgrent();
3526 /****************************************************************************
3527 * GETGROUPLIST
3528 ***************************************************************************/
3530 #ifdef HAVE_GETGROUPLIST
3531 static int nwrap_getgrouplist(const char *user, gid_t group,
3532 gid_t *groups, int *ngroups)
3534 struct group *grp;
3535 gid_t *groups_tmp;
3536 int count = 1;
3537 const char *name_of_group = "";
3539 NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
3541 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
3542 if (!groups_tmp) {
3543 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
3544 errno = ENOMEM;
3545 return -1;
3548 memcpy(groups_tmp, &group, sizeof(gid_t));
3550 grp = nwrap_getgrgid(group);
3551 if (grp) {
3552 name_of_group = grp->gr_name;
3555 nwrap_setgrent();
3556 while ((grp = nwrap_getgrent()) != NULL) {
3557 int i = 0;
3559 NWRAP_LOG(NWRAP_LOG_DEBUG,
3560 "Inspecting %s for group membership",
3561 grp->gr_name);
3563 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
3565 if ((strcmp(user, grp->gr_mem[i]) == 0) &&
3566 (strcmp(name_of_group, grp->gr_name) != 0)) {
3568 NWRAP_LOG(NWRAP_LOG_DEBUG,
3569 "%s is member of %s",
3570 user,
3571 grp->gr_name);
3573 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
3574 if (!groups_tmp) {
3575 NWRAP_LOG(NWRAP_LOG_ERROR,
3576 "Out of memory");
3577 errno = ENOMEM;
3578 return -1;
3581 memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t));
3582 count++;
3587 nwrap_endgrent();
3589 NWRAP_LOG(NWRAP_LOG_DEBUG,
3590 "%s is member of %d groups",
3591 user, *ngroups);
3593 if (*ngroups < count) {
3594 *ngroups = count;
3595 free(groups_tmp);
3596 return -1;
3599 *ngroups = count;
3600 memcpy(groups, groups_tmp, count * sizeof(gid_t));
3601 free(groups_tmp);
3603 return count;
3606 int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
3608 if (!nss_wrapper_enabled()) {
3609 return libc_getgrouplist(user, group, groups, ngroups);
3612 return nwrap_getgrouplist(user, group, groups, ngroups);
3614 #endif
3616 /**********************************************************
3617 * NETDB
3618 **********************************************************/
3620 static void nwrap_sethostent(int stayopen) {
3621 (void) stayopen; /* ignored */
3623 nwrap_files_sethostent();
3626 #ifdef HAVE_SOLARIS_SETHOSTENT
3627 int sethostent(int stayopen)
3629 if (!nss_wrapper_hosts_enabled()) {
3630 libc_sethostent(stayopen);
3631 return 0;
3634 nwrap_sethostent(stayopen);
3636 return 0;
3638 #else /* HAVE_SOLARIS_SETHOSTENT */
3639 void sethostent(int stayopen)
3641 if (!nss_wrapper_hosts_enabled()) {
3642 libc_sethostent(stayopen);
3643 return;
3646 nwrap_sethostent(stayopen);
3648 #endif /* HAVE_SOLARIS_SETHOSTENT */
3650 static struct hostent *nwrap_gethostent(void)
3652 return nwrap_files_gethostent();
3655 struct hostent *gethostent(void) {
3656 if (!nss_wrapper_hosts_enabled()) {
3657 return libc_gethostent();
3660 return nwrap_gethostent();
3663 static void nwrap_endhostent(void) {
3664 nwrap_files_endhostent();
3667 #ifdef HAVE_SOLARIS_ENDHOSTENT
3668 int endhostent(void)
3670 if (!nss_wrapper_hosts_enabled()) {
3671 libc_endhostent();
3672 return 0;
3675 nwrap_endhostent();
3677 return 0;
3679 #else /* HAVE_SOLARIS_ENDHOSTENT */
3680 void endhostent(void)
3682 if (!nss_wrapper_hosts_enabled()) {
3683 libc_endhostent();
3684 return;
3687 nwrap_endhostent();
3689 #endif /* HAVE_SOLARIS_ENDHOSTENT */
3691 static struct hostent *nwrap_gethostbyname(const char *name)
3693 return nwrap_files_gethostbyname(name, AF_UNSPEC);
3696 struct hostent *gethostbyname(const char *name)
3698 if (!nss_wrapper_hosts_enabled()) {
3699 return libc_gethostbyname(name);
3702 return nwrap_gethostbyname(name);
3705 /* This is a GNU extension */
3706 #ifdef HAVE_GETHOSTBYNAME2
3707 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
3709 return nwrap_files_gethostbyname(name, af);
3712 struct hostent *gethostbyname2(const char *name, int af)
3714 if (!nss_wrapper_hosts_enabled()) {
3715 return libc_gethostbyname2(name, af);
3718 return nwrap_gethostbyname2(name, af);
3720 #endif
3722 static struct hostent *nwrap_gethostbyaddr(const void *addr,
3723 socklen_t len, int type)
3725 return nwrap_files_gethostbyaddr(addr, len, type);
3728 struct hostent *gethostbyaddr(const void *addr,
3729 socklen_t len, int type)
3731 if (!nss_wrapper_hosts_enabled()) {
3732 return libc_gethostbyaddr(addr, len, type);
3735 return nwrap_gethostbyaddr(addr, len, type);
3738 static const struct addrinfo default_hints =
3740 .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
3741 .ai_family = AF_UNSPEC,
3742 .ai_socktype = 0,
3743 .ai_protocol = 0,
3744 .ai_addrlen = 0,
3745 .ai_addr = NULL,
3746 .ai_canonname = NULL,
3747 .ai_next = NULL
3750 static int nwrap_convert_he_ai(const struct hostent *he,
3751 unsigned short port,
3752 const struct addrinfo *hints,
3753 struct addrinfo **pai)
3755 struct addrinfo *ai;
3756 socklen_t socklen;
3758 switch (he->h_addrtype) {
3759 case AF_INET:
3760 socklen = sizeof(struct sockaddr_in);
3761 break;
3762 #ifdef HAVE_IPV6
3763 case AF_INET6:
3764 socklen = sizeof(struct sockaddr_in6);
3765 break;
3766 #endif
3767 default:
3768 return EAI_FAMILY;
3771 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
3772 if (ai == NULL) {
3773 return EAI_MEMORY;
3776 ai->ai_flags = 0;
3777 ai->ai_family = he->h_addrtype;
3778 ai->ai_socktype = hints->ai_socktype;
3779 ai->ai_protocol = hints->ai_protocol;
3781 ai->ai_addrlen = socklen;
3782 ai->ai_addr = (void *)(ai + 1);
3784 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3785 ai->ai_addr->sa_len = socklen;
3786 #endif
3787 ai->ai_addr->sa_family = he->h_addrtype;
3789 switch (he->h_addrtype) {
3790 case AF_INET:
3792 struct sockaddr_in *sinp =
3793 (struct sockaddr_in *) ai->ai_addr;
3795 memset(sinp, 0, sizeof(struct sockaddr_in));
3797 sinp->sin_port = htons(port);
3798 sinp->sin_family = AF_INET;
3800 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
3801 memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
3804 break;
3805 #ifdef HAVE_IPV6
3806 case AF_INET6:
3808 struct sockaddr_in6 *sin6p =
3809 (struct sockaddr_in6 *) ai->ai_addr;
3811 memset(sin6p, 0, sizeof(struct sockaddr_in6));
3813 sin6p->sin6_port = htons(port);
3814 sin6p->sin6_family = AF_INET6;
3816 memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length);
3818 break;
3819 #endif
3822 ai->ai_next = NULL;
3824 if (he->h_name) {
3825 ai->ai_canonname = strdup(he->h_name);
3826 if (ai->ai_canonname == NULL) {
3827 freeaddrinfo(ai);
3828 return EAI_MEMORY;
3832 *pai = ai;
3833 return 0;
3836 static int nwrap_getaddrinfo(const char *node,
3837 const char *service,
3838 const struct addrinfo *hints,
3839 struct addrinfo **res)
3841 struct addrinfo *ai = NULL;
3842 struct addrinfo *p = NULL;
3843 unsigned short port = 0;
3844 struct hostent *he;
3845 struct in_addr in;
3846 bool is_addr_ipv4 = false;
3847 bool is_addr_ipv6 = false;
3848 int eai = EAI_SYSTEM;
3849 int ret;
3850 int rc;
3851 int af;
3853 if (node == NULL && service == NULL) {
3854 return EAI_NONAME;
3857 ret = libc_getaddrinfo(node, service, hints, &p);
3858 if (ret == 0) {
3859 *res = p;
3862 /* If no node has been specified, let glibc deal with it */
3863 if (node == NULL) {
3864 return ret;
3867 if (hints == NULL) {
3868 hints = &default_hints;
3871 if ((hints->ai_flags & AI_CANONNAME) && node == NULL) {
3872 return EAI_BADFLAGS;
3875 if (service != NULL && service[0] != '\0') {
3876 if (isdigit((int)service[0])) {
3877 port = (unsigned short)atoi(service);
3878 } else {
3879 const char *proto = NULL;
3880 struct servent *s;
3882 if (hints->ai_protocol != 0) {
3883 struct protoent *pent;
3885 pent = getprotobynumber(hints->ai_protocol);
3886 if (pent != NULL) {
3887 proto = pent->p_name;
3891 s = getservbyname(service, proto);
3892 if (s != NULL) {
3893 port = ntohs(s->s_port);
3894 } else {
3895 if (p != NULL) {
3896 freeaddrinfo(p);
3898 return EAI_SERVICE;
3903 af = hints->ai_family;
3904 if (af == AF_UNSPEC) {
3905 af = AF_INET;
3908 rc = inet_pton(af, node, &in);
3909 if (rc == 1) {
3910 is_addr_ipv4 = true;
3911 if (af == AF_UNSPEC) {
3912 af = AF_INET;
3914 #ifdef HAVE_IPV6
3915 } else {
3916 struct in6_addr in6;
3918 af = AF_INET6;
3920 rc = inet_pton(af, node, &in6);
3921 if (rc == 1) {
3922 is_addr_ipv6 = true;
3924 #endif
3927 if (is_addr_ipv4) {
3928 he = nwrap_files_gethostbyaddr(&in, sizeof(struct in_addr), af);
3929 if (he != NULL) {
3930 rc = nwrap_convert_he_ai(he, port, hints, &ai);
3931 } else {
3932 eai = EAI_NODATA;
3933 rc = -1;
3935 #ifdef HAVE_IPV6
3936 } else if (is_addr_ipv6) {
3937 struct in6_addr in6;
3939 rc = inet_pton(af, node, &in6);
3940 if (rc <= 0) {
3941 eai = EAI_ADDRFAMILY;
3942 return ret == 0 ? 0 : eai;
3945 he = nwrap_files_gethostbyaddr(&in6,
3946 sizeof(struct in6_addr),
3947 af);
3948 if (he != NULL) {
3949 rc = nwrap_convert_he_ai(he, port, hints, &ai);
3950 eai = rc;
3951 } else {
3952 eai = EAI_NODATA;
3953 rc = -1;
3955 #endif
3956 } else {
3957 he = nwrap_files_gethostbyname(node, hints->ai_family);
3958 if (he != NULL) {
3959 rc = nwrap_convert_he_ai(he, port, hints, &ai);
3960 eai = rc;
3961 } else {
3962 eai = EAI_NODATA;
3963 rc = -1;
3967 if (rc < 0) {
3968 return ret == 0 ? 0 : eai;
3971 if (ret == 0) {
3972 freeaddrinfo(p);
3975 if (ai->ai_flags == 0) {
3976 ai->ai_flags = hints->ai_flags;
3978 if (ai->ai_socktype == 0) {
3979 ai->ai_socktype = SOCK_DGRAM;
3981 if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) {
3982 ai->ai_protocol = 17; /* UDP */
3983 } else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
3984 ai->ai_protocol = 6; /* TCP */
3987 if (hints->ai_socktype == 0) {
3988 /* Add second ai */
3989 rc = nwrap_convert_he_ai(he, port, hints, &ai->ai_next);
3990 if (rc < 0) {
3991 freeaddrinfo(ai);
3992 return rc;
3995 if (ai->ai_next->ai_flags == 0) {
3996 ai->ai_next->ai_flags = hints->ai_flags;
3998 if (ai->ai_socktype == SOCK_DGRAM) {
3999 ai->ai_next->ai_socktype = SOCK_STREAM;
4000 } else if (ai->ai_socktype == SOCK_STREAM) {
4001 ai->ai_next->ai_socktype = SOCK_DGRAM;
4003 if (ai->ai_next->ai_socktype == SOCK_DGRAM) {
4004 ai->ai_next->ai_protocol = 17; /* UDP */
4005 } else if (ai->ai_next->ai_socktype == SOCK_STREAM) {
4006 ai->ai_next->ai_protocol = 6; /* TCP */
4010 *res = ai;
4012 return 0;
4015 int getaddrinfo(const char *node, const char *service,
4016 const struct addrinfo *hints,
4017 struct addrinfo **res)
4019 if (!nss_wrapper_hosts_enabled()) {
4020 return libc_getaddrinfo(node, service, hints, res);
4023 return nwrap_getaddrinfo(node, service, hints, res);
4026 static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
4027 char *host, size_t hostlen,
4028 char *serv, size_t servlen,
4029 int flags)
4031 struct hostent *he;
4032 struct servent *service;
4033 const char *proto;
4034 const void *addr;
4035 socklen_t addrlen;
4036 uint16_t port;
4037 sa_family_t type;
4039 if (sa == NULL || salen < sizeof(sa_family_t)) {
4040 return EAI_FAMILY;
4043 if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
4044 return EAI_NONAME;
4047 type = sa->sa_family;
4048 switch (type) {
4049 case AF_INET:
4050 if (salen < sizeof(struct sockaddr_in))
4051 return EAI_FAMILY;
4052 addr = &((const struct sockaddr_in *)sa)->sin_addr;
4053 addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
4054 port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
4055 break;
4056 #ifdef HAVE_IPV6
4057 case AF_INET6:
4058 if (salen < sizeof(struct sockaddr_in6))
4059 return EAI_FAMILY;
4060 addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
4061 addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
4062 port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
4063 break;
4064 #endif
4065 default:
4066 return EAI_FAMILY;
4069 if (host != NULL) {
4070 he = NULL;
4071 if ((flags & NI_NUMERICHOST) == 0) {
4072 he = nwrap_files_gethostbyaddr(addr, addrlen, type);
4073 if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
4074 return EAI_NONAME;
4076 if (he != NULL && he->h_name != NULL) {
4077 if (strlen(he->h_name) >= hostlen)
4078 return EAI_OVERFLOW;
4079 strcpy(host, he->h_name);
4080 if (flags & NI_NOFQDN)
4081 host[strcspn(host, ".")] = '\0';
4082 } else {
4083 if (inet_ntop(type, addr, host, hostlen) == NULL)
4084 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
4088 if (serv != NULL) {
4089 service = NULL;
4090 if ((flags & NI_NUMERICSERV) == 0) {
4091 proto = (flags & NI_DGRAM) ? "udp" : "tcp";
4092 service = getservbyport(htons(port), proto);
4094 if (service != NULL) {
4095 if (strlen(service->s_name) >= servlen)
4096 return EAI_OVERFLOW;
4097 strcpy(serv, service->s_name);
4098 } else {
4099 if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
4100 return EAI_OVERFLOW;
4104 return 0;
4107 #ifdef HAVE_LINUX_GETNAMEINFO
4108 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4109 char *host, socklen_t hostlen,
4110 char *serv, socklen_t servlen,
4111 int flags)
4112 #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
4113 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4114 char *host, socklen_t hostlen,
4115 char *serv, socklen_t servlen,
4116 unsigned int flags)
4117 #else
4118 int getnameinfo(const struct sockaddr *sa, socklen_t salen,
4119 char *host, size_t hostlen,
4120 char *serv, size_t servlen,
4121 int flags)
4122 #endif
4124 if (!nss_wrapper_hosts_enabled()) {
4125 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
4128 return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
4131 static int nwrap_gethostname(char *name, size_t len)
4133 const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
4135 if (strlen(hostname) >= len) {
4136 errno = ENAMETOOLONG;
4137 return -1;
4139 snprintf(name, len, "%s", hostname);
4141 return 0;
4144 #ifdef HAVE_SOLARIS_GETHOSTNAME
4145 int gethostname(char *name, int len)
4146 #else /* HAVE_SOLARIS_GETHOSTNAME */
4147 int gethostname(char *name, size_t len)
4148 #endif /* HAVE_SOLARIS_GETHOSTNAME */
4150 if (!nwrap_hostname_enabled()) {
4151 return libc_gethostname(name, len);
4154 return nwrap_gethostname(name, len);
4157 /****************************
4158 * DESTRUCTOR
4159 ***************************/
4162 * This function is called when the library is unloaded and makes sure that
4163 * sockets get closed and the unix file for the socket are unlinked.
4165 void nwrap_destructor(void)
4167 int i;
4169 if (nwrap_main_global != NULL) {
4170 struct nwrap_main *m = nwrap_main_global;
4172 /* libc */
4173 SAFE_FREE(m->libc->fns);
4174 if (m->libc->handle != NULL) {
4175 dlclose(m->libc->handle);
4177 if (m->libc->nsl_handle != NULL) {
4178 dlclose(m->libc->nsl_handle);
4180 if (m->libc->sock_handle != NULL) {
4181 dlclose(m->libc->sock_handle);
4183 SAFE_FREE(m->libc);
4185 /* backends */
4186 for (i = 0; i < m->num_backends; i++) {
4187 struct nwrap_backend *b = &(m->backends[i]);
4189 if (b->so_handle != NULL) {
4190 dlclose(b->so_handle);
4192 SAFE_FREE(b->fns);
4194 SAFE_FREE(m->backends);
4197 if (nwrap_pw_global.cache != NULL) {
4198 struct nwrap_cache *c = nwrap_pw_global.cache;
4200 nwrap_files_cache_unload(c);
4201 if (c->fd >= 0) {
4202 close(c->fd);
4205 SAFE_FREE(nwrap_pw_global.list);
4206 nwrap_pw_global.num = 0;
4209 if (nwrap_gr_global.cache != NULL) {
4210 struct nwrap_cache *c = nwrap_gr_global.cache;
4212 nwrap_files_cache_unload(c);
4213 if (c->fd >= 0) {
4214 close(c->fd);
4217 SAFE_FREE(nwrap_gr_global.list);
4218 nwrap_pw_global.num = 0;
4221 if (nwrap_he_global.cache != NULL) {
4222 struct nwrap_cache *c = nwrap_he_global.cache;
4224 nwrap_files_cache_unload(c);
4225 if (c->fd >= 0) {
4226 close(c->fd);
4229 SAFE_FREE(nwrap_he_global.list);
4230 nwrap_he_global.num = 0;