LCOV - code coverage report
Current view: top level - third_party/nss_wrapper - nss_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1435 2351 61.0 %
Date: 2024-06-13 04:01:37 Functions: 111 155 71.6 %

          Line data    Source code
       1             : /*
       2             :  * BSD 3-Clause License
       3             :  *
       4             :  * Copyright (c) 2007,      Stefan Metzmacher <metze@samba.org>
       5             :  * Copyright (c) 2009,      Guenther Deschner <gd@samba.org>
       6             :  * Copyright (c) 2014-2015, Michael Adam <obnox@samba.org>
       7             :  * Copyright (c) 2015,      Robin Hack <hack.robin@gmail.com>
       8             :  * Copyright (c) 2013-2018, Andreas Schneider <asn@samba.org>
       9             :  * All rights reserved.
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  *
      15             :  * 1. Redistributions of source code must retain the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer.
      17             :  *
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  *
      22             :  * 3. Neither the name of the author nor the names of its contributors
      23             :  *    may be used to endorse or promote products derived from this software
      24             :  *    without specific prior written permission.
      25             :  *
      26             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      27             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      28             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      29             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      30             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      31             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      32             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      33             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      34             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      35             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      36             :  * SUCH DAMAGE.
      37             :  */
      38             : 
      39             : #include "config.h"
      40             : 
      41             : #include <pthread.h>
      42             : 
      43             : #include <sys/types.h>
      44             : #include <sys/stat.h>
      45             : #include <sys/socket.h>
      46             : #include <errno.h>
      47             : #include <fcntl.h>
      48             : #include <stdarg.h>
      49             : #include <stdbool.h>
      50             : #include <stddef.h>
      51             : #include <stdio.h>
      52             : #include <stdint.h>
      53             : #include <stdlib.h>
      54             : #include <string.h>
      55             : #include <unistd.h>
      56             : #include <ctype.h>
      57             : 
      58             : #include <netinet/in.h>
      59             : 
      60             : #include <search.h>
      61             : #include <assert.h>
      62             : 
      63             : /*
      64             :  * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h  gives us
      65             :  * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
      66             :  * Solaris
      67             :  */
      68             : #ifndef _POSIX_PTHREAD_SEMANTICS
      69             : #define _POSIX_PTHREAD_SEMANTICS
      70             : #endif
      71             : 
      72             : #include <pwd.h>
      73             : #include <grp.h>
      74             : #ifdef HAVE_SHADOW_H
      75             : #include <shadow.h>
      76             : #endif /* HAVE_SHADOW_H */
      77             : 
      78             : #include <netdb.h>
      79             : #include <arpa/inet.h>
      80             : #include <netinet/in.h>
      81             : 
      82             : #include <dlfcn.h>
      83             : 
      84             : #if defined(HAVE_NSS_H)
      85             : /* Linux and BSD */
      86             : #include <nss.h>
      87             : 
      88             : typedef enum nss_status NSS_STATUS;
      89             : #elif defined(HAVE_NSS_COMMON_H)
      90             : /* Solaris */
      91             : #include <nss_common.h>
      92             : #include <nss_dbdefs.h>
      93             : #include <nsswitch.h>
      94             : 
      95             : typedef nss_status_t NSS_STATUS;
      96             : 
      97             : # define NSS_STATUS_SUCCESS     NSS_SUCCESS
      98             : # define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
      99             : # define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
     100             : # define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
     101             : #else
     102             : # error "No nsswitch support detected"
     103             : #endif
     104             : 
     105             : #ifndef PTR_DIFF
     106             : #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
     107             : #endif
     108             : 
     109             : #ifndef _PUBLIC_
     110             : #define _PUBLIC_
     111             : #endif
     112             : 
     113             : #ifndef EAI_NODATA
     114             : #define EAI_NODATA EAI_NONAME
     115             : #endif
     116             : 
     117             : #ifndef EAI_ADDRFAMILY
     118             : #define EAI_ADDRFAMILY EAI_FAMILY
     119             : #endif
     120             : 
     121             : #ifndef __STRING
     122             : #define __STRING(x)    #x
     123             : #endif
     124             : 
     125             : #ifndef __STRINGSTRING
     126             : #define __STRINGSTRING(x) __STRING(x)
     127             : #endif
     128             : 
     129             : #ifndef __LINESTR__
     130             : #define __LINESTR__ __STRINGSTRING(__LINE__)
     131             : #endif
     132             : 
     133             : #ifndef __location__
     134             : #define __location__ __FILE__ ":" __LINESTR__
     135             : #endif
     136             : 
     137             : #ifndef DNS_NAME_MAX
     138             : #define DNS_NAME_MAX 255
     139             : #endif
     140             : 
     141             : /* GCC have printf type attribute check. */
     142             : #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
     143             : #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
     144             : #else
     145             : #define PRINTF_ATTRIBUTE(a,b)
     146             : #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
     147             : 
     148             : #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
     149             : #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
     150             : #else
     151             : #define CONSTRUCTOR_ATTRIBUTE
     152             : #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
     153             : 
     154             : #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
     155             : #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
     156             : #else
     157             : #define DESTRUCTOR_ATTRIBUTE
     158             : #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
     159             : 
     160             : #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
     161             : 
     162             : #ifndef SAFE_FREE
     163             : #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
     164             : #endif
     165             : 
     166             : #ifndef discard_const
     167             : #define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
     168             : #endif
     169             : 
     170             : #ifndef discard_const_p
     171             : #define discard_const_p(type, ptr) ((type *)discard_const(ptr))
     172             : #endif
     173             : 
     174             : #ifdef HAVE_IPV6
     175             : #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
     176             : #else
     177             : #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
     178             : #endif
     179             : 
     180             : #define NWRAP_LOCK(m) do { \
     181             :         pthread_mutex_lock(&( m ## _mutex)); \
     182             : } while(0)
     183             : 
     184             : #define NWRAP_UNLOCK(m) do { \
     185             :         pthread_mutex_unlock(&( m ## _mutex)); \
     186             : } while(0)
     187             : 
     188             : static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
     189             : static pthread_mutex_t nss_module_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
     190             : 
     191             : static bool nwrap_initialized = false;
     192             : static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
     193             : 
     194             : /* The mutex or accessing the id */
     195             : static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     196             : static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     197             : static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     198             : static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     199             : static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     200             : 
     201             : /* Add new global locks here please */
     202             : /* Also don't forget to add locks to
     203             :  * nwrap_init() function.
     204             :  */
     205             : # define NWRAP_LOCK_ALL do { \
     206             :         NWRAP_LOCK(libc_symbol_binding); \
     207             :         NWRAP_LOCK(nss_module_symbol_binding); \
     208             :         NWRAP_LOCK(nwrap_initialized); \
     209             :         NWRAP_LOCK(nwrap_global); \
     210             :         NWRAP_LOCK(nwrap_gr_global); \
     211             :         NWRAP_LOCK(nwrap_he_global); \
     212             :         NWRAP_LOCK(nwrap_pw_global); \
     213             :         NWRAP_LOCK(nwrap_sp_global); \
     214             : } while (0);
     215             : 
     216             : # define NWRAP_UNLOCK_ALL do {\
     217             :         NWRAP_UNLOCK(nwrap_sp_global); \
     218             :         NWRAP_UNLOCK(nwrap_pw_global); \
     219             :         NWRAP_UNLOCK(nwrap_he_global); \
     220             :         NWRAP_UNLOCK(nwrap_gr_global); \
     221             :         NWRAP_UNLOCK(nwrap_global); \
     222             :         NWRAP_UNLOCK(nwrap_initialized); \
     223             :         NWRAP_UNLOCK(nss_module_symbol_binding); \
     224             :         NWRAP_UNLOCK(libc_symbol_binding); \
     225             : } while (0);
     226             : 
     227             : static void nwrap_init(void);
     228             : 
     229      419767 : static void nwrap_thread_prepare(void)
     230             : {
     231      419767 :         nwrap_init();
     232      419767 :         NWRAP_LOCK_ALL;
     233      419767 : }
     234             : 
     235      402091 : static void nwrap_thread_parent(void)
     236             : {
     237      402091 :         NWRAP_UNLOCK_ALL;
     238      402091 : }
     239             : 
     240       17676 : static void nwrap_thread_child(void)
     241             : {
     242       17676 :         NWRAP_UNLOCK_ALL;
     243       17676 : }
     244             : 
     245             : enum nwrap_dbglvl_e {
     246             :         NWRAP_LOG_ERROR = 0,
     247             :         NWRAP_LOG_WARN,
     248             :         NWRAP_LOG_DEBUG,
     249             :         NWRAP_LOG_TRACE
     250             : };
     251             : 
     252             : #ifndef HAVE_GETPROGNAME
     253     3745300 : static const char *getprogname(void)
     254             : {
     255             : #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
     256     3745300 :         return program_invocation_short_name;
     257             : #elif defined(HAVE_GETEXECNAME)
     258             :         return getexecname();
     259             : #else
     260             :         return NULL;
     261             : #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
     262             : }
     263             : #endif /* HAVE_GETPROGNAME */
     264             : 
     265             : static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
     266             : # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
     267             : 
     268     3745300 : static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
     269             :                       const char *func,
     270             :                       const char *format, ...)
     271             : {
     272             :         char buffer[1024];
     273             :         va_list va;
     274             :         const char *d;
     275     3745300 :         unsigned int lvl = 0;
     276     3745300 :         const char *prefix = "NWRAP";
     277     3745300 :         const char *progname = getprogname();
     278             : 
     279     3745300 :         d = getenv("NSS_WRAPPER_DEBUGLEVEL");
     280     3745300 :         if (d != NULL) {
     281           0 :                 lvl = atoi(d);
     282             :         }
     283             : 
     284     3745300 :         if (lvl < dbglvl) {
     285     3745300 :                 return;
     286             :         }
     287             : 
     288           0 :         va_start(va, format);
     289           0 :         vsnprintf(buffer, sizeof(buffer), format, va);
     290           0 :         va_end(va);
     291             : 
     292           0 :         switch (dbglvl) {
     293           0 :                 case NWRAP_LOG_ERROR:
     294           0 :                         prefix = "NWRAP_ERROR";
     295           0 :                         break;
     296           0 :                 case NWRAP_LOG_WARN:
     297           0 :                         prefix = "NWRAP_WARN";
     298           0 :                         break;
     299           0 :                 case NWRAP_LOG_DEBUG:
     300           0 :                         prefix = "NWRAP_DEBUG";
     301           0 :                         break;
     302           0 :                 case NWRAP_LOG_TRACE:
     303           0 :                         prefix = "NWRAP_TRACE";
     304           0 :                         break;
     305             :         }
     306             : 
     307           0 :         if (progname == NULL) {
     308           0 :                 progname = "<unknown>";
     309             :         }
     310             : 
     311           0 :         fprintf(stderr,
     312             :                 "%s[%s (%u)] - %s: %s\n",
     313             :                 prefix,
     314             :                 progname,
     315           0 :                 (unsigned int)getpid(),
     316             :                 func,
     317             :                 buffer);
     318             : }
     319             : 
     320             : /*****************
     321             :  * LIBC
     322             :  *****************/
     323             : 
     324             : #define LIBC_NAME "libc.so"
     325             : 
     326             : typedef struct passwd *(*__libc_getpwnam)(const char *name);
     327             : 
     328             : typedef int (*__libc_getpwnam_r)(const char *name,
     329             :                                  struct passwd *pwd,
     330             :                                  char *buf,
     331             :                                  size_t buflen,
     332             :                                  struct passwd **result);
     333             : 
     334             : typedef struct passwd *(*__libc_getpwuid)(uid_t uid);
     335             : 
     336             : typedef int (*__libc_getpwuid_r)(uid_t uid,
     337             :                                  struct passwd *pwd,
     338             :                                  char *buf,
     339             :                                  size_t buflen,
     340             :                                  struct passwd **result);
     341             : 
     342             : typedef void (*__libc_setpwent)(void);
     343             : 
     344             : typedef struct passwd *(*__libc_getpwent)(void);
     345             : 
     346             : #ifdef HAVE_GETPWENT_R
     347             : # ifdef HAVE_SOLARIS_GETPWENT_R
     348             : typedef struct passwd *(*__libc_getpwent_r)(struct passwd *pwbuf,
     349             :                                             char *buf,
     350             :                                             size_t buflen);
     351             : # else /* HAVE_SOLARIS_GETPWENT_R */
     352             : typedef int (*__libc_getpwent_r)(struct passwd *pwbuf,
     353             :                                  char *buf,
     354             :                                  size_t buflen,
     355             :                                  struct passwd **pwbufp);
     356             : # endif /* HAVE_SOLARIS_GETPWENT_R */
     357             : #endif /* HAVE_GETPWENT_R */
     358             : 
     359             : typedef void (*__libc_endpwent)(void);
     360             : 
     361             : typedef int (*__libc_initgroups)(const char *user, gid_t gid);
     362             : 
     363             : typedef struct group *(*__libc_getgrnam)(const char *name);
     364             : 
     365             : typedef int (*__libc_getgrnam_r)(const char *name,
     366             :                                  struct group *grp,
     367             :                                  char *buf,
     368             :                                  size_t buflen,
     369             :                                  struct group **result);
     370             : 
     371             : typedef struct group *(*__libc_getgrgid)(gid_t gid);
     372             : 
     373             : typedef int (*__libc_getgrgid_r)(gid_t gid,
     374             :                                  struct group *grp,
     375             :                                  char *buf,
     376             :                                  size_t buflen,
     377             :                                  struct group **result);
     378             : 
     379             : typedef void (*__libc_setgrent)(void);
     380             : 
     381             : typedef struct group *(*__libc_getgrent)(void);
     382             : 
     383             : #ifdef HAVE_GETGRENT_R
     384             : # ifdef HAVE_SOLARIS_GETGRENT_R
     385             : typedef struct group *(*__libc_getgrent_r)(struct group *group,
     386             :                                            char *buf,
     387             :                                            size_t buflen);
     388             : # else /* HAVE_SOLARIS_GETGRENT_R */
     389             : typedef int (*__libc_getgrent_r)(struct group *group,
     390             :                                  char *buf,
     391             :                                  size_t buflen,
     392             :                                  struct group **result);
     393             : # endif /* HAVE_SOLARIS_GETGRENT_R */
     394             : #endif /* HAVE_GETGRENT_R */
     395             : 
     396             : typedef void (*__libc_endgrent)(void);
     397             : 
     398             : typedef int (*__libc_getgrouplist)(const char *user,
     399             :                                    gid_t group,
     400             :                                    gid_t *groups,
     401             :                                    int *ngroups);
     402             : 
     403             : typedef void (*__libc_sethostent)(int stayopen);
     404             : 
     405             : typedef struct hostent *(*__libc_gethostent)(void);
     406             : 
     407             : typedef void (*__libc_endhostent)(void);
     408             : 
     409             : typedef struct hostent *(*__libc_gethostbyname)(const char *name);
     410             : 
     411             : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
     412             : typedef struct hostent *(*__libc_gethostbyname2)(const char *name, int af);
     413             : #endif
     414             : 
     415             : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
     416             : typedef int (*__libc_gethostbyname2_r)(const char *name,
     417             :                               int af,
     418             :                               struct hostent *ret,
     419             :                               char *buf,
     420             :                               size_t buflen,
     421             :                               struct hostent **result,
     422             :                               int *h_errnop);
     423             : #endif
     424             : 
     425             : typedef struct hostent *(*__libc_gethostbyaddr)(const void *addr,
     426             :                                                 socklen_t len,
     427             :                                                 int type);
     428             : 
     429             : typedef int (*__libc_getaddrinfo)(const char *node,
     430             :                                   const char *service,
     431             :                                   const struct addrinfo *hints,
     432             :                                   struct addrinfo **res);
     433             : typedef int (*__libc_getnameinfo)(const struct sockaddr *sa,
     434             :                                   socklen_t salen,
     435             :                                   char *host,
     436             :                                   size_t hostlen,
     437             :                                   char *serv,
     438             :                                   size_t servlen,
     439             :                                   int flags);
     440             : 
     441             : typedef int (*__libc_gethostname)(char *name, size_t len);
     442             : 
     443             : #ifdef HAVE_GETHOSTBYNAME_R
     444             : typedef int (*__libc_gethostbyname_r)(const char *name,
     445             :                              struct hostent *ret,
     446             :                              char *buf, size_t buflen,
     447             :                              struct hostent **result, int *h_errnop);
     448             : #endif
     449             : 
     450             : #ifdef HAVE_GETHOSTBYADDR_R
     451             : typedef int (*__libc_gethostbyaddr_r)(const void *addr,
     452             :                                       socklen_t len,
     453             :                                       int type,
     454             :                                       struct hostent *ret,
     455             :                                       char *buf,
     456             :                                       size_t buflen,
     457             :                                       struct hostent **result,
     458             :                                       int *h_errnop);
     459             : #endif
     460             : 
     461             : #define NWRAP_SYMBOL_ENTRY(i) \
     462             :         union { \
     463             :                 __libc_##i f; \
     464             :                 void *obj; \
     465             :         } _libc_##i
     466             : 
     467             : struct nwrap_libc_symbols {
     468             :         NWRAP_SYMBOL_ENTRY(getpwnam);
     469             :         NWRAP_SYMBOL_ENTRY(getpwnam_r);
     470             :         NWRAP_SYMBOL_ENTRY(getpwuid);
     471             :         NWRAP_SYMBOL_ENTRY(getpwuid_r);
     472             :         NWRAP_SYMBOL_ENTRY(setpwent);
     473             :         NWRAP_SYMBOL_ENTRY(getpwent);
     474             : #ifdef HAVE_GETPWENT_R
     475             :         NWRAP_SYMBOL_ENTRY(getpwent_r);
     476             : #endif
     477             :         NWRAP_SYMBOL_ENTRY(endpwent);
     478             : 
     479             :         NWRAP_SYMBOL_ENTRY(initgroups);
     480             :         NWRAP_SYMBOL_ENTRY(getgrnam);
     481             :         NWRAP_SYMBOL_ENTRY(getgrnam_r);
     482             :         NWRAP_SYMBOL_ENTRY(getgrgid);
     483             :         NWRAP_SYMBOL_ENTRY(getgrgid_r);
     484             :         NWRAP_SYMBOL_ENTRY(setgrent);
     485             :         NWRAP_SYMBOL_ENTRY(getgrent);
     486             : #ifdef HAVE_GETGRENT_R
     487             :         NWRAP_SYMBOL_ENTRY(getgrent_r);
     488             : #endif
     489             :         NWRAP_SYMBOL_ENTRY(endgrent);
     490             :         NWRAP_SYMBOL_ENTRY(getgrouplist);
     491             : 
     492             :         NWRAP_SYMBOL_ENTRY(sethostent);
     493             :         NWRAP_SYMBOL_ENTRY(gethostent);
     494             :         NWRAP_SYMBOL_ENTRY(endhostent);
     495             :         NWRAP_SYMBOL_ENTRY(gethostbyname);
     496             : #ifdef HAVE_GETHOSTBYNAME_R
     497             :         NWRAP_SYMBOL_ENTRY(gethostbyname_r);
     498             : #endif
     499             : #ifdef HAVE_GETHOSTBYNAME2
     500             :         NWRAP_SYMBOL_ENTRY(gethostbyname2);
     501             : #endif
     502             : #ifdef HAVE_GETHOSTBYNAME2_R
     503             :         NWRAP_SYMBOL_ENTRY(gethostbyname2_r);
     504             : #endif
     505             :         NWRAP_SYMBOL_ENTRY(gethostbyaddr);
     506             : #ifdef HAVE_GETHOSTBYADDR_R
     507             :         NWRAP_SYMBOL_ENTRY(gethostbyaddr_r);
     508             : #endif
     509             :         NWRAP_SYMBOL_ENTRY(getaddrinfo);
     510             :         NWRAP_SYMBOL_ENTRY(getnameinfo);
     511             :         NWRAP_SYMBOL_ENTRY(gethostname);
     512             : };
     513             : #undef NWRAP_SYMBOL_ENTRY
     514             : 
     515             : typedef NSS_STATUS (*__nss_getpwnam_r)(const char *name,
     516             :                                        struct passwd *result,
     517             :                                        char *buffer,
     518             :                                        size_t buflen,
     519             :                                        int *errnop);
     520             : typedef NSS_STATUS (*__nss_getpwuid_r)(uid_t uid,
     521             :                                        struct passwd *result,
     522             :                                        char *buffer,
     523             :                                        size_t buflen,
     524             :                                        int *errnop);
     525             : typedef NSS_STATUS (*__nss_setpwent)(void);
     526             : typedef NSS_STATUS (*__nss_getpwent_r)(struct passwd *result,
     527             :                                        char *buffer,
     528             :                                        size_t buflen,
     529             :                                        int *errnop);
     530             : typedef NSS_STATUS (*__nss_endpwent)(void);
     531             : typedef NSS_STATUS (*__nss_initgroups)(const char *user,
     532             :                                        gid_t group,
     533             :                                        long int *start,
     534             :                                        long int *size,
     535             :                                        gid_t **groups,
     536             :                                        long int limit,
     537             :                                        int *errnop);
     538             : typedef NSS_STATUS (*__nss_getgrnam_r)(const char *name,
     539             :                                        struct group *result,
     540             :                                        char *buffer,
     541             :                                        size_t buflen,
     542             :                                        int *errnop);
     543             : typedef NSS_STATUS (*__nss_getgrgid_r)(gid_t gid,
     544             :                                        struct group *result,
     545             :                                        char *buffer,
     546             :                                        size_t buflen,
     547             :                                        int *errnop);
     548             : typedef NSS_STATUS (*__nss_setgrent)(void);
     549             : typedef NSS_STATUS (*__nss_getgrent_r)(struct group *result,
     550             :                                        char *buffer,
     551             :                                        size_t buflen,
     552             :                                        int *errnop);
     553             : typedef NSS_STATUS (*__nss_endgrent)(void);
     554             : typedef NSS_STATUS (*__nss_gethostbyaddr_r)(const void *addr,
     555             :                                             socklen_t addrlen,
     556             :                                             int af,
     557             :                                             struct hostent *result,
     558             :                                             char *buffer,
     559             :                                             size_t buflen,
     560             :                                             int *errnop,
     561             :                                             int *h_errnop);
     562             : typedef NSS_STATUS (*__nss_gethostbyname2_r)(const char *name,
     563             :                                              int af,
     564             :                                              struct hostent *result,
     565             :                                              char *buffer,
     566             :                                              size_t buflen,
     567             :                                              int *errnop,
     568             :                                              int *h_errnop);
     569             : 
     570             : #define NWRAP_NSS_MODULE_SYMBOL_ENTRY(i) \
     571             :         union { \
     572             :                 __nss_##i f; \
     573             :                 void *obj; \
     574             :         } _nss_##i
     575             : 
     576             : struct nwrap_nss_module_symbols {
     577             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwnam_r);
     578             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwuid_r);
     579             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(setpwent);
     580             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwent_r);
     581             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(endpwent);
     582             : 
     583             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups);
     584             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrnam_r);
     585             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrgid_r);
     586             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(setgrent);
     587             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrent_r);
     588             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(endgrent);
     589             : 
     590             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyaddr_r);
     591             :         NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyname2_r);
     592             : };
     593             : 
     594             : struct nwrap_backend {
     595             :         const char *name;
     596             :         const char *so_path;
     597             :         void *so_handle;
     598             :         struct nwrap_ops *ops;
     599             :         struct nwrap_nss_module_symbols *symbols;
     600             : };
     601             : 
     602             : struct nwrap_vector;
     603             : 
     604             : struct nwrap_ops {
     605             :         struct passwd * (*nw_getpwnam)(struct nwrap_backend *b,
     606             :                                        const char *name);
     607             :         int             (*nw_getpwnam_r)(struct nwrap_backend *b,
     608             :                                          const char *name, struct passwd *pwdst,
     609             :                                          char *buf, size_t buflen, struct passwd **pwdstp);
     610             :         struct passwd * (*nw_getpwuid)(struct nwrap_backend *b,
     611             :                                        uid_t uid);
     612             :         int             (*nw_getpwuid_r)(struct nwrap_backend *b,
     613             :                                          uid_t uid, struct passwd *pwdst,
     614             :                                          char *buf, size_t buflen, struct passwd **pwdstp);
     615             :         void            (*nw_setpwent)(struct nwrap_backend *b);
     616             :         struct passwd * (*nw_getpwent)(struct nwrap_backend *b);
     617             :         int             (*nw_getpwent_r)(struct nwrap_backend *b,
     618             :                                          struct passwd *pwdst, char *buf,
     619             :                                          size_t buflen, struct passwd **pwdstp);
     620             :         void            (*nw_endpwent)(struct nwrap_backend *b);
     621             :         int             (*nw_initgroups)(struct nwrap_backend *b,
     622             :                                          const char *user, gid_t group);
     623             :         struct group *  (*nw_getgrnam)(struct nwrap_backend *b,
     624             :                                        const char *name);
     625             :         int             (*nw_getgrnam_r)(struct nwrap_backend *b,
     626             :                                          const char *name, struct group *grdst,
     627             :                                          char *buf, size_t buflen, struct group **grdstp);
     628             :         struct group *  (*nw_getgrgid)(struct nwrap_backend *b,
     629             :                                        gid_t gid);
     630             :         int             (*nw_getgrgid_r)(struct nwrap_backend *b,
     631             :                                          gid_t gid, struct group *grdst,
     632             :                                          char *buf, size_t buflen, struct group **grdstp);
     633             :         void            (*nw_setgrent)(struct nwrap_backend *b);
     634             :         struct group *  (*nw_getgrent)(struct nwrap_backend *b);
     635             :         int             (*nw_getgrent_r)(struct nwrap_backend *b,
     636             :                                          struct group *grdst, char *buf,
     637             :                                          size_t buflen, struct group **grdstp);
     638             :         void            (*nw_endgrent)(struct nwrap_backend *b);
     639             :         struct hostent *(*nw_gethostbyaddr)(struct nwrap_backend *b,
     640             :                                             const void *addr,
     641             :                                             socklen_t len, int type);
     642             :         struct hostent *(*nw_gethostbyname)(struct nwrap_backend *b,
     643             :                                             const char *name);
     644             :         struct hostent *(*nw_gethostbyname2)(struct nwrap_backend *b,
     645             :                                              const char *name, int af);
     646             :         int             (*nw_gethostbyname2_r)(struct nwrap_backend *b,
     647             :                                                const char *name, int af,
     648             :                                                struct hostent *hedst,
     649             :                                                char *buf, size_t buflen,
     650             :                                                struct hostent **hedstp);
     651             : };
     652             : 
     653             : /* Public prototypes */
     654             : 
     655             : bool nss_wrapper_enabled(void);
     656             : bool nss_wrapper_shadow_enabled(void);
     657             : bool nss_wrapper_hosts_enabled(void);
     658             : 
     659             : /* prototypes for files backend */
     660             : 
     661             : 
     662             : static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
     663             :                                            const char *name);
     664             : static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
     665             :                                   const char *name, struct passwd *pwdst,
     666             :                                   char *buf, size_t buflen, struct passwd **pwdstp);
     667             : static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
     668             :                                            uid_t uid);
     669             : static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
     670             :                                   uid_t uid, struct passwd *pwdst,
     671             :                                   char *buf, size_t buflen, struct passwd **pwdstp);
     672             : static void nwrap_files_setpwent(struct nwrap_backend *b);
     673             : static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b);
     674             : static int nwrap_files_getpwent_r(struct nwrap_backend *b,
     675             :                                   struct passwd *pwdst, char *buf,
     676             :                                   size_t buflen, struct passwd **pwdstp);
     677             : static void nwrap_files_endpwent(struct nwrap_backend *b);
     678             : static int nwrap_files_initgroups(struct nwrap_backend *b,
     679             :                                   const char *user, gid_t group);
     680             : static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
     681             :                                           const char *name);
     682             : static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
     683             :                                   const char *name, struct group *grdst,
     684             :                                   char *buf, size_t buflen, struct group **grdstp);
     685             : static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
     686             :                                           gid_t gid);
     687             : static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
     688             :                                   gid_t gid, struct group *grdst,
     689             :                                   char *buf, size_t buflen, struct group **grdstp);
     690             : static void nwrap_files_setgrent(struct nwrap_backend *b);
     691             : static struct group *nwrap_files_getgrent(struct nwrap_backend *b);
     692             : static int nwrap_files_getgrent_r(struct nwrap_backend *b,
     693             :                                   struct group *grdst, char *buf,
     694             :                                   size_t buflen, struct group **grdstp);
     695             : static void nwrap_files_endgrent(struct nwrap_backend *b);
     696             : static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
     697             :                                                  const void *addr,
     698             :                                                  socklen_t len, int type);
     699             : static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
     700             :                                                  const char *name);
     701             : #ifdef HAVE_GETHOSTBYNAME2
     702             : static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
     703             :                                                   const char *name, int af);
     704             : #endif /* HAVE_GETHOSTBYNAME2 */
     705             : static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
     706             :                                         const char *name, int af,
     707             :                                         struct hostent *hedst,
     708             :                                         char *buf, size_t buflen,
     709             :                                         struct hostent **hedstp);
     710             : 
     711             : /* prototypes for module backend */
     712             : 
     713             : static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b);
     714             : static int nwrap_module_getpwent_r(struct nwrap_backend *b,
     715             :                                    struct passwd *pwdst, char *buf,
     716             :                                    size_t buflen, struct passwd **pwdstp);
     717             : static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
     718             :                                             const char *name);
     719             : static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
     720             :                                    const char *name, struct passwd *pwdst,
     721             :                                    char *buf, size_t buflen, struct passwd **pwdstp);
     722             : static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
     723             :                                             uid_t uid);
     724             : static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
     725             :                                    uid_t uid, struct passwd *pwdst,
     726             :                                    char *buf, size_t buflen, struct passwd **pwdstp);
     727             : static void nwrap_module_setpwent(struct nwrap_backend *b);
     728             : static void nwrap_module_endpwent(struct nwrap_backend *b);
     729             : static struct group *nwrap_module_getgrent(struct nwrap_backend *b);
     730             : static int nwrap_module_getgrent_r(struct nwrap_backend *b,
     731             :                                    struct group *grdst, char *buf,
     732             :                                    size_t buflen, struct group **grdstp);
     733             : static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
     734             :                                            const char *name);
     735             : static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
     736             :                                    const char *name, struct group *grdst,
     737             :                                    char *buf, size_t buflen, struct group **grdstp);
     738             : static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
     739             :                                            gid_t gid);
     740             : static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
     741             :                                    gid_t gid, struct group *grdst,
     742             :                                    char *buf, size_t buflen, struct group **grdstp);
     743             : static void nwrap_module_setgrent(struct nwrap_backend *b);
     744             : static void nwrap_module_endgrent(struct nwrap_backend *b);
     745             : static int nwrap_module_initgroups(struct nwrap_backend *b,
     746             :                                    const char *user, gid_t group);
     747             : static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
     748             :                                                   const void *addr,
     749             :                                                   socklen_t len, int type);
     750             : static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
     751             :                                                   const char *name);
     752             : static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
     753             :                                                    const char *name, int af);
     754             : static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
     755             :                                          const char *name, int af,
     756             :                                          struct hostent *hedst,
     757             :                                          char *buf, size_t buflen,
     758             :                                          struct hostent **hedstp);
     759             : 
     760             : struct nwrap_ops nwrap_files_ops = {
     761             :         .nw_getpwnam    = nwrap_files_getpwnam,
     762             :         .nw_getpwnam_r  = nwrap_files_getpwnam_r,
     763             :         .nw_getpwuid    = nwrap_files_getpwuid,
     764             :         .nw_getpwuid_r  = nwrap_files_getpwuid_r,
     765             :         .nw_setpwent    = nwrap_files_setpwent,
     766             :         .nw_getpwent    = nwrap_files_getpwent,
     767             :         .nw_getpwent_r  = nwrap_files_getpwent_r,
     768             :         .nw_endpwent    = nwrap_files_endpwent,
     769             :         .nw_initgroups  = nwrap_files_initgroups,
     770             :         .nw_getgrnam    = nwrap_files_getgrnam,
     771             :         .nw_getgrnam_r  = nwrap_files_getgrnam_r,
     772             :         .nw_getgrgid    = nwrap_files_getgrgid,
     773             :         .nw_getgrgid_r  = nwrap_files_getgrgid_r,
     774             :         .nw_setgrent    = nwrap_files_setgrent,
     775             :         .nw_getgrent    = nwrap_files_getgrent,
     776             :         .nw_getgrent_r  = nwrap_files_getgrent_r,
     777             :         .nw_endgrent    = nwrap_files_endgrent,
     778             :         .nw_gethostbyaddr       = nwrap_files_gethostbyaddr,
     779             :         .nw_gethostbyname       = nwrap_files_gethostbyname,
     780             : #ifdef HAVE_GETHOSTBYNAME2
     781             :         .nw_gethostbyname2      = nwrap_files_gethostbyname2,
     782             : #endif /* HAVE_GETHOSTBYNAME2 */
     783             :         .nw_gethostbyname2_r    = nwrap_files_gethostbyname2_r,
     784             : };
     785             : 
     786             : struct nwrap_ops nwrap_module_ops = {
     787             :         .nw_getpwnam    = nwrap_module_getpwnam,
     788             :         .nw_getpwnam_r  = nwrap_module_getpwnam_r,
     789             :         .nw_getpwuid    = nwrap_module_getpwuid,
     790             :         .nw_getpwuid_r  = nwrap_module_getpwuid_r,
     791             :         .nw_setpwent    = nwrap_module_setpwent,
     792             :         .nw_getpwent    = nwrap_module_getpwent,
     793             :         .nw_getpwent_r  = nwrap_module_getpwent_r,
     794             :         .nw_endpwent    = nwrap_module_endpwent,
     795             :         .nw_initgroups  = nwrap_module_initgroups,
     796             :         .nw_getgrnam    = nwrap_module_getgrnam,
     797             :         .nw_getgrnam_r  = nwrap_module_getgrnam_r,
     798             :         .nw_getgrgid    = nwrap_module_getgrgid,
     799             :         .nw_getgrgid_r  = nwrap_module_getgrgid_r,
     800             :         .nw_setgrent    = nwrap_module_setgrent,
     801             :         .nw_getgrent    = nwrap_module_getgrent,
     802             :         .nw_getgrent_r  = nwrap_module_getgrent_r,
     803             :         .nw_endgrent    = nwrap_module_endgrent,
     804             :         .nw_gethostbyaddr       = nwrap_module_gethostbyaddr,
     805             :         .nw_gethostbyname       = nwrap_module_gethostbyname,
     806             :         .nw_gethostbyname2      = nwrap_module_gethostbyname2,
     807             :         .nw_gethostbyname2_r    = nwrap_module_gethostbyname2_r,
     808             : };
     809             : 
     810             : struct nwrap_libc {
     811             :         void *handle;
     812             :         void *nsl_handle;
     813             :         void *sock_handle;
     814             :         struct nwrap_libc_symbols symbols;
     815             : };
     816             : 
     817             : struct nwrap_main {
     818             :         size_t num_backends;
     819             :         struct nwrap_backend *backends;
     820             :         struct nwrap_libc *libc;
     821             : };
     822             : 
     823             : static struct nwrap_main *nwrap_main_global;
     824             : static struct nwrap_main __nwrap_main_global;
     825             : 
     826             : /*
     827             :  * PROTOTYPES
     828             :  */
     829             : static int nwrap_convert_he_ai(const struct hostent *he,
     830             :                                unsigned short port,
     831             :                                const struct addrinfo *hints,
     832             :                                struct addrinfo **pai,
     833             :                                bool skip_canonname);
     834             : 
     835             : /*
     836             :  * VECTORS
     837             :  */
     838             : 
     839             : #define DEFAULT_VECTOR_CAPACITY 16
     840             : 
     841             : struct nwrap_vector {
     842             :         void **items;
     843             :         size_t count;
     844             :         size_t capacity;
     845             : };
     846             : 
     847             : /* Macro returns pointer to first element of vector->items array.
     848             :  *
     849             :  * nwrap_vector is used as a memory backend which take care of
     850             :  * memory allocations and other stuff like memory growing.
     851             :  * nwrap_vectors should not be considered as some abstract structures.
     852             :  * On this level, vectors are more handy than direct realloc/malloc
     853             :  * calls.
     854             :  *
     855             :  * nwrap_vector->items is array inside nwrap_vector which can be
     856             :  * directly pointed by libc structure assembled by cwrap itself.
     857             :  *
     858             :  * EXAMPLE:
     859             :  *
     860             :  * 1) struct hostent contains char **h_addr_list element.
     861             :  * 2) nwrap_vector holds array of pointers to addresses.
     862             :  *    It's easier to use vector to store results of
     863             :  *    file parsing etc.
     864             :  *
     865             :  * Now, pretend that cwrap assembled struct hostent and
     866             :  * we need to set h_addr_list to point to nwrap_vector.
     867             :  * Idea behind is to shield users from internal nwrap_vector
     868             :  * implementation.
     869             :  * (Yes, not fully - array terminated by NULL is needed because
     870             :  * it's result expected by libc function caller.)
     871             :  *
     872             :  *
     873             :  * CODE EXAMPLE:
     874             :  *
     875             :  * struct hostent he;
     876             :  * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
     877             :  * ... don't care about failed allocation now ...
     878             :  *
     879             :  * ... fill nwrap vector ...
     880             :  *
     881             :  * struct hostent he;
     882             :  * he.h_addr_list = nwrap_vector_head(vector);
     883             :  *
     884             :  */
     885             : #define nwrap_vector_head(vect) ((void *)((vect)->items))
     886             : 
     887             : #define nwrap_vector_foreach(item, vect, iter) \
     888             :         for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
     889             :              item != NULL; \
     890             :              (item) = (vect).items[++iter])
     891             : 
     892             : #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
     893             : 
     894       88239 : static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
     895             : {
     896       88239 :         if (vector == NULL) {
     897           0 :                 return false;
     898             :         }
     899             : 
     900             :         /* count is initialized by ZERO_STRUCTP */
     901       88239 :         ZERO_STRUCTP(vector);
     902       88239 :         vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     903       88239 :         if (vector->items == NULL) {
     904           0 :                 return false;
     905             :         }
     906       88239 :         vector->capacity = DEFAULT_VECTOR_CAPACITY;
     907       88239 :         memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     908             : 
     909       88239 :         return true;
     910             : }
     911             : 
     912      411541 : static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
     913             : {
     914      411541 :         assert (vector != NULL);
     915             : 
     916      411541 :         if (vector->items == NULL) {
     917       88230 :                 nwrap_vector_init(vector);
     918             :         }
     919             : 
     920      411541 :         if (vector->count == vector->capacity) {
     921             :                 /* Items array _MUST_ be NULL terminated because it's passed
     922             :                  * as result to caller which expect NULL terminated array from libc.
     923             :                  */
     924        9259 :                 void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
     925        9259 :                 if (items == NULL) {
     926           0 :                         return false;
     927             :                 }
     928        9259 :                 vector->items = items;
     929             : 
     930             :                 /* Don't count ending NULL to capacity */
     931        9259 :                 vector->capacity *= 2;
     932             :         }
     933             : 
     934      411541 :         vector->items[vector->count] = item;
     935             : 
     936      411541 :         vector->count += 1;
     937      411541 :         vector->items[vector->count] = NULL;
     938             : 
     939      411541 :         return true;
     940             : }
     941             : 
     942           9 : static bool nwrap_vector_merge(struct nwrap_vector *dst,
     943             :                                struct nwrap_vector *src)
     944             : {
     945           9 :         void **dst_items = NULL;
     946             :         size_t count;
     947             : 
     948           9 :         if (src->count == 0) {
     949           0 :                 return true;
     950             :         }
     951             : 
     952           9 :         count = dst->count + src->count;
     953             : 
     954             :         /* We don't need reallocation if we have enough capacity. */
     955           9 :         if (src->count > (dst->capacity - dst->count)) {
     956           0 :                 dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
     957           0 :                 if (dst_items == NULL) {
     958           0 :                         return false;
     959             :                 }
     960           0 :                 dst->items = dst_items;
     961           0 :                 dst->capacity = count;
     962             :         }
     963             : 
     964          18 :         memcpy((void *)(((long *)dst->items) + dst->count),
     965           9 :                src->items,
     966           9 :                src->count * sizeof(void *));
     967           9 :         dst->count = count;
     968             : 
     969           9 :         return true;
     970             : }
     971             : 
     972             : struct nwrap_cache {
     973             :         const char *path;
     974             :         int fd;
     975             :         FILE *fp;
     976             :         struct stat st;
     977             :         void *private_data;
     978             : 
     979             :         struct nwrap_vector lines;
     980             : 
     981             :         bool (*parse_line)(struct nwrap_cache *, char *line);
     982             :         void (*unload)(struct nwrap_cache *);
     983             : };
     984             : 
     985             : /* passwd */
     986             : struct nwrap_pw {
     987             :         struct nwrap_cache *cache;
     988             : 
     989             :         struct passwd *list;
     990             :         int num;
     991             :         int idx;
     992             : };
     993             : 
     994             : struct nwrap_cache __nwrap_cache_pw;
     995             : struct nwrap_pw nwrap_pw_global;
     996             : 
     997             : static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
     998             : static void nwrap_pw_unload(struct nwrap_cache *nwrap);
     999             : 
    1000             : /* shadow */
    1001             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    1002             : struct nwrap_sp {
    1003             :         struct nwrap_cache *cache;
    1004             : 
    1005             :         struct spwd *list;
    1006             :         int num;
    1007             :         int idx;
    1008             : };
    1009             : 
    1010             : struct nwrap_cache __nwrap_cache_sp;
    1011             : struct nwrap_sp nwrap_sp_global;
    1012             : 
    1013             : static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
    1014             : static void nwrap_sp_unload(struct nwrap_cache *nwrap);
    1015             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    1016             : 
    1017             : /* group */
    1018             : struct nwrap_gr {
    1019             :         struct nwrap_cache *cache;
    1020             : 
    1021             :         struct group *list;
    1022             :         int num;
    1023             :         int idx;
    1024             : };
    1025             : 
    1026             : struct nwrap_cache __nwrap_cache_gr;
    1027             : struct nwrap_gr nwrap_gr_global;
    1028             : 
    1029             : /* hosts */
    1030             : static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
    1031             : static void nwrap_he_unload(struct nwrap_cache *nwrap);
    1032             : 
    1033             : struct nwrap_addrdata {
    1034             :         unsigned char host_addr[16]; /* IPv4 or IPv6 address */
    1035             : };
    1036             : 
    1037             : static size_t max_hostents = 100;
    1038             : 
    1039             : struct nwrap_entdata {
    1040             :         struct nwrap_addrdata addr;
    1041             :         struct hostent ht;
    1042             : 
    1043             :         struct nwrap_vector nwrap_addrdata;
    1044             : 
    1045             :         ssize_t aliases_count;
    1046             : };
    1047             : 
    1048             : struct nwrap_entlist {
    1049             :         struct nwrap_entlist *next;
    1050             :         struct nwrap_entdata *ed;
    1051             : };
    1052             : 
    1053             : struct nwrap_he {
    1054             :         struct nwrap_cache *cache;
    1055             : 
    1056             :         struct nwrap_vector entries;
    1057             :         struct nwrap_vector lists;
    1058             : 
    1059             :         int num;
    1060             :         int idx;
    1061             : };
    1062             : 
    1063             : static struct nwrap_cache __nwrap_cache_he;
    1064             : static struct nwrap_he nwrap_he_global;
    1065             : 
    1066             : 
    1067             : /*********************************************************
    1068             :  * NWRAP PROTOTYPES
    1069             :  *********************************************************/
    1070             : 
    1071             : static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
    1072             : static void nwrap_gr_unload(struct nwrap_cache *nwrap);
    1073             : #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT)
    1074             : /* xlC and other oldschool compilers support (only) this */
    1075             : #pragma init (nwrap_constructor)
    1076             : #endif
    1077             : void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
    1078             : #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI)
    1079             : #pragma fini (nwrap_destructor)
    1080             : #endif
    1081             : void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
    1082             : 
    1083             : /*********************************************************
    1084             :  * NWRAP LIBC LOADER FUNCTIONS
    1085             :  *********************************************************/
    1086             : 
    1087             : enum nwrap_lib {
    1088             :     NWRAP_LIBC,
    1089             :     NWRAP_LIBNSL,
    1090             :     NWRAP_LIBSOCKET,
    1091             : };
    1092             : 
    1093       17422 : static const char *nwrap_str_lib(enum nwrap_lib lib)
    1094             : {
    1095       17422 :         switch (lib) {
    1096        2315 :         case NWRAP_LIBC:
    1097        2315 :                 return "libc";
    1098        7103 :         case NWRAP_LIBNSL:
    1099        7103 :                 return "libnsl";
    1100        8004 :         case NWRAP_LIBSOCKET:
    1101        8004 :                 return "libsocket";
    1102             :         }
    1103             : 
    1104             :         /* Compiler would warn us about unhandled enum value if we get here */
    1105           0 :         return "unknown";
    1106             : }
    1107             : 
    1108       17422 : static void *nwrap_load_lib_handle(enum nwrap_lib lib)
    1109             : {
    1110       17422 :         int flags = RTLD_LAZY;
    1111       17422 :         void *handle = NULL;
    1112             :         int i;
    1113             : 
    1114             : #ifdef RTLD_DEEPBIND
    1115       17422 :         const char *env_preload = getenv("LD_PRELOAD");
    1116       17422 :         const char *env_deepbind = getenv("NSS_WRAPPER_DISABLE_DEEPBIND");
    1117       17422 :         bool enable_deepbind = true;
    1118             : 
    1119             :         /* Don't do a deepbind if we run with libasan */
    1120       17422 :         if (env_preload != NULL && strlen(env_preload) < 1024) {
    1121       17422 :                 const char *p = strstr(env_preload, "libasan.so");
    1122       17422 :                 if (p != NULL) {
    1123           0 :                         enable_deepbind = false;
    1124             :                 }
    1125             :         }
    1126             : 
    1127       17422 :         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
    1128           0 :                 enable_deepbind = false;
    1129             :         }
    1130             : 
    1131       17422 :         if (enable_deepbind) {
    1132       17422 :                 flags |= RTLD_DEEPBIND;
    1133             :         }
    1134             : #endif
    1135             : 
    1136       17422 :         switch (lib) {
    1137       10548 :         case NWRAP_LIBNSL:
    1138             : #ifdef HAVE_LIBNSL
    1139        6148 :                 handle = nwrap_main_global->libc->nsl_handle;
    1140        6148 :                 if (handle == NULL) {
    1141       61450 :                         for (i = 10; i >= 0; i--) {
    1142       61450 :                                 char soname[256] = {0};
    1143             : 
    1144       61450 :                                 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
    1145       61450 :                                 handle = dlopen(soname, flags);
    1146       61450 :                                 if (handle != NULL) {
    1147        6145 :                                         break;
    1148             :                                 }
    1149             :                         }
    1150             : 
    1151        6145 :                         nwrap_main_global->libc->nsl_handle = handle;
    1152             :                 }
    1153        6148 :                 break;
    1154             : #endif
    1155             :                 /* FALL TROUGH */
    1156        6874 :         case NWRAP_LIBSOCKET:
    1157             : #ifdef HAVE_LIBSOCKET
    1158             :                 handle = nwrap_main_global->libc->sock_handle;
    1159             :                 if (handle == NULL) {
    1160             :                         for (i = 10; i >= 0; i--) {
    1161             :                                 char soname[256] = {0};
    1162             : 
    1163             :                                 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
    1164             :                                 handle = dlopen(soname, flags);
    1165             :                                 if (handle != NULL) {
    1166             :                                         break;
    1167             :                                 }
    1168             :                         }
    1169             : 
    1170             :                         nwrap_main_global->libc->sock_handle = handle;
    1171             :                 }
    1172             :                 break;
    1173             : #endif
    1174             :                 /* FALL TROUGH */
    1175             :         case NWRAP_LIBC:
    1176       11274 :                 handle = nwrap_main_global->libc->handle;
    1177       11274 :                 if (handle == NULL) {
    1178       43295 :                         for (i = 10; i >= 0; i--) {
    1179       43295 :                                 char soname[256] = {0};
    1180             : 
    1181       43295 :                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
    1182       43295 :                                 handle = dlopen(soname, flags);
    1183       43295 :                                 if (handle != NULL) {
    1184        8659 :                                         break;
    1185             :                                 }
    1186             :                         }
    1187             : 
    1188        8659 :                         nwrap_main_global->libc->handle = handle;
    1189             :                 }
    1190       11274 :                 break;
    1191             :         }
    1192             : 
    1193       17422 :         if (handle == NULL) {
    1194             : #ifdef RTLD_NEXT
    1195           0 :                 handle = nwrap_main_global->libc->handle
    1196           0 :                        = nwrap_main_global->libc->sock_handle
    1197           0 :                        = nwrap_main_global->libc->nsl_handle
    1198           0 :                        = RTLD_NEXT;
    1199             : #else
    1200             :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1201             :                           "Failed to dlopen library: %s\n",
    1202             :                           dlerror());
    1203             :                 exit(-1);
    1204             : #endif
    1205             :         }
    1206             : 
    1207       17422 :         return handle;
    1208             : }
    1209             : 
    1210       17422 : static void *_nwrap_bind_symbol(enum nwrap_lib lib, const char *fn_name)
    1211             : {
    1212             :         void *handle;
    1213             :         void *func;
    1214             : 
    1215       17422 :         nwrap_init();
    1216             : 
    1217       17422 :         handle = nwrap_load_lib_handle(lib);
    1218             : 
    1219       17422 :         func = dlsym(handle, fn_name);
    1220       17422 :         if (func == NULL) {
    1221           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1222             :                                 "Failed to find %s: %s\n",
    1223             :                                 fn_name, dlerror());
    1224           0 :                 exit(-1);
    1225             :         }
    1226             : 
    1227       17422 :         NWRAP_LOG(NWRAP_LOG_TRACE,
    1228             :                         "Loaded %s from %s",
    1229             :                         fn_name, nwrap_str_lib(lib));
    1230       17422 :         return func;
    1231             : }
    1232             : 
    1233             : #define nwrap_bind_symbol_libc(sym_name) \
    1234             :         NWRAP_LOCK(libc_symbol_binding); \
    1235             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1236             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1237             :                         _nwrap_bind_symbol(NWRAP_LIBC, #sym_name); \
    1238             :         } \
    1239             :         NWRAP_UNLOCK(libc_symbol_binding)
    1240             : 
    1241             : #define nwrap_bind_symbol_libc_posix(sym_name) \
    1242             :         NWRAP_LOCK(libc_symbol_binding); \
    1243             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1244             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1245             :                         _nwrap_bind_symbol(NWRAP_LIBC, "__posix_" #sym_name); \
    1246             :         } \
    1247             :         NWRAP_UNLOCK(libc_symbol_binding)
    1248             : 
    1249             : #define nwrap_bind_symbol_libnsl(sym_name) \
    1250             :         NWRAP_LOCK(libc_symbol_binding); \
    1251             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1252             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1253             :                         _nwrap_bind_symbol(NWRAP_LIBNSL, #sym_name); \
    1254             :         } \
    1255             :         NWRAP_UNLOCK(libc_symbol_binding)
    1256             : 
    1257             : #define nwrap_bind_symbol_libsocket(sym_name) \
    1258             :         NWRAP_LOCK(libc_symbol_binding); \
    1259             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1260             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1261             :                         _nwrap_bind_symbol(NWRAP_LIBSOCKET, #sym_name); \
    1262             :         } \
    1263             :         NWRAP_UNLOCK(libc_symbol_binding)
    1264             : 
    1265             : /* INTERNAL HELPER FUNCTIONS */
    1266      172940 : static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
    1267             : {
    1268             :         size_t p;
    1269             :         void *item;
    1270      534857 :         nwrap_vector_foreach(item, nwrap->lines, p) {
    1271             :                 /* Maybe some vectors were merged ... */
    1272      361917 :                 SAFE_FREE(item);
    1273             :         }
    1274      172940 :         SAFE_FREE(nwrap->lines.items);
    1275      172940 :         ZERO_STRUCTP(&nwrap->lines);
    1276      172940 : }
    1277             : 
    1278             : /*
    1279             :  * IMPORTANT
    1280             :  *
    1281             :  * Functions expeciall from libc need to be loaded individually, you can't load
    1282             :  * all at once or gdb will segfault at startup. The same applies to valgrind and
    1283             :  * has probably something todo with with the linker.
    1284             :  * So we need load each function at the point it is called the first time.
    1285             :  */
    1286         530 : static struct passwd *libc_getpwnam(const char *name)
    1287             : {
    1288         530 :         nwrap_bind_symbol_libc(getpwnam);
    1289             : 
    1290         530 :         return nwrap_main_global->libc->symbols._libc_getpwnam.f(name);
    1291             : }
    1292             : 
    1293             : #ifdef HAVE_GETPWNAM_R
    1294           0 : static int libc_getpwnam_r(const char *name,
    1295             :                            struct passwd *pwd,
    1296             :                            char *buf,
    1297             :                            size_t buflen,
    1298             :                            struct passwd **result)
    1299             : {
    1300             : #ifdef HAVE___POSIX_GETPWNAM_R
    1301             :         nwrap_bind_symbol_libc_posix(getpwnam_r);
    1302             : #else
    1303           0 :         nwrap_bind_symbol_libc(getpwnam_r);
    1304             : #endif
    1305             : 
    1306           0 :         return nwrap_main_global->libc->symbols._libc_getpwnam_r.f(name,
    1307             :                                                                    pwd,
    1308             :                                                                    buf,
    1309             :                                                                    buflen,
    1310             :                                                                    result);
    1311             : }
    1312             : #endif
    1313             : 
    1314        2886 : static struct passwd *libc_getpwuid(uid_t uid)
    1315             : {
    1316        2886 :         nwrap_bind_symbol_libc(getpwuid);
    1317             : 
    1318        2886 :         return nwrap_main_global->libc->symbols._libc_getpwuid.f(uid);
    1319             : }
    1320             : 
    1321             : #ifdef HAVE_GETPWUID_R
    1322           0 : static int libc_getpwuid_r(uid_t uid,
    1323             :                            struct passwd *pwd,
    1324             :                            char *buf,
    1325             :                            size_t buflen,
    1326             :                            struct passwd **result)
    1327             : {
    1328             : #ifdef HAVE___POSIX_GETPWUID_R
    1329             :         nwrap_bind_symbol_libc_posix(getpwuid_r);
    1330             : #else
    1331           0 :         nwrap_bind_symbol_libc(getpwuid_r);
    1332             : #endif
    1333             : 
    1334           0 :         return nwrap_main_global->libc->symbols._libc_getpwuid_r.f(uid,
    1335             :                                                                    pwd,
    1336             :                                                                    buf,
    1337             :                                                                    buflen,
    1338             :                                                                    result);
    1339             : }
    1340             : #endif
    1341             : 
    1342      744947 : static inline void str_tolower(char *dst, char *src)
    1343             : {
    1344      744947 :         register char *src_tmp = src;
    1345      744947 :         register char *dst_tmp = dst;
    1346             : 
    1347    13332565 :         while (*src_tmp != '\0') {
    1348    12004810 :                 *dst_tmp = tolower(*src_tmp);
    1349    12004810 :                 ++src_tmp;
    1350    12004810 :                 ++dst_tmp;
    1351             :         }
    1352      744947 : }
    1353             : 
    1354      625989 : static bool str_tolower_copy(char **dst_name, const char *const src_name)
    1355             : {
    1356             :         char *h_name_lower;
    1357             : 
    1358      625989 :         if ((dst_name == NULL) || (src_name == NULL)) {
    1359           0 :                 return false;
    1360             :         }
    1361             : 
    1362      625989 :         h_name_lower = strdup(src_name);
    1363      625989 :         if (h_name_lower == NULL) {
    1364           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
    1365           0 :                 return false;
    1366             :         }
    1367             : 
    1368      625989 :         str_tolower(h_name_lower, h_name_lower);
    1369      625989 :         *dst_name = h_name_lower;
    1370      625989 :         return true;
    1371             : }
    1372             : 
    1373           0 : static void libc_setpwent(void)
    1374             : {
    1375           0 :         nwrap_bind_symbol_libc(setpwent);
    1376             : 
    1377           0 :         nwrap_main_global->libc->symbols._libc_setpwent.f();
    1378           0 : }
    1379             : 
    1380           0 : static struct passwd *libc_getpwent(void)
    1381             : {
    1382           0 :         nwrap_bind_symbol_libc(getpwent);
    1383             : 
    1384           0 :         return nwrap_main_global->libc->symbols._libc_getpwent.f();
    1385             : }
    1386             : 
    1387             : #ifdef HAVE_GETPWENT_R
    1388             : #  ifdef HAVE_SOLARIS_GETPWENT_R
    1389             : static struct passwd *libc_getpwent_r(struct passwd *pwdst,
    1390             :                                       char *buf,
    1391             :                                       int buflen)
    1392             : {
    1393             :         nwrap_bind_symbol_libc(getpwent_r);
    1394             : 
    1395             :         return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
    1396             :                                                                    buf,
    1397             :                                                                    buflen);
    1398             : }
    1399             : #  else /* HAVE_SOLARIS_GETPWENT_R */
    1400           0 : static int libc_getpwent_r(struct passwd *pwdst,
    1401             :                            char *buf,
    1402             :                            size_t buflen,
    1403             :                            struct passwd **pwdstp)
    1404             : {
    1405           0 :         nwrap_bind_symbol_libc(getpwent_r);
    1406             : 
    1407           0 :         return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
    1408             :                                                                    buf,
    1409             :                                                                    buflen,
    1410             :                                                                    pwdstp);
    1411             : }
    1412             : #  endif /* HAVE_SOLARIS_GETPWENT_R */
    1413             : #endif /* HAVE_GETPWENT_R */
    1414             : 
    1415         208 : static void libc_endpwent(void)
    1416             : {
    1417         208 :         nwrap_bind_symbol_libc(endpwent);
    1418             : 
    1419         208 :         nwrap_main_global->libc->symbols._libc_endpwent.f();
    1420         208 : }
    1421             : 
    1422           0 : static int libc_initgroups(const char *user, gid_t gid)
    1423             : {
    1424           0 :         nwrap_bind_symbol_libc(initgroups);
    1425             : 
    1426           0 :         return nwrap_main_global->libc->symbols._libc_initgroups.f(user, gid);
    1427             : }
    1428             : 
    1429         131 : static struct group *libc_getgrnam(const char *name)
    1430             : {
    1431         131 :         nwrap_bind_symbol_libc(getgrnam);
    1432             : 
    1433         131 :         return nwrap_main_global->libc->symbols._libc_getgrnam.f(name);
    1434             : }
    1435             : 
    1436             : #ifdef HAVE_GETGRNAM_R
    1437           0 : static int libc_getgrnam_r(const char *name,
    1438             :                            struct group *grp,
    1439             :                            char *buf,
    1440             :                            size_t buflen,
    1441             :                            struct group **result)
    1442             : {
    1443             : #ifdef HAVE___POSIX_GETGRNAM_R
    1444             :         nwrap_bind_symbol_libc_posix(getgrnam_r);
    1445             : #else
    1446           0 :         nwrap_bind_symbol_libc(getgrnam_r);
    1447             : #endif
    1448             : 
    1449           0 :         return nwrap_main_global->libc->symbols._libc_getgrnam_r.f(name,
    1450             :                                                                    grp,
    1451             :                                                                    buf,
    1452             :                                                                    buflen,
    1453             :                                                                    result);
    1454             : }
    1455             : #endif
    1456             : 
    1457         236 : static struct group *libc_getgrgid(gid_t gid)
    1458             : {
    1459         236 :         nwrap_bind_symbol_libc(getgrgid);
    1460             : 
    1461         236 :         return nwrap_main_global->libc->symbols._libc_getgrgid.f(gid);
    1462             : }
    1463             : 
    1464             : #ifdef HAVE_GETGRGID_R
    1465           0 : static int libc_getgrgid_r(gid_t gid,
    1466             :                            struct group *grp,
    1467             :                            char *buf,
    1468             :                            size_t buflen,
    1469             :                            struct group **result)
    1470             : {
    1471             : #ifdef HAVE___POSIX_GETGRGID_R
    1472             :         if (nwrap_main_global->libc->symbols._libc_getgrgid_r == NULL) {
    1473             :                 *(void **) (&nwrap_main_global->libc->symbols._libc_getgrgid_r) =
    1474             :                         _nwrap_bind_symbol_libc("__posix_getgrgid_r");
    1475             :         }
    1476             : #else
    1477           0 :         nwrap_bind_symbol_libc(getgrgid_r);
    1478             : #endif
    1479             : 
    1480           0 :         return nwrap_main_global->libc->symbols._libc_getgrgid_r.f(gid,
    1481             :                                                                    grp,
    1482             :                                                                    buf,
    1483             :                                                                    buflen,
    1484             :                                                                    result);
    1485             : }
    1486             : #endif
    1487             : 
    1488           0 : static void libc_setgrent(void)
    1489             : {
    1490           0 :         nwrap_bind_symbol_libc(setgrent);
    1491             : 
    1492           0 :         nwrap_main_global->libc->symbols._libc_setgrent.f();
    1493           0 : }
    1494             : 
    1495           0 : static struct group *libc_getgrent(void)
    1496             : {
    1497           0 :         nwrap_bind_symbol_libc(getgrent);
    1498             : 
    1499           0 :         return nwrap_main_global->libc->symbols._libc_getgrent.f();
    1500             : }
    1501             : 
    1502             : #ifdef HAVE_GETGRENT_R
    1503             : #  ifdef HAVE_SOLARIS_GETGRENT_R
    1504             : static struct group *libc_getgrent_r(struct group *group,
    1505             :                                      char *buf,
    1506             :                                      size_t buflen)
    1507             : {
    1508             :         nwrap_bind_symbol_libc(getgrent_r);
    1509             : 
    1510             :         return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
    1511             :                                                                    buf,
    1512             :                                                                    buflen);
    1513             : }
    1514             : #  else /* HAVE_SOLARIS_GETGRENT_R */
    1515           0 : static int libc_getgrent_r(struct group *group,
    1516             :                            char *buf,
    1517             :                            size_t buflen,
    1518             :                            struct group **result)
    1519             : {
    1520           0 :         nwrap_bind_symbol_libc(getgrent_r);
    1521             : 
    1522           0 :         return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
    1523             :                                                                    buf,
    1524             :                                                                    buflen,
    1525             :                                                                    result);
    1526             : }
    1527             : #  endif /* HAVE_SOLARIS_GETGRENT_R */
    1528             : #endif /* HAVE_GETGRENT_R */
    1529             : 
    1530           0 : static void libc_endgrent(void)
    1531             : {
    1532           0 :         nwrap_bind_symbol_libc(endgrent);
    1533             : 
    1534           0 :         nwrap_main_global->libc->symbols._libc_endgrent.f();
    1535           0 : }
    1536             : 
    1537             : #ifdef HAVE_GETGROUPLIST
    1538           0 : static int libc_getgrouplist(const char *user,
    1539             :                              gid_t group,
    1540             :                              gid_t *groups,
    1541             :                              int *ngroups)
    1542             : {
    1543           0 :         nwrap_bind_symbol_libc(getgrouplist);
    1544             : 
    1545           0 :         return nwrap_main_global->libc->symbols._libc_getgrouplist.f(user,
    1546             :                                                                      group,
    1547             :                                                                      groups,
    1548             :                                                                      ngroups);
    1549             : }
    1550             : #endif
    1551             : 
    1552           0 : static void libc_sethostent(int stayopen)
    1553             : {
    1554           0 :         nwrap_bind_symbol_libnsl(sethostent);
    1555             : 
    1556           0 :         nwrap_main_global->libc->symbols._libc_sethostent.f(stayopen);
    1557           0 : }
    1558             : 
    1559           0 : static struct hostent *libc_gethostent(void)
    1560             : {
    1561           0 :         nwrap_bind_symbol_libnsl(gethostent);
    1562             : 
    1563           0 :         return nwrap_main_global->libc->symbols._libc_gethostent.f();
    1564             : }
    1565             : 
    1566           0 : static void libc_endhostent(void)
    1567             : {
    1568           0 :         nwrap_bind_symbol_libnsl(endhostent);
    1569             : 
    1570           0 :         nwrap_main_global->libc->symbols._libc_endhostent.f();
    1571           0 : }
    1572             : 
    1573           0 : static struct hostent *libc_gethostbyname(const char *name)
    1574             : {
    1575           0 :         nwrap_bind_symbol_libnsl(gethostbyname);
    1576             : 
    1577           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname.f(name);
    1578             : }
    1579             : 
    1580             : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
    1581           0 : static struct hostent *libc_gethostbyname2(const char *name, int af)
    1582             : {
    1583           0 :         nwrap_bind_symbol_libnsl(gethostbyname2);
    1584             : 
    1585           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname2.f(name, af);
    1586             : }
    1587             : #endif
    1588             : 
    1589             : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
    1590           0 : static int libc_gethostbyname2_r(const char *name,
    1591             :                                  int af,
    1592             :                                  struct hostent *ret,
    1593             :                                  char *buf,
    1594             :                                  size_t buflen,
    1595             :                                  struct hostent **result,
    1596             :                                  int *h_errnop)
    1597             : {
    1598           0 :         nwrap_bind_symbol_libnsl(gethostbyname2_r);
    1599             : 
    1600           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname2_r.f(name,
    1601             :                                                                          af,
    1602             :                                                                          ret,
    1603             :                                                                          buf,
    1604             :                                                                          buflen,
    1605             :                                                                          result,
    1606             :                                                                          h_errnop);
    1607             : }
    1608             : #endif
    1609             : 
    1610           0 : static struct hostent *libc_gethostbyaddr(const void *addr,
    1611             :                                           socklen_t len,
    1612             :                                           int type)
    1613             : {
    1614           0 :         nwrap_bind_symbol_libnsl(gethostbyaddr);
    1615             : 
    1616           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyaddr.f(addr,
    1617             :                                                                       len,
    1618             :                                                                       type);
    1619             : }
    1620             : 
    1621        7180 : static int libc_gethostname(char *name, size_t len)
    1622             : {
    1623        7180 :         nwrap_bind_symbol_libnsl(gethostname);
    1624             : 
    1625        7180 :         return nwrap_main_global->libc->symbols._libc_gethostname.f(name, len);
    1626             : }
    1627             : 
    1628             : #ifdef HAVE_GETHOSTBYNAME_R
    1629           3 : static int libc_gethostbyname_r(const char *name,
    1630             :                                 struct hostent *ret,
    1631             :                                 char *buf,
    1632             :                                 size_t buflen,
    1633             :                                 struct hostent **result,
    1634             :                                 int *h_errnop)
    1635             : {
    1636           3 :         nwrap_bind_symbol_libnsl(gethostbyname_r);
    1637             : 
    1638           3 :         return nwrap_main_global->libc->symbols._libc_gethostbyname_r.f(name,
    1639             :                                                                         ret,
    1640             :                                                                         buf,
    1641             :                                                                         buflen,
    1642             :                                                                         result,
    1643             :                                                                         h_errnop);
    1644             : }
    1645             : #endif
    1646             : 
    1647             : #ifdef HAVE_GETHOSTBYADDR_R
    1648           0 : static int libc_gethostbyaddr_r(const void *addr,
    1649             :                                 socklen_t len,
    1650             :                                 int type,
    1651             :                                 struct hostent *ret,
    1652             :                                 char *buf,
    1653             :                                 size_t buflen,
    1654             :                                 struct hostent **result,
    1655             :                                 int *h_errnop)
    1656             : {
    1657           0 :         nwrap_bind_symbol_libnsl(gethostbyaddr_r);
    1658             : 
    1659           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyaddr_r.f(addr,
    1660             :                                                                         len,
    1661             :                                                                         type,
    1662             :                                                                         ret,
    1663             :                                                                         buf,
    1664             :                                                                         buflen,
    1665             :                                                                         result,
    1666             :                                                                         h_errnop);
    1667             : }
    1668             : #endif
    1669             : 
    1670      494018 : static int libc_getaddrinfo(const char *node,
    1671             :                             const char *service,
    1672             :                             const struct addrinfo *hints,
    1673             :                             struct addrinfo **res)
    1674             : {
    1675      494018 :         nwrap_bind_symbol_libsocket(getaddrinfo);
    1676             : 
    1677      494018 :         return nwrap_main_global->libc->symbols._libc_getaddrinfo.f(node,
    1678             :                                                                     service,
    1679             :                                                                     hints,
    1680             :                                                                     res);
    1681             : }
    1682             : 
    1683       66432 : static int libc_getnameinfo(const struct sockaddr *sa,
    1684             :                             socklen_t salen,
    1685             :                             char *host,
    1686             :                             size_t hostlen,
    1687             :                             char *serv,
    1688             :                             size_t servlen,
    1689             :                             int flags)
    1690             : {
    1691       66432 :         nwrap_bind_symbol_libsocket(getnameinfo);
    1692             : 
    1693       66432 :         return nwrap_main_global->libc->symbols._libc_getnameinfo.f(sa,
    1694             :                                                                     salen,
    1695             :                                                                     host,
    1696             :                                                                     hostlen,
    1697             :                                                                     serv,
    1698             :                                                                     servlen,
    1699             :                                                                     flags);
    1700             : }
    1701             : 
    1702             : /*********************************************************
    1703             :  * NWRAP NSS MODULE LOADER FUNCTIONS
    1704             :  *********************************************************/
    1705             : 
    1706      155519 : static void *_nwrap_bind_nss_module_symbol(struct nwrap_backend *b,
    1707             :                                            const char *fn_name)
    1708             : {
    1709      155519 :         void *res = NULL;
    1710      155519 :         char *s = NULL;
    1711             :         int rc;
    1712             : 
    1713      155519 :         if (b->so_handle == NULL) {
    1714           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
    1715           0 :                 return NULL;
    1716             :         }
    1717             : 
    1718      155519 :         rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name);
    1719      155519 :         if (rc == -1) {
    1720           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    1721           0 :                 return NULL;
    1722             :         }
    1723             : 
    1724      155519 :         res = dlsym(b->so_handle, s);
    1725      155519 :         if (res == NULL) {
    1726       23926 :                 NWRAP_LOG(NWRAP_LOG_WARN,
    1727             :                           "Cannot find function %s in %s",
    1728             :                           s, b->so_path);
    1729             :         }
    1730      155519 :         SAFE_FREE(s);
    1731      155519 :         return res;
    1732             : }
    1733             : 
    1734             : #define nwrap_nss_module_bind_symbol(sym_name) \
    1735             :         NWRAP_LOCK(nss_module_symbol_binding); \
    1736             :         if (symbols->_nss_##sym_name.obj == NULL) { \
    1737             :                 symbols->_nss_##sym_name.obj = \
    1738             :                         _nwrap_bind_nss_module_symbol(b, #sym_name); \
    1739             :         } \
    1740             :         NWRAP_UNLOCK(nss_module_symbol_binding)
    1741             : 
    1742             : #define nwrap_nss_module_bind_symbol2(sym_name, alt_name) \
    1743             :         NWRAP_LOCK(nss_module_symbol_binding); \
    1744             :         if (symbols->_nss_##sym_name.obj == NULL) { \
    1745             :                 symbols->_nss_##sym_name.obj = \
    1746             :                         _nwrap_bind_nss_module_symbol(b, #alt_name); \
    1747             :         } \
    1748             :         NWRAP_UNLOCK(nss_module_symbol_binding)
    1749             : 
    1750             : static struct nwrap_nss_module_symbols *
    1751       11963 : nwrap_bind_nss_module_symbols(struct nwrap_backend *b)
    1752             : {
    1753             :         struct nwrap_nss_module_symbols *symbols;
    1754             : 
    1755       11963 :         if (!b->so_handle) {
    1756           0 :                 return NULL;
    1757             :         }
    1758             : 
    1759       11963 :         symbols = calloc(1, sizeof(struct nwrap_nss_module_symbols));
    1760       11963 :         if (symbols == NULL) {
    1761           0 :                 return NULL;
    1762             :         }
    1763             : 
    1764       11963 :         nwrap_nss_module_bind_symbol(getpwnam_r);
    1765       11963 :         nwrap_nss_module_bind_symbol(getpwuid_r);
    1766       11963 :         nwrap_nss_module_bind_symbol(setpwent);
    1767       11963 :         nwrap_nss_module_bind_symbol(getpwent_r);
    1768       11963 :         nwrap_nss_module_bind_symbol(endpwent);
    1769       11963 :         nwrap_nss_module_bind_symbol2(initgroups, initgroups_dyn);
    1770       11963 :         nwrap_nss_module_bind_symbol(getgrnam_r);
    1771       11963 :         nwrap_nss_module_bind_symbol(getgrgid_r);
    1772       11963 :         nwrap_nss_module_bind_symbol(setgrent);
    1773       11963 :         nwrap_nss_module_bind_symbol(getgrent_r);
    1774       11963 :         nwrap_nss_module_bind_symbol(endgrent);
    1775       11963 :         nwrap_nss_module_bind_symbol(gethostbyaddr_r);
    1776       11963 :         nwrap_nss_module_bind_symbol(gethostbyname2_r);
    1777             : 
    1778       11963 :         return symbols;
    1779             : }
    1780             : 
    1781       11963 : static void *nwrap_load_module(const char *so_path)
    1782             : {
    1783             :         void *h;
    1784             : 
    1785       11963 :         if (!so_path || !strlen(so_path)) {
    1786           0 :                 return NULL;
    1787             :         }
    1788             : 
    1789       11963 :         h = dlopen(so_path, RTLD_LAZY);
    1790       11963 :         if (!h) {
    1791           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1792             :                           "Cannot open shared library %s",
    1793             :                           so_path);
    1794           0 :                 return NULL;
    1795             :         }
    1796             : 
    1797       11963 :         return h;
    1798             : }
    1799             : 
    1800       31747 : static bool nwrap_module_init(const char *name,
    1801             :                               struct nwrap_ops *ops,
    1802             :                               const char *so_path,
    1803             :                               size_t *num_backends,
    1804             :                               struct nwrap_backend **backends)
    1805             : {
    1806       31747 :         struct nwrap_backend *b = NULL;
    1807       31747 :         size_t n = *num_backends + 1;
    1808             : 
    1809       31747 :         b = realloc(*backends, sizeof(struct nwrap_backend) * n);
    1810       31747 :         if (b == NULL) {
    1811           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    1812           0 :                 return false;
    1813             :         }
    1814       31747 :         *backends = b;
    1815             : 
    1816       31747 :         b = &((*backends)[*num_backends]);
    1817             : 
    1818       31747 :         *b = (struct nwrap_backend) {
    1819             :                 .name = name,
    1820             :                 .ops = ops,
    1821             :                 .so_path = so_path,
    1822             :         };
    1823             : 
    1824       31747 :         if (so_path != NULL) {
    1825       11963 :                 b->so_handle = nwrap_load_module(so_path);
    1826       11963 :                 b->symbols = nwrap_bind_nss_module_symbols(b);
    1827       11963 :                 if (b->symbols == NULL) {
    1828           0 :                         return false;
    1829             :                 }
    1830             :         }
    1831             : 
    1832       31747 :         *num_backends = n;
    1833             : 
    1834       31747 :         return true;
    1835             : }
    1836             : 
    1837       19784 : static void nwrap_libc_init(struct nwrap_main *r)
    1838             : {
    1839       19784 :         r->libc = calloc(1, sizeof(struct nwrap_libc));
    1840       19784 :         if (r->libc == NULL) {
    1841           0 :                 printf("Failed to allocate memory for libc");
    1842           0 :                 exit(-1);
    1843             :         }
    1844       19784 : }
    1845             : 
    1846       19784 : static void nwrap_backend_init(struct nwrap_main *r)
    1847             : {
    1848       19784 :         const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
    1849       19784 :         const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
    1850             : 
    1851       19784 :         r->num_backends = 0;
    1852       19784 :         r->backends = NULL;
    1853             : 
    1854       19784 :         if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
    1855             :                                &r->num_backends,
    1856             :                                &r->backends)) {
    1857           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1858             :                           "Failed to initialize 'files' backend");
    1859           0 :                 return;
    1860             :         }
    1861             : 
    1862       25778 :         if (module_so_path != NULL &&
    1863       17985 :             module_so_path[0] != '\0' &&
    1864       11963 :             module_fn_name != NULL &&
    1865       11963 :             module_fn_name[0] != '\0') {
    1866       11963 :                 if (!nwrap_module_init(module_fn_name,
    1867             :                                        &nwrap_module_ops,
    1868             :                                        module_so_path,
    1869             :                                        &r->num_backends,
    1870             :                                        &r->backends)) {
    1871           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    1872             :                                   "Failed to initialize '%s' backend",
    1873             :                                   module_fn_name);
    1874           0 :                         return;
    1875             :                 }
    1876             :         }
    1877             : }
    1878             : 
    1879     2684299 : static void nwrap_init(void)
    1880             : {
    1881             :         const char *env;
    1882             :         char *endptr;
    1883             :         size_t max_hostents_tmp;
    1884             :         int ok;
    1885             : 
    1886     2684299 :         NWRAP_LOCK(nwrap_initialized);
    1887     2684299 :         if (nwrap_initialized) {
    1888     2664515 :                 NWRAP_UNLOCK(nwrap_initialized);
    1889     2664515 :                 return;
    1890             :         }
    1891             : 
    1892             :         /*
    1893             :          * Still holding nwrap_initialized lock here.
    1894             :          * We don't use NWRAP_(UN)LOCK_ALL macros here because we
    1895             :          * want to avoid overhead when other threads do their job.
    1896             :          */
    1897       19784 :         NWRAP_LOCK(nwrap_global);
    1898       19784 :         NWRAP_LOCK(nwrap_gr_global);
    1899       19784 :         NWRAP_LOCK(nwrap_he_global);
    1900       19784 :         NWRAP_LOCK(nwrap_pw_global);
    1901       19784 :         NWRAP_LOCK(nwrap_sp_global);
    1902             : 
    1903       19784 :         nwrap_initialized = true;
    1904             : 
    1905       19784 :         env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
    1906       19784 :         if (env != NULL) {
    1907       19784 :                 max_hostents_tmp = (size_t)strtoul(env, &endptr, 10);
    1908       32393 :                 if ((*env == '\0') ||
    1909       32393 :                     (*endptr != '\0') ||
    1910             :                     (max_hostents_tmp == 0)) {
    1911           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    1912             :                                   "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
    1913             :                                   "value or value is too small. "
    1914             :                                   "Using default value: %lu.",
    1915             :                                   (unsigned long)max_hostents);
    1916             :                 } else {
    1917       19784 :                         max_hostents = max_hostents_tmp;
    1918             :                 }
    1919             :         }
    1920             :         /* Initialize hash table */
    1921       19784 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    1922             :                   "Initializing hash table of size %lu items.",
    1923             :                   (unsigned long)max_hostents);
    1924       19784 :         ok = hcreate(max_hostents);
    1925       19784 :         if (!ok) {
    1926           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1927             :                           "Failed to initialize hash table");
    1928           0 :                 exit(-1);
    1929             :         }
    1930             : 
    1931       19784 :         nwrap_main_global = &__nwrap_main_global;
    1932             : 
    1933       19784 :         nwrap_libc_init(nwrap_main_global);
    1934             : 
    1935       19784 :         nwrap_backend_init(nwrap_main_global);
    1936             : 
    1937             :         /* passwd */
    1938       19784 :         nwrap_pw_global.cache = &__nwrap_cache_pw;
    1939             : 
    1940       19784 :         nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
    1941       19784 :         nwrap_pw_global.cache->fp = NULL;
    1942       19784 :         nwrap_pw_global.cache->fd = -1;
    1943       19784 :         nwrap_pw_global.cache->private_data = &nwrap_pw_global;
    1944       19784 :         nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
    1945       19784 :         nwrap_pw_global.cache->unload = nwrap_pw_unload;
    1946             : 
    1947             :         /* shadow */
    1948             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    1949       19784 :         nwrap_sp_global.cache = &__nwrap_cache_sp;
    1950             : 
    1951       19784 :         nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
    1952       19784 :         nwrap_sp_global.cache->fp = NULL;
    1953       19784 :         nwrap_sp_global.cache->fd = -1;
    1954       19784 :         nwrap_sp_global.cache->private_data = &nwrap_sp_global;
    1955       19784 :         nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
    1956       19784 :         nwrap_sp_global.cache->unload = nwrap_sp_unload;
    1957             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    1958             : 
    1959             :         /* group */
    1960       19784 :         nwrap_gr_global.cache = &__nwrap_cache_gr;
    1961             : 
    1962       19784 :         nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
    1963       19784 :         nwrap_gr_global.cache->fp = NULL;
    1964       19784 :         nwrap_gr_global.cache->fd = -1;
    1965       19784 :         nwrap_gr_global.cache->private_data = &nwrap_gr_global;
    1966       19784 :         nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
    1967       19784 :         nwrap_gr_global.cache->unload = nwrap_gr_unload;
    1968             : 
    1969             :         /* hosts */
    1970       19784 :         nwrap_he_global.cache = &__nwrap_cache_he;
    1971             : 
    1972       19784 :         nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
    1973       19784 :         nwrap_he_global.cache->fp = NULL;
    1974       19784 :         nwrap_he_global.cache->fd = -1;
    1975       19784 :         nwrap_he_global.cache->private_data = &nwrap_he_global;
    1976       19784 :         nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
    1977       19784 :         nwrap_he_global.cache->unload = nwrap_he_unload;
    1978             : 
    1979             :         /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
    1980       19784 :         NWRAP_UNLOCK_ALL;
    1981             : }
    1982             : 
    1983       69032 : bool nss_wrapper_enabled(void)
    1984             : {
    1985       69032 :         nwrap_init();
    1986             : 
    1987      110568 :         if (nwrap_pw_global.cache->path == NULL ||
    1988       65321 :             nwrap_pw_global.cache->path[0] == '\0') {
    1989        3900 :                 return false;
    1990             :         }
    1991      106479 :         if (nwrap_gr_global.cache->path == NULL ||
    1992       65132 :             nwrap_gr_global.cache->path[0] == '\0') {
    1993         189 :                 return false;
    1994             :         }
    1995             : 
    1996       64943 :         return true;
    1997             : }
    1998             : 
    1999             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    2000           0 : bool nss_wrapper_shadow_enabled(void)
    2001             : {
    2002           0 :         nwrap_init();
    2003             : 
    2004           0 :         if (nwrap_sp_global.cache->path == NULL ||
    2005           0 :             nwrap_sp_global.cache->path[0] == '\0') {
    2006           0 :                 return false;
    2007             :         }
    2008             : 
    2009           0 :         return true;
    2010             : }
    2011             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    2012             : 
    2013     2145655 : bool nss_wrapper_hosts_enabled(void)
    2014             : {
    2015     2145655 :         nwrap_init();
    2016             : 
    2017     3801595 :         if (nwrap_he_global.cache->path == NULL ||
    2018     2041243 :             nwrap_he_global.cache->path[0] == '\0') {
    2019      108584 :                 return false;
    2020             :         }
    2021             : 
    2022     2037071 :         return true;
    2023             : }
    2024             : 
    2025       32423 : static bool nwrap_hostname_enabled(void)
    2026             : {
    2027       32423 :         nwrap_init();
    2028             : 
    2029       32423 :         if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
    2030        7180 :                 return false;
    2031             :         }
    2032             : 
    2033       25243 :         return true;
    2034             : }
    2035             : 
    2036       17908 : static bool nwrap_parse_file(struct nwrap_cache *nwrap)
    2037             : {
    2038       17908 :         char *line = NULL;
    2039             :         ssize_t n;
    2040             :         /* Unused but getline needs it */
    2041             :         size_t len;
    2042             :         bool ok;
    2043             : 
    2044       17908 :         if (nwrap->st.st_size == 0) {
    2045           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
    2046           0 :                 return true;
    2047             :         }
    2048             : 
    2049             :         /* Support for 32-bit system I guess */
    2050       17908 :         if (nwrap->st.st_size > INT32_MAX) {
    2051           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2052             :                           "Size[%u] larger than INT32_MAX",
    2053             :                           (unsigned)nwrap->st.st_size);
    2054           0 :                 return false;
    2055             :         }
    2056             : 
    2057       17908 :         rewind(nwrap->fp);
    2058             : 
    2059             :         do {
    2060      202834 :                 n = getline(&line, &len, nwrap->fp);
    2061      202834 :                 if (n < 0) {
    2062       17908 :                         SAFE_FREE(line);
    2063       17908 :                         if (feof(nwrap->fp)) {
    2064       17908 :                                 break;
    2065             :                         }
    2066             : 
    2067           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2068             :                                   "Unable to read line from file: %s",
    2069             :                                   nwrap->path);
    2070           0 :                         return false;
    2071             :                 }
    2072             : 
    2073      184926 :                 if (line[n - 1] == '\n') {
    2074      184926 :                         line[n - 1] = '\0';
    2075             :                 }
    2076             : 
    2077      184926 :                 if (line[0] == '\0') {
    2078           0 :                         SAFE_FREE(line);
    2079           0 :                         continue;
    2080             :                 }
    2081             : 
    2082      184926 :                 ok = nwrap->parse_line(nwrap, line);
    2083      184926 :                 if (!ok) {
    2084           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2085             :                                   "Unable to parse line file: %s",
    2086             :                                   line);
    2087           0 :                         SAFE_FREE(line);
    2088           0 :                         return false;
    2089             :                 }
    2090             : 
    2091             :                 /* Line is parsed without issues so add it to list */
    2092      184926 :                 ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
    2093      184926 :                 if (!ok) {
    2094           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2095             :                                   "Unable to add line to vector");
    2096           0 :                         return false;
    2097             :                 }
    2098             : 
    2099             :                 /* This forces getline to allocate new memory for line. */
    2100      184926 :                 line = NULL;
    2101      184926 :         } while (!feof(nwrap->fp));
    2102             : 
    2103       17908 :         return true;
    2104             : }
    2105             : 
    2106      172940 : static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
    2107             : {
    2108      172940 :         nwrap->unload(nwrap);
    2109             : 
    2110      172940 :         nwrap_lines_unload(nwrap);
    2111      172940 : }
    2112             : 
    2113      671529 : static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
    2114             : {
    2115             :         struct stat st;
    2116             :         int ret;
    2117             :         bool ok;
    2118      671529 :         bool retried = false;
    2119             : 
    2120      671529 :         assert(nwrap != NULL);
    2121             : 
    2122      544050 : reopen:
    2123      672039 :         if (nwrap->fd < 0) {
    2124       17422 :                 nwrap->fp = fopen(nwrap->path, "re");
    2125       17422 :                 if (nwrap->fp == NULL) {
    2126           0 :                         nwrap->fd = -1;
    2127           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2128             :                                   "Unable to open '%s' readonly %d:%s",
    2129             :                                   nwrap->path, nwrap->fd,
    2130             :                                   strerror(errno));
    2131           0 :                         return false;
    2132             : 
    2133             :                 }
    2134       17422 :                 nwrap->fd = fileno(nwrap->fp);
    2135       17422 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
    2136             :         }
    2137             : 
    2138      672039 :         ret = fstat(nwrap->fd, &st);
    2139      672039 :         if (ret != 0 && errno == EBADF && retried == false) {
    2140             :                 /* maybe something closed the fd on our behalf */
    2141           0 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2142             :                           "fstat(%s) - %d:%s - reopen",
    2143             :                           nwrap->path,
    2144             :                           ret,
    2145             :                           strerror(errno));
    2146           0 :                 retried = true;
    2147           0 :                 memset(&nwrap->st, 0, sizeof(nwrap->st));
    2148           0 :                 fclose(nwrap->fp);
    2149           0 :                 nwrap->fp = NULL;
    2150           0 :                 nwrap->fd = -1;
    2151           0 :                 goto reopen;
    2152             :         }
    2153      672039 :         else if (ret != 0) {
    2154           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2155             :                           "fstat(%s) - %d:%s",
    2156             :                           nwrap->path,
    2157             :                           ret,
    2158             :                           strerror(errno));
    2159           0 :                 fclose(nwrap->fp);
    2160           0 :                 nwrap->fp = NULL;
    2161           0 :                 nwrap->fd = -1;
    2162           0 :                 return false;
    2163             :         }
    2164             : 
    2165      672039 :         if (retried == false && st.st_nlink == 0) {
    2166             :                 /* maybe someone has replaced the file... */
    2167         510 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2168             :                           "st_nlink == 0, reopen %s",
    2169             :                           nwrap->path);
    2170         510 :                 retried = true;
    2171         510 :                 memset(&nwrap->st, 0, sizeof(nwrap->st));
    2172         510 :                 fclose(nwrap->fp);
    2173         510 :                 nwrap->fp = NULL;
    2174         510 :                 nwrap->fd = -1;
    2175         510 :                 goto reopen;
    2176             :         }
    2177             : 
    2178      671529 :         if (st.st_mtime == nwrap->st.st_mtime) {
    2179      653621 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2180             :                           "st_mtime[%u] hasn't changed, skip reload",
    2181             :                           (unsigned)st.st_mtime);
    2182      653621 :                 return true;
    2183             :         }
    2184             : 
    2185       17908 :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2186             :                   "st_mtime has changed [%u] => [%u], start reload",
    2187             :                   (unsigned)st.st_mtime,
    2188             :                   (unsigned)nwrap->st.st_mtime);
    2189             : 
    2190       17908 :         nwrap->st = st;
    2191             : 
    2192       17908 :         nwrap_files_cache_unload(nwrap);
    2193             : 
    2194       17908 :         ok = nwrap_parse_file(nwrap);
    2195       17908 :         if (!ok) {
    2196           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
    2197           0 :                 nwrap_files_cache_unload(nwrap);
    2198           0 :                 return false;
    2199             :         }
    2200             : 
    2201       17908 :         NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
    2202       17908 :         return true;
    2203             : }
    2204             : 
    2205             : /*
    2206             :  * the caller has to call nwrap_unload() on failure
    2207             :  */
    2208      124875 : static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
    2209             : {
    2210             :         struct nwrap_pw *nwrap_pw;
    2211             :         char *c;
    2212             :         char *p;
    2213             :         char *e;
    2214             :         struct passwd *pw;
    2215             :         size_t list_size;
    2216             : 
    2217      124875 :         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
    2218             : 
    2219      124875 :         list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
    2220      124875 :         pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
    2221      124875 :         if (!pw) {
    2222           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2223             :                           "realloc(%u) failed",
    2224             :                           (unsigned)list_size);
    2225           0 :                 return false;
    2226             :         }
    2227      124875 :         nwrap_pw->list = pw;
    2228             : 
    2229      124875 :         pw = &nwrap_pw->list[nwrap_pw->num];
    2230             : 
    2231      124875 :         c = line;
    2232             : 
    2233             :         /* name */
    2234      124875 :         p = strchr(c, ':');
    2235      124875 :         if (!p) {
    2236           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2237             :                           "Invalid line[%s]: '%s'",
    2238             :                           line,
    2239             :                           c);
    2240           0 :                 return false;
    2241             :         }
    2242      124875 :         *p = '\0';
    2243      124875 :         p++;
    2244      124875 :         pw->pw_name = c;
    2245      124875 :         c = p;
    2246             : 
    2247      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
    2248             : 
    2249             :         /* password */
    2250      124875 :         p = strchr(c, ':');
    2251      124875 :         if (!p) {
    2252           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2253           0 :                 return false;
    2254             :         }
    2255      124875 :         *p = '\0';
    2256      124875 :         p++;
    2257      124875 :         pw->pw_passwd = c;
    2258      124875 :         c = p;
    2259             : 
    2260      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
    2261             : 
    2262             :         /* uid */
    2263      124875 :         p = strchr(c, ':');
    2264      124875 :         if (!p) {
    2265           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2266           0 :                 return false;
    2267             :         }
    2268      124875 :         *p = '\0';
    2269      124875 :         p++;
    2270      124875 :         e = NULL;
    2271      124875 :         pw->pw_uid = (uid_t)strtoul(c, &e, 10);
    2272      124875 :         if (c == e) {
    2273           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2274             :                           "Invalid line[%s]: '%s' - %s",
    2275             :                           line, c, strerror(errno));
    2276           0 :                 return false;
    2277             :         }
    2278      124875 :         if (e == NULL) {
    2279           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2280             :                           "Invalid line[%s]: '%s' - %s",
    2281             :                           line, c, strerror(errno));
    2282           0 :                 return false;
    2283             :         }
    2284      124875 :         if (e[0] != '\0') {
    2285           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2286             :                           "Invalid line[%s]: '%s' - %s",
    2287             :                           line, c, strerror(errno));
    2288           0 :                 return false;
    2289             :         }
    2290      124875 :         c = p;
    2291             : 
    2292      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
    2293             : 
    2294             :         /* gid */
    2295      124875 :         p = strchr(c, ':');
    2296      124875 :         if (!p) {
    2297           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2298           0 :                 return false;
    2299             :         }
    2300      124875 :         *p = '\0';
    2301      124875 :         p++;
    2302      124875 :         e = NULL;
    2303      124875 :         pw->pw_gid = (gid_t)strtoul(c, &e, 10);
    2304      124875 :         if (c == e) {
    2305           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2306             :                           "Invalid line[%s]: '%s' - %s",
    2307             :                           line, c, strerror(errno));
    2308           0 :                 return false;
    2309             :         }
    2310      124875 :         if (e == NULL) {
    2311           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2312             :                           "Invalid line[%s]: '%s' - %s",
    2313             :                           line, c, strerror(errno));
    2314           0 :                 return false;
    2315             :         }
    2316      124875 :         if (e[0] != '\0') {
    2317           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2318             :                           "Invalid line[%s]: '%s' - %s",
    2319             :                           line, c, strerror(errno));
    2320           0 :                 return false;
    2321             :         }
    2322      124875 :         c = p;
    2323             : 
    2324      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
    2325             : 
    2326             : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
    2327             :         pw->pw_class = discard_const_p(char, "");
    2328             : 
    2329             :         NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class);
    2330             : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
    2331             : 
    2332             : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
    2333             :         pw->pw_change = 0;
    2334             : 
    2335             :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2336             :                   "change[%lu]",
    2337             :                   (unsigned long)pw->pw_change);
    2338             : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
    2339             : 
    2340             : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
    2341             :         pw->pw_expire = 0;
    2342             : 
    2343             :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2344             :                   "expire[%lu]",
    2345             :                   (unsigned long)pw->pw_expire);
    2346             : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
    2347             : 
    2348             :         /* gecos */
    2349      124875 :         p = strchr(c, ':');
    2350      124875 :         if (!p) {
    2351           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
    2352           0 :                 return false;
    2353             :         }
    2354      124875 :         *p = '\0';
    2355      124875 :         p++;
    2356      124875 :         pw->pw_gecos = c;
    2357      124875 :         c = p;
    2358             : 
    2359      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
    2360             : 
    2361             :         /* dir */
    2362      124875 :         p = strchr(c, ':');
    2363      124875 :         if (!p) {
    2364           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
    2365           0 :                 return false;
    2366             :         }
    2367      124875 :         *p = '\0';
    2368      124875 :         p++;
    2369      124875 :         pw->pw_dir = c;
    2370      124875 :         c = p;
    2371             : 
    2372      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
    2373             : 
    2374             :         /* shell */
    2375      124875 :         pw->pw_shell = c;
    2376      124875 :         NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
    2377             : 
    2378      124875 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    2379             :                   "Added user[%s:%s:%u:%u:%s:%s:%s]",
    2380             :                   pw->pw_name, pw->pw_passwd,
    2381             :                   pw->pw_uid, pw->pw_gid,
    2382             :                   pw->pw_gecos, pw->pw_dir, pw->pw_shell);
    2383             : 
    2384      124875 :         nwrap_pw->num++;
    2385      124875 :         return true;
    2386             : }
    2387             : 
    2388       48877 : static void nwrap_pw_unload(struct nwrap_cache *nwrap)
    2389             : {
    2390             :         struct nwrap_pw *nwrap_pw;
    2391       48877 :         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
    2392             : 
    2393       48877 :         SAFE_FREE(nwrap_pw->list);
    2394       48877 :         nwrap_pw->num = 0;
    2395       48877 :         nwrap_pw->idx = 0;
    2396       48877 : }
    2397             : 
    2398         269 : static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
    2399             :                            char *buf, size_t buflen, struct passwd **dstp)
    2400             : {
    2401             :         char *first;
    2402             :         char *last;
    2403             :         off_t ofs;
    2404             : 
    2405         269 :         first = src->pw_name;
    2406             : 
    2407         269 :         last = src->pw_shell;
    2408        1879 :         while (*last) last++;
    2409             : 
    2410         269 :         ofs = PTR_DIFF(last + 1, first);
    2411             : 
    2412         269 :         if (ofs > (off_t) buflen) {
    2413           0 :                 return ERANGE;
    2414             :         }
    2415             : 
    2416         269 :         memcpy(buf, first, ofs);
    2417             : 
    2418         269 :         ofs = PTR_DIFF(src->pw_name, first);
    2419         269 :         dst->pw_name = buf + ofs;
    2420         269 :         ofs = PTR_DIFF(src->pw_passwd, first);
    2421         269 :         dst->pw_passwd = buf + ofs;
    2422         269 :         dst->pw_uid = src->pw_uid;
    2423         269 :         dst->pw_gid = src->pw_gid;
    2424             : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
    2425             :         ofs = PTR_DIFF(src->pw_class, first);
    2426             :         dst->pw_class = buf + ofs;
    2427             : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
    2428             : 
    2429             : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
    2430             :         dst->pw_change = 0;
    2431             : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
    2432             : 
    2433             : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
    2434             :         dst->pw_expire = 0;
    2435             : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
    2436             : 
    2437         269 :         ofs = PTR_DIFF(src->pw_gecos, first);
    2438         269 :         dst->pw_gecos = buf + ofs;
    2439         269 :         ofs = PTR_DIFF(src->pw_dir, first);
    2440         269 :         dst->pw_dir = buf + ofs;
    2441         269 :         ofs = PTR_DIFF(src->pw_shell, first);
    2442         269 :         dst->pw_shell = buf + ofs;
    2443             : 
    2444         269 :         if (dstp) {
    2445         269 :                 *dstp = dst;
    2446             :         }
    2447             : 
    2448         269 :         return 0;
    2449             : }
    2450             : 
    2451             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    2452           0 : static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
    2453             : {
    2454             :         struct nwrap_sp *nwrap_sp;
    2455             :         struct spwd *sp;
    2456             :         size_t list_size;
    2457             :         char *c;
    2458             :         char *e;
    2459             :         char *p;
    2460             : 
    2461           0 :         nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
    2462             : 
    2463           0 :         list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
    2464           0 :         sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
    2465           0 :         if (sp == NULL) {
    2466           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2467             :                           "realloc(%u) failed",
    2468             :                           (unsigned)list_size);
    2469           0 :                 return false;
    2470             :         }
    2471           0 :         nwrap_sp->list = sp;
    2472             : 
    2473           0 :         sp = &nwrap_sp->list[nwrap_sp->num];
    2474             : 
    2475           0 :         c = line;
    2476             : 
    2477             :         /* name */
    2478           0 :         p = strchr(c, ':');
    2479           0 :         if (p == NULL) {
    2480           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2481             :                           "name -- Invalid line[%s]: '%s'",
    2482             :                           line,
    2483             :                           c);
    2484           0 :                 return false;
    2485             :         }
    2486           0 :         *p = '\0';
    2487           0 :         p++;
    2488           0 :         sp->sp_namp = c;
    2489           0 :         c = p;
    2490             : 
    2491           0 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
    2492             : 
    2493             :         /* pwd */
    2494           0 :         p = strchr(c, ':');
    2495           0 :         if (p == NULL) {
    2496           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2497             :                           "pwd -- Invalid line[%s]: '%s'",
    2498             :                           line,
    2499             :                           c);
    2500           0 :                 return false;
    2501             :         }
    2502           0 :         *p = '\0';
    2503           0 :         p++;
    2504           0 :         sp->sp_pwdp = c;
    2505           0 :         c = p;
    2506             : 
    2507             :         /* lstchg (long) */
    2508           0 :         if (c[0] == ':') {
    2509           0 :                 sp->sp_lstchg = -1;
    2510           0 :                 p++;
    2511             :         } else {
    2512           0 :                 p = strchr(c, ':');
    2513           0 :                 if (p == NULL) {
    2514           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2515             :                                   "lstchg -- Invalid line[%s]: '%s'",
    2516             :                                   line,
    2517             :                                   c);
    2518           0 :                         return false;
    2519             :                 }
    2520           0 :                 *p = '\0';
    2521           0 :                 p++;
    2522           0 :                 sp->sp_lstchg = strtol(c, &e, 10);
    2523           0 :                 if (c == e) {
    2524           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2525             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2526             :                                   line, c, strerror(errno));
    2527           0 :                         return false;
    2528             :                 }
    2529           0 :                 if (e == NULL) {
    2530           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2531             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2532             :                                   line, c, strerror(errno));
    2533           0 :                         return false;
    2534             :                 }
    2535           0 :                 if (e[0] != '\0') {
    2536           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2537             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2538             :                                   line, c, strerror(errno));
    2539           0 :                         return false;
    2540             :                 }
    2541             :         }
    2542           0 :         c = p;
    2543             : 
    2544             :         /* min (long) */
    2545           0 :         if (c[0] == ':') {
    2546           0 :                 sp->sp_min = -1;
    2547           0 :                 p++;
    2548             :         } else {
    2549           0 :                 p = strchr(c, ':');
    2550           0 :                 if (p == NULL) {
    2551           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2552             :                                   "min -- Invalid line[%s]: '%s'",
    2553             :                                   line,
    2554             :                                   c);
    2555           0 :                         return false;
    2556             :                 }
    2557           0 :                 *p = '\0';
    2558           0 :                 p++;
    2559           0 :                 sp->sp_min = strtol(c, &e, 10);
    2560           0 :                 if (c == e) {
    2561           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2562             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2563             :                                   line, c, strerror(errno));
    2564           0 :                         return false;
    2565             :                 }
    2566           0 :                 if (e == NULL) {
    2567           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2568             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2569             :                                   line, c, strerror(errno));
    2570           0 :                         return false;
    2571             :                 }
    2572           0 :                 if (e[0] != '\0') {
    2573           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2574             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2575             :                                   line, c, strerror(errno));
    2576           0 :                         return false;
    2577             :                 }
    2578             :         }
    2579           0 :         c = p;
    2580             : 
    2581             :         /* max (long) */
    2582           0 :         if (c[0] == ':') {
    2583           0 :                 sp->sp_max = -1;
    2584           0 :                 p++;
    2585             :         } else {
    2586           0 :                 p = strchr(c, ':');
    2587           0 :                 if (p == NULL) {
    2588           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2589             :                                   "max -- Invalid line[%s]: '%s'",
    2590             :                                   line,
    2591             :                                   c);
    2592           0 :                         return false;
    2593             :                 }
    2594           0 :                 *p = '\0';
    2595           0 :                 p++;
    2596           0 :                 sp->sp_max = strtol(c, &e, 10);
    2597           0 :                 if (c == e) {
    2598           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2599             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2600             :                                   line, c, strerror(errno));
    2601           0 :                         return false;
    2602             :                 }
    2603           0 :                 if (e == NULL) {
    2604           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2605             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2606             :                                   line, c, strerror(errno));
    2607           0 :                         return false;
    2608             :                 }
    2609           0 :                 if (e[0] != '\0') {
    2610           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2611             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2612             :                                   line, c, strerror(errno));
    2613           0 :                         return false;
    2614             :                 }
    2615             :         }
    2616           0 :         c = p;
    2617             : 
    2618             :         /* warn (long) */
    2619           0 :         if (c[0] == ':') {
    2620           0 :                 sp->sp_warn = -1;
    2621           0 :                 p++;
    2622             :         } else {
    2623           0 :                 p = strchr(c, ':');
    2624           0 :                 if (p == NULL) {
    2625           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2626             :                                   "warn -- Invalid line[%s]: '%s'",
    2627             :                                   line,
    2628             :                                   c);
    2629           0 :                         return false;
    2630             :                 }
    2631           0 :                 *p = '\0';
    2632           0 :                 p++;
    2633           0 :                 sp->sp_warn = strtol(c, &e, 10);
    2634           0 :                 if (c == e) {
    2635           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2636             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2637             :                                   line, c, strerror(errno));
    2638           0 :                         return false;
    2639             :                 }
    2640           0 :                 if (e == NULL) {
    2641           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2642             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2643             :                                   line, c, strerror(errno));
    2644           0 :                         return false;
    2645             :                 }
    2646           0 :                 if (e[0] != '\0') {
    2647           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2648             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2649             :                                   line, c, strerror(errno));
    2650           0 :                         return false;
    2651             :                 }
    2652             :         }
    2653           0 :         c = p;
    2654             : 
    2655             :         /* inact (long) */
    2656           0 :         if (c[0] == ':') {
    2657           0 :                 sp->sp_inact = -1;
    2658           0 :                 p++;
    2659             :         } else {
    2660           0 :                 p = strchr(c, ':');
    2661           0 :                 if (p == NULL) {
    2662           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2663             :                                   "inact -- Invalid line[%s]: '%s'",
    2664             :                                   line,
    2665             :                                   c);
    2666           0 :                         return false;
    2667             :                 }
    2668           0 :                 *p = '\0';
    2669           0 :                 p++;
    2670           0 :                 sp->sp_inact = strtol(c, &e, 10);
    2671           0 :                 if (c == e) {
    2672           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2673             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2674             :                                   line, c, strerror(errno));
    2675           0 :                         return false;
    2676             :                 }
    2677           0 :                 if (e == NULL) {
    2678           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2679             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2680             :                                   line, c, strerror(errno));
    2681           0 :                         return false;
    2682             :                 }
    2683           0 :                 if (e[0] != '\0') {
    2684           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2685             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2686             :                                   line, c, strerror(errno));
    2687           0 :                         return false;
    2688             :                 }
    2689             :         }
    2690           0 :         c = p;
    2691             : 
    2692             :         /* expire (long) */
    2693           0 :         if (c[0] == ':') {
    2694           0 :                 sp->sp_expire = -1;
    2695           0 :                 p++;
    2696             :         } else {
    2697           0 :                 p = strchr(c, ':');
    2698           0 :                 if (p == NULL) {
    2699           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2700             :                                   "expire -- Invalid line[%s]: '%s'",
    2701             :                                   line,
    2702             :                                   c);
    2703           0 :                         return false;
    2704             :                 }
    2705           0 :                 *p = '\0';
    2706           0 :                 p++;
    2707           0 :                 sp->sp_expire = strtol(c, &e, 10);
    2708           0 :                 if (c == e) {
    2709           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2710             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2711             :                                   line, c, strerror(errno));
    2712           0 :                         return false;
    2713             :                 }
    2714           0 :                 if (e == NULL) {
    2715           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2716             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2717             :                                   line, c, strerror(errno));
    2718           0 :                         return false;
    2719             :                 }
    2720           0 :                 if (e[0] != '\0') {
    2721           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2722             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2723             :                                   line, c, strerror(errno));
    2724           0 :                         return false;
    2725             :                 }
    2726             :         }
    2727           0 :         c = p;
    2728             : 
    2729           0 :         nwrap_sp->num++;
    2730           0 :         return true;
    2731             : }
    2732             : 
    2733       38758 : static void nwrap_sp_unload(struct nwrap_cache *nwrap)
    2734             : {
    2735             :         struct nwrap_sp *nwrap_sp;
    2736       38758 :         nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
    2737             : 
    2738       38758 :         SAFE_FREE(nwrap_sp->list);
    2739       38758 :         nwrap_sp->num = 0;
    2740       38758 :         nwrap_sp->idx = 0;
    2741       38758 : }
    2742             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    2743             : 
    2744             : /*
    2745             :  * the caller has to call nwrap_unload() on failure
    2746             :  */
    2747        4339 : static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
    2748             : {
    2749             :         struct nwrap_gr *nwrap_gr;
    2750             :         char *c;
    2751             :         char *p;
    2752             :         char *e;
    2753             :         struct group *gr;
    2754             :         size_t list_size;
    2755             :         unsigned nummem;
    2756             : 
    2757        4339 :         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
    2758             : 
    2759        4339 :         list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
    2760        4339 :         gr = (struct group *)realloc(nwrap_gr->list, list_size);
    2761        4339 :         if (!gr) {
    2762           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
    2763           0 :                 return false;
    2764             :         }
    2765        4339 :         nwrap_gr->list = gr;
    2766             : 
    2767        4339 :         gr = &nwrap_gr->list[nwrap_gr->num];
    2768             : 
    2769        4339 :         c = line;
    2770             : 
    2771             :         /* name */
    2772        4339 :         p = strchr(c, ':');
    2773        4339 :         if (!p) {
    2774           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2775           0 :                 return false;
    2776             :         }
    2777        4339 :         *p = '\0';
    2778        4339 :         p++;
    2779        4339 :         gr->gr_name = c;
    2780        4339 :         c = p;
    2781             : 
    2782        4339 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
    2783             : 
    2784             :         /* password */
    2785        4339 :         p = strchr(c, ':');
    2786        4339 :         if (!p) {
    2787           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2788           0 :                 return false;
    2789             :         }
    2790        4339 :         *p = '\0';
    2791        4339 :         p++;
    2792        4339 :         gr->gr_passwd = c;
    2793        4339 :         c = p;
    2794             : 
    2795        4339 :         NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
    2796             : 
    2797             :         /* gid */
    2798        4339 :         p = strchr(c, ':');
    2799        4339 :         if (!p) {
    2800           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2801           0 :                 return false;
    2802             :         }
    2803        4339 :         *p = '\0';
    2804        4339 :         p++;
    2805        4339 :         e = NULL;
    2806        4339 :         gr->gr_gid = (gid_t)strtoul(c, &e, 10);
    2807        4339 :         if (c == e) {
    2808           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2809             :                           "Invalid line[%s]: '%s' - %s",
    2810             :                           line, c, strerror(errno));
    2811           0 :                 return false;
    2812             :         }
    2813        4339 :         if (e == NULL) {
    2814           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2815             :                           "Invalid line[%s]: '%s' - %s",
    2816             :                           line, c, strerror(errno));
    2817           0 :                 return false;
    2818             :         }
    2819        4339 :         if (e[0] != '\0') {
    2820           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2821             :                           "Invalid line[%s]: '%s' - %s",
    2822             :                           line, c, strerror(errno));
    2823           0 :                 return false;
    2824             :         }
    2825        4339 :         c = p;
    2826             : 
    2827        4339 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
    2828             : 
    2829             :         /* members */
    2830        4339 :         gr->gr_mem = (char **)malloc(sizeof(char *));
    2831        4339 :         if (!gr->gr_mem) {
    2832           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    2833           0 :                 return false;
    2834             :         }
    2835        4339 :         gr->gr_mem[0] = NULL;
    2836             : 
    2837        5684 :         for(nummem = 0; p != NULL && p[0] != '\0'; nummem++) {
    2838             :                 char **m;
    2839             :                 size_t m_size;
    2840        1345 :                 c = p;
    2841        1345 :                 p = strchr(c, ',');
    2842        1345 :                 if (p) {
    2843           0 :                         *p = '\0';
    2844           0 :                         p++;
    2845             :                 }
    2846             : 
    2847        1345 :                 if (strlen(c) == 0) {
    2848           0 :                         break;
    2849             :                 }
    2850             : 
    2851        1345 :                 m_size = sizeof(char *) * (nummem+2);
    2852        1345 :                 m = (char **)realloc(gr->gr_mem, m_size);
    2853        1345 :                 if (!m) {
    2854           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2855             :                                   "realloc(%zd) failed",
    2856             :                                   m_size);
    2857           0 :                         return false;
    2858             :                 }
    2859        1345 :                 gr->gr_mem = m;
    2860        1345 :                 gr->gr_mem[nummem] = c;
    2861        1345 :                 gr->gr_mem[nummem+1] = NULL;
    2862             : 
    2863        1345 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2864             :                           "member[%u]: '%s'",
    2865             :                           nummem, gr->gr_mem[nummem]);
    2866             :         }
    2867             : 
    2868        4339 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    2869             :                   "Added group[%s:%s:%u:] with %u members",
    2870             :                   gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
    2871             : 
    2872        4339 :         nwrap_gr->num++;
    2873        4339 :         return true;
    2874             : }
    2875             : 
    2876       39242 : static void nwrap_gr_unload(struct nwrap_cache *nwrap)
    2877             : {
    2878             :         int i;
    2879             :         struct nwrap_gr *nwrap_gr;
    2880       39242 :         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
    2881             : 
    2882       39242 :         if (nwrap_gr->list) {
    2883       48977 :                 for (i=0; i < nwrap_gr->num; i++) {
    2884       43266 :                         SAFE_FREE(nwrap_gr->list[i].gr_mem);
    2885             :                 }
    2886        5711 :                 SAFE_FREE(nwrap_gr->list);
    2887             :         }
    2888             : 
    2889       39242 :         nwrap_gr->num = 0;
    2890       39242 :         nwrap_gr->idx = 0;
    2891       39242 : }
    2892             : 
    2893         149 : static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
    2894             :                            char *buf, size_t buflen, struct group **dstp)
    2895             : {
    2896         149 :         char *p = NULL;
    2897         149 :         uintptr_t align = 0;
    2898         149 :         unsigned int gr_mem_cnt = 0;
    2899             :         unsigned i;
    2900             :         size_t total_len;
    2901         149 :         size_t gr_name_len = strlen(src->gr_name) + 1;
    2902         149 :         size_t gr_passwd_len = strlen(src->gr_passwd) + 1;
    2903             :         union {
    2904             :                 char *ptr;
    2905             :                 char **data;
    2906             :         } g_mem;
    2907             : 
    2908         197 :         for (i = 0; src->gr_mem[i] != NULL; i++) {
    2909          48 :                 gr_mem_cnt++;
    2910             :         }
    2911             : 
    2912             :         /* Align the memory for storing pointers */
    2913         149 :         align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *));
    2914         215 :         total_len = align +
    2915         215 :                     (1 + gr_mem_cnt) * sizeof(char *) +
    2916             :                     gr_name_len + gr_passwd_len;
    2917             : 
    2918         149 :         if (total_len > buflen) {
    2919           0 :                 errno = ERANGE;
    2920           0 :                 return -1;
    2921             :         }
    2922         149 :         buflen -= total_len;
    2923             : 
    2924             :         /* gr_mem */
    2925         149 :         p = buf + align;
    2926         149 :         g_mem.ptr = p;
    2927         149 :         dst->gr_mem = g_mem.data;
    2928             : 
    2929             :         /* gr_name */
    2930         149 :         p += (1 + gr_mem_cnt) * sizeof(char *);
    2931         149 :         dst->gr_name = p;
    2932             : 
    2933             :         /* gr_passwd */
    2934         149 :         p += gr_name_len;
    2935         149 :         dst->gr_passwd = p;
    2936             : 
    2937             :         /* gr_mem[x] */
    2938         149 :         p += gr_passwd_len;
    2939             : 
    2940             :         /* gr_gid */
    2941         149 :         dst->gr_gid = src->gr_gid;
    2942             : 
    2943         149 :         memcpy(dst->gr_name, src->gr_name, gr_name_len);
    2944             : 
    2945         149 :         memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len);
    2946             : 
    2947             :         /* Set the terminating entry */
    2948         149 :         dst->gr_mem[gr_mem_cnt] = NULL;
    2949             : 
    2950             :         /* Now add the group members content */
    2951         149 :         total_len = 0;
    2952         197 :         for (i = 0; i < gr_mem_cnt; i++) {
    2953          48 :                 size_t len = strlen(src->gr_mem[i]) + 1;
    2954             : 
    2955          48 :                 dst->gr_mem[i] = p;
    2956          48 :                 total_len += len;
    2957          48 :                 p += len;
    2958             :         }
    2959             : 
    2960         149 :         if (total_len > buflen) {
    2961           0 :                 errno = ERANGE;
    2962           0 :                 return -1;
    2963             :         }
    2964             : 
    2965         197 :         for (i = 0; i < gr_mem_cnt; i++) {
    2966          48 :                 size_t len = strlen(src->gr_mem[i]) + 1;
    2967             : 
    2968          48 :                 memcpy(dst->gr_mem[i],
    2969          48 :                        src->gr_mem[i],
    2970             :                        len);
    2971             :         }
    2972             : 
    2973         149 :         if (dstp != NULL) {
    2974         149 :                 *dstp = dst;
    2975             :         }
    2976             : 
    2977         149 :         return 0;
    2978             : }
    2979             : 
    2980      174670 : static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
    2981             : {
    2982             :         struct nwrap_entlist *el;
    2983             : 
    2984      174670 :         if (ed == NULL) {
    2985           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2986             :                           "entry is NULL, can't create list item");
    2987           0 :                 return NULL;
    2988             :         }
    2989             : 
    2990      174670 :         el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
    2991      174670 :         if (el == NULL) {
    2992           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
    2993           0 :                 return NULL;
    2994             :         }
    2995             : 
    2996      174670 :         el->next = NULL;
    2997      174670 :         el->ed = ed;
    2998             : 
    2999      174670 :         return el;
    3000             : }
    3001             : 
    3002      115191 : static bool nwrap_ed_inventarize_add_new(char *const h_name,
    3003             :                                          struct nwrap_entdata *const ed)
    3004             : {
    3005             :         ENTRY e;
    3006             :         ENTRY *p;
    3007             :         struct nwrap_entlist *el;
    3008             :         bool ok;
    3009             : 
    3010      115191 :         if (h_name == NULL) {
    3011           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
    3012           0 :                 return false;
    3013             :         }
    3014             : 
    3015      115191 :         el = nwrap_entlist_init(ed);
    3016      115191 :         if (el == NULL) {
    3017           0 :                 return false;
    3018             :         }
    3019             : 
    3020      115191 :         e.key = h_name;
    3021      115191 :         e.data = (void *)el;
    3022             : 
    3023      115191 :         p = hsearch(e, ENTER);
    3024      115191 :         if (p == NULL) {
    3025           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3026             :                           "Hash table is full (%s)!",
    3027             :                           strerror(errno));
    3028           0 :                 return false;
    3029             :         }
    3030             : 
    3031      115191 :         ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
    3032      115191 :         if (!ok) {
    3033           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3034             :                           "Failed to add list entry to vector.");
    3035           0 :                 return false;
    3036             :         }
    3037             : 
    3038      115191 :         return true;
    3039             : }
    3040             : 
    3041       59479 : static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
    3042             :                                                  struct nwrap_entlist *const el)
    3043             : {
    3044             :         struct nwrap_entlist *cursor;
    3045             :         struct nwrap_entlist *el_new;
    3046             : 
    3047       59479 :         if (el == NULL) {
    3048           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
    3049           0 :                 return false;
    3050             :         }
    3051             : 
    3052             : 
    3053       59479 :         for (cursor = el; cursor->next != NULL; cursor = cursor->next)
    3054             :         {
    3055           0 :                 if (cursor->ed == ed) {
    3056             :                         /* The entry already exists in this list. */
    3057           0 :                         return true;
    3058             :                 }
    3059             :         }
    3060             : 
    3061       59479 :         if (cursor->ed == ed) {
    3062             :                 /* The entry already exists in this list. */
    3063           0 :                 return true;
    3064             :         }
    3065             : 
    3066       59479 :         el_new = nwrap_entlist_init(ed);
    3067       59479 :         if (el_new == NULL) {
    3068           0 :                 return false;
    3069             :         }
    3070             : 
    3071       59479 :         cursor->next = el_new;
    3072       59479 :         return true;
    3073             : }
    3074             : 
    3075      174670 : static bool nwrap_ed_inventarize(char *const name,
    3076             :                                  struct nwrap_entdata *const ed)
    3077             : {
    3078             :         ENTRY e;
    3079             :         ENTRY *p;
    3080             :         bool ok;
    3081             : 
    3082      174670 :         e.key = name;
    3083      174670 :         e.data = NULL;
    3084             : 
    3085      174670 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
    3086             : 
    3087      174670 :         p = hsearch(e, FIND);
    3088      174670 :         if (p == NULL) {
    3089      115191 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
    3090      115191 :                 ok = nwrap_ed_inventarize_add_new(name, ed);
    3091             :         } else {
    3092       59479 :                 struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
    3093             : 
    3094       59479 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
    3095       59479 :                 ok = nwrap_ed_inventarize_add_to_existing(ed, el);
    3096             :         }
    3097             : 
    3098      174670 :         return ok;
    3099             : }
    3100             : 
    3101       55712 : static bool nwrap_add_hname(struct nwrap_entdata *const ed)
    3102             : {
    3103       55712 :         char *const h_name = (char *const)(ed->ht.h_name);
    3104             :         unsigned i;
    3105             :         bool ok;
    3106             : 
    3107       55712 :         ok = nwrap_ed_inventarize(h_name, ed);
    3108       55712 :         if (!ok) {
    3109           0 :                 return false;
    3110             :         }
    3111             : 
    3112       55712 :         if (ed->ht.h_aliases == NULL) {
    3113           0 :                 return true;
    3114             :         }
    3115             : 
    3116             :         /* Itemize aliases */
    3117      118958 :         for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
    3118             :                 char *h_name_alias;
    3119             : 
    3120       63246 :                 h_name_alias = ed->ht.h_aliases[i];
    3121             : 
    3122       63246 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
    3123             : 
    3124       63246 :                 if (!nwrap_ed_inventarize(h_name_alias, ed)) {
    3125           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3126             :                                   "Unable to add alias: %s", h_name_alias);
    3127           0 :                         return false;
    3128             :                 }
    3129             :         }
    3130             : 
    3131       55712 :         return true;
    3132             : }
    3133             : 
    3134       55712 : static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
    3135             : {
    3136       55712 :         struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
    3137       55712 :         bool do_aliases = true;
    3138       55712 :         ssize_t aliases_count = 0;
    3139             :         char *p;
    3140             :         char *i;
    3141             :         char *n;
    3142             : 
    3143             :         char *ip;
    3144             :         bool ok;
    3145             : 
    3146       33304 :         struct nwrap_entdata *ed = (struct nwrap_entdata *)
    3147       22408 :                                    malloc(sizeof(struct nwrap_entdata));
    3148       55712 :         if (ed == NULL) {
    3149           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3150             :                           "Unable to allocate memory for nwrap_entdata");
    3151           0 :                 return false;
    3152             :         }
    3153       55712 :         ZERO_STRUCTP(ed);
    3154             : 
    3155       55712 :         i = line;
    3156             : 
    3157             :         /*
    3158             :          * IP
    3159             :          */
    3160             : 
    3161             :         /* Walk to first char */
    3162       55712 :         for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
    3163           0 :                 if (*p == '\0') {
    3164           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3165             :                                   "Invalid line[%s]: '%s'",
    3166             :                                   line, i);
    3167           0 :                         free(ed);
    3168           0 :                         return false;
    3169             :                 }
    3170             :         }
    3171             : 
    3172     1447728 :         for (i = p; !isspace((int)*p); p++) {
    3173     1392016 :                 if (*p == '\0') {
    3174           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3175             :                                   "Invalid line[%s]: '%s'",
    3176             :                                   line, i);
    3177           0 :                         free(ed);
    3178           0 :                         return false;
    3179             :                 }
    3180             :         }
    3181             : 
    3182       55712 :         *p = '\0';
    3183             : 
    3184       55712 :         if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
    3185       27856 :                 ed->ht.h_addrtype = AF_INET;
    3186       27856 :                 ed->ht.h_length = 4;
    3187             : #ifdef HAVE_IPV6
    3188       27856 :         } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
    3189       27856 :                 ed->ht.h_addrtype = AF_INET6;
    3190       27856 :                 ed->ht.h_length = 16;
    3191             : #endif
    3192             :         } else {
    3193           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3194             :                           "Invalid line[%s]: '%s'",
    3195             :                           line, i);
    3196             : 
    3197           0 :                 free(ed);
    3198           0 :                 return false;
    3199             :         }
    3200       55712 :         ip = i;
    3201             : 
    3202       55712 :         ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
    3203       55712 :                                    (void *const)ed->addr.host_addr);
    3204       55712 :         if (!ok) {
    3205           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
    3206           0 :                 free(ed);
    3207           0 :                 return false;
    3208             :         }
    3209       55712 :         ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
    3210             : 
    3211       55712 :         p++;
    3212             : 
    3213             :         /*
    3214             :          * FQDN
    3215             :          */
    3216             : 
    3217             :         /* Walk to first char */
    3218       55712 :         for (n = p; *p != '_' && !isalnum((int) *p); p++) {
    3219           0 :                 if (*p == '\0') {
    3220           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3221             :                                   "Invalid line[%s]: '%s'",
    3222             :                                   line, n);
    3223             : 
    3224           0 :                         free(ed);
    3225           0 :                         return false;
    3226             :                 }
    3227             :         }
    3228             : 
    3229     1700456 :         for (n = p; !isspace((int)*p); p++) {
    3230     1644744 :                 if (*p == '\0') {
    3231           0 :                         do_aliases = false;
    3232           0 :                         break;
    3233             :                 }
    3234             :         }
    3235             : 
    3236       55712 :         *p = '\0';
    3237             : 
    3238             :         /* Convert to lowercase. This operate on same memory region */
    3239       55712 :         str_tolower(n, n);
    3240       55712 :         ed->ht.h_name = n;
    3241             : 
    3242             :         /* glib's getent always dereferences he->h_aliases */
    3243       55712 :         ed->ht.h_aliases = malloc(sizeof(char *));
    3244       55712 :         if (ed->ht.h_aliases == NULL) {
    3245           0 :                 free(ed);
    3246           0 :                 return false;
    3247             :         }
    3248       55712 :         ed->ht.h_aliases[0] = NULL;
    3249             : 
    3250             :         /*
    3251             :          * Aliases
    3252             :          */
    3253      152262 :         while (do_aliases) {
    3254             :                 char **aliases;
    3255             :                 char *a;
    3256             : 
    3257       63246 :                 p++;
    3258             : 
    3259             :                 /* Walk to first char */
    3260       63246 :                 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
    3261           0 :                         if (*p == '\0') {
    3262           0 :                                 do_aliases = false;
    3263           0 :                                 break;
    3264             :                         }
    3265             :                 }
    3266             :                 /* Only trailing spaces are left */
    3267       63246 :                 if (!do_aliases) {
    3268           0 :                         break;
    3269             :                 }
    3270             : 
    3271      603422 :                 for (a = p; !isspace((int)*p); p++) {
    3272      595888 :                         if (*p == '\0') {
    3273       55712 :                                 do_aliases = false;
    3274       55712 :                                 break;
    3275             :                         }
    3276             :                 }
    3277             : 
    3278       63246 :                 *p = '\0';
    3279             : 
    3280       63246 :                 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
    3281       63246 :                 if (aliases == NULL) {
    3282           0 :                         free(ed);
    3283           0 :                         return false;
    3284             :                 }
    3285       63246 :                 ed->ht.h_aliases = aliases;
    3286             : 
    3287       63246 :                 str_tolower(a, a);
    3288       63246 :                 aliases[aliases_count] = a;
    3289       63246 :                 aliases[aliases_count + 1] = NULL;
    3290             : 
    3291       63246 :                 aliases_count += 1;
    3292             :         }
    3293             : 
    3294       55712 :         ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
    3295       55712 :         if (!ok) {
    3296           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
    3297           0 :                 free(ed);
    3298           0 :                 return false;
    3299             :         }
    3300             : 
    3301       55712 :         ed->aliases_count = aliases_count;
    3302             :         /* Inventarize item */
    3303       55712 :         ok = nwrap_add_hname(ed);
    3304       55712 :         if (!ok) {
    3305           0 :                 return false;
    3306             :         }
    3307             : 
    3308       55712 :         ok = nwrap_ed_inventarize(ip, ed);
    3309       55712 :         if (!ok) {
    3310           0 :                 return false;
    3311             :         }
    3312             : 
    3313       55712 :         nwrap_he->num++;
    3314       55712 :         return true;
    3315             : }
    3316             : 
    3317       46063 : static void nwrap_he_unload(struct nwrap_cache *nwrap)
    3318             : {
    3319       46063 :         struct nwrap_he *nwrap_he =
    3320             :                 (struct nwrap_he *)nwrap->private_data;
    3321             :         struct nwrap_entdata *ed;
    3322             :         struct nwrap_entlist *el;
    3323             :         size_t i;
    3324             :         int rc;
    3325             : 
    3326      186621 :         nwrap_vector_foreach (ed, nwrap_he->entries, i)
    3327             :         {
    3328      140558 :                 SAFE_FREE(ed->nwrap_addrdata.items);
    3329      140558 :                 SAFE_FREE(ed->ht.h_aliases);
    3330      140558 :                 SAFE_FREE(ed);
    3331             :         }
    3332       46063 :         SAFE_FREE(nwrap_he->entries.items);
    3333       46063 :         nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
    3334             : 
    3335      336855 :         nwrap_vector_foreach(el, nwrap_he->lists, i)
    3336             :         {
    3337      907258 :                 while (el != NULL) {
    3338             :                         struct nwrap_entlist *el_next;
    3339             : 
    3340      441026 :                         el_next = el->next;
    3341      441026 :                         SAFE_FREE(el);
    3342      441026 :                         el = el_next;
    3343             :                 }
    3344             :         }
    3345       46063 :         SAFE_FREE(nwrap_he->lists.items);
    3346       46063 :         nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
    3347             : 
    3348       46063 :         nwrap_he->num = 0;
    3349       46063 :         nwrap_he->idx = 0;
    3350             : 
    3351             :         /*
    3352             :          * If we unload the file, the pointers in the hash table point to
    3353             :          * invalid memory. So we need to destroy the hash table and recreate
    3354             :          * it.
    3355             :          */
    3356       46063 :         hdestroy();
    3357       46063 :         rc = hcreate(max_hostents);
    3358       46063 :         if (rc == 0) {
    3359           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
    3360           0 :                 exit(-1);
    3361             :         }
    3362       46063 : }
    3363             : 
    3364             : 
    3365             : /* user functions */
    3366       13579 : static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
    3367             :                                            const char *name)
    3368             : {
    3369             :         int i;
    3370             :         bool ok;
    3371             : 
    3372             :         (void) b; /* unused */
    3373             : 
    3374       13579 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
    3375             : 
    3376       13579 :         ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3377       13579 :         if (!ok) {
    3378           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3379           0 :                 return NULL;
    3380             :         }
    3381             : 
    3382      113786 :         for (i=0; i<nwrap_pw_global.num; i++) {
    3383      102748 :                 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
    3384        2541 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
    3385        2541 :                         return &nwrap_pw_global.list[i];
    3386             :                 }
    3387      100207 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3388             :                           "user[%s] does not match [%s]",
    3389             :                           name,
    3390             :                           nwrap_pw_global.list[i].pw_name);
    3391             :         }
    3392             : 
    3393       11038 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
    3394             : 
    3395       11038 :         errno = ENOENT;
    3396       11038 :         return NULL;
    3397             : }
    3398             : 
    3399         160 : static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
    3400             :                                   const char *name, struct passwd *pwdst,
    3401             :                                   char *buf, size_t buflen, struct passwd **pwdstp)
    3402             : {
    3403             :         struct passwd *pw;
    3404             : 
    3405         160 :         pw = nwrap_files_getpwnam(b, name);
    3406         160 :         if (!pw) {
    3407          52 :                 if (errno == 0) {
    3408           0 :                         return ENOENT;
    3409             :                 }
    3410          52 :                 return errno;
    3411             :         }
    3412             : 
    3413         108 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3414             : }
    3415             : 
    3416       25833 : static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
    3417             :                                            uid_t uid)
    3418             : {
    3419             :         int i;
    3420             :         bool ok;
    3421             : 
    3422             :         (void) b; /* unused */
    3423             : 
    3424       25833 :         ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3425       25833 :         if (!ok) {
    3426           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3427           0 :                 return NULL;
    3428             :         }
    3429             : 
    3430       83764 :         for (i=0; i<nwrap_pw_global.num; i++) {
    3431       80963 :                 if (nwrap_pw_global.list[i].pw_uid == uid) {
    3432       23032 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
    3433       23032 :                         return &nwrap_pw_global.list[i];
    3434             :                 }
    3435       57931 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3436             :                           "uid[%u] does not match [%u]",
    3437             :                           uid,
    3438             :                           nwrap_pw_global.list[i].pw_uid);
    3439             :         }
    3440             : 
    3441        2801 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
    3442             : 
    3443        2801 :         errno = ENOENT;
    3444        2801 :         return NULL;
    3445             : }
    3446             : 
    3447         141 : static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
    3448             :                                   uid_t uid, struct passwd *pwdst,
    3449             :                                   char *buf, size_t buflen, struct passwd **pwdstp)
    3450             : {
    3451             :         struct passwd *pw;
    3452             : 
    3453         141 :         pw = nwrap_files_getpwuid(b, uid);
    3454         141 :         if (!pw) {
    3455          52 :                 if (errno == 0) {
    3456           0 :                         return ENOENT;
    3457             :                 }
    3458          52 :                 return errno;
    3459             :         }
    3460             : 
    3461          89 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3462             : }
    3463             : 
    3464             : /* user enum functions */
    3465          10 : static void nwrap_files_setpwent(struct nwrap_backend *b)
    3466             : {
    3467             :         (void) b; /* unused */
    3468             : 
    3469          10 :         nwrap_pw_global.idx = 0;
    3470          10 : }
    3471             : 
    3472         320 : static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
    3473             : {
    3474             :         struct passwd *pw;
    3475             : 
    3476             :         (void) b; /* unused */
    3477             : 
    3478         320 :         if (nwrap_pw_global.idx == 0) {
    3479             :                 bool ok;
    3480          10 :                 ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3481          10 :                 if (!ok) {
    3482           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3483           0 :                         return NULL;
    3484             :                 }
    3485             :         }
    3486             : 
    3487         320 :         if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
    3488         140 :                 errno = ENOENT;
    3489         140 :                 return NULL;
    3490             :         }
    3491             : 
    3492         180 :         pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
    3493             : 
    3494         180 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3495             :                   "return user[%s] uid[%u]",
    3496             :                   pw->pw_name, pw->pw_uid);
    3497             : 
    3498         180 :         return pw;
    3499             : }
    3500             : 
    3501         128 : static int nwrap_files_getpwent_r(struct nwrap_backend *b,
    3502             :                                   struct passwd *pwdst, char *buf,
    3503             :                                   size_t buflen, struct passwd **pwdstp)
    3504             : {
    3505             :         struct passwd *pw;
    3506             : 
    3507         128 :         pw = nwrap_files_getpwent(b);
    3508         128 :         if (!pw) {
    3509          56 :                 if (errno == 0) {
    3510           0 :                         return ENOENT;
    3511             :                 }
    3512          56 :                 return errno;
    3513             :         }
    3514             : 
    3515          72 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3516             : }
    3517             : 
    3518        3678 : static void nwrap_files_endpwent(struct nwrap_backend *b)
    3519             : {
    3520             :         (void) b; /* unused */
    3521             : 
    3522        3678 :         nwrap_pw_global.idx = 0;
    3523        3678 : }
    3524             : 
    3525             : /* shadow */
    3526             : 
    3527             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    3528             : 
    3529             : #ifdef HAVE_SETSPENT
    3530             : static void nwrap_files_setspent(void)
    3531             : {
    3532             :         nwrap_sp_global.idx = 0;
    3533             : }
    3534             : 
    3535             : static struct spwd *nwrap_files_getspent(void)
    3536             : {
    3537             :         struct spwd *sp;
    3538             : 
    3539             :         if (nwrap_sp_global.idx == 0) {
    3540             :                 bool ok;
    3541             : 
    3542             :                 ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
    3543             :                 if (!ok) {
    3544             :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
    3545             :                         return NULL;
    3546             :                 }
    3547             :         }
    3548             : 
    3549             :         if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
    3550             :                 errno = ENOENT;
    3551             :                 return NULL;
    3552             :         }
    3553             : 
    3554             :         sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
    3555             : 
    3556             :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3557             :                   "return user[%s]",
    3558             :                   sp->sp_namp);
    3559             : 
    3560             :         return sp;
    3561             : }
    3562             : 
    3563             : static void nwrap_files_endspent(void)
    3564             : {
    3565             :         nwrap_sp_global.idx = 0;
    3566             : }
    3567             : #endif /* HAVE_SETSPENT */
    3568             : 
    3569           0 : static struct spwd *nwrap_files_getspnam(const char *name)
    3570             : {
    3571             :         int i;
    3572             :         bool ok;
    3573             : 
    3574           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
    3575             : 
    3576           0 :         ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
    3577           0 :         if (!ok) {
    3578           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
    3579           0 :                 return NULL;
    3580             :         }
    3581             : 
    3582           0 :         for (i=0; i<nwrap_sp_global.num; i++) {
    3583           0 :                 if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
    3584           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
    3585           0 :                         return &nwrap_sp_global.list[i];
    3586             :                 }
    3587           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3588             :                           "user[%s] does not match [%s]",
    3589             :                           name,
    3590             :                           nwrap_sp_global.list[i].sp_namp);
    3591             :         }
    3592             : 
    3593           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
    3594             : 
    3595           0 :         errno = ENOENT;
    3596           0 :         return NULL;
    3597             : }
    3598             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    3599             : 
    3600             : /* misc functions */
    3601           0 : static int nwrap_files_initgroups(struct nwrap_backend *b,
    3602             :                                   const char *user,
    3603             :                                   gid_t group)
    3604             : {
    3605             :         struct group *grp;
    3606             :         gid_t *groups;
    3607           0 :         int size = 1;
    3608             :         int rc;
    3609             : 
    3610           0 :         groups = (gid_t *)malloc(size * sizeof(gid_t));
    3611           0 :         if (groups == NULL) {
    3612           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    3613           0 :                 errno = ENOMEM;
    3614           0 :                 return -1;
    3615             :         }
    3616           0 :         groups[0] = group;
    3617             : 
    3618           0 :         nwrap_files_setgrent(b);
    3619           0 :         while ((grp = nwrap_files_getgrent(b)) != NULL) {
    3620           0 :                 int i = 0;
    3621             : 
    3622           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3623             :                           "Inspecting %s for group membership",
    3624             :                           grp->gr_name);
    3625             : 
    3626           0 :                 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
    3627           0 :                         if (group != grp->gr_gid &&
    3628           0 :                             (strcmp(user, grp->gr_mem[i]) == 0)) {
    3629           0 :                                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3630             :                                           "%s is member of %s",
    3631             :                                           user,
    3632             :                                           grp->gr_name);
    3633             : 
    3634           0 :                                 groups = (gid_t *)realloc(groups,
    3635           0 :                                                           (size + 1) * sizeof(gid_t));
    3636           0 :                                 if (groups == NULL) {
    3637           0 :                                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3638             :                                                   "Out of memory");
    3639           0 :                                         errno = ENOMEM;
    3640           0 :                                         return -1;
    3641             :                                 }
    3642             : 
    3643           0 :                                 groups[size] = grp->gr_gid;
    3644           0 :                                 size++;
    3645             :                         }
    3646             :                 }
    3647             :         }
    3648             : 
    3649           0 :         nwrap_files_endgrent(b);
    3650             : 
    3651           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3652             :                   "%s is member of %d groups",
    3653             :                   user, size);
    3654             : 
    3655             :         /* This really only works if uid_wrapper is loaded */
    3656           0 :         rc = setgroups(size, groups);
    3657             : 
    3658           0 :         free(groups);
    3659             : 
    3660           0 :         return rc;
    3661             : }
    3662             : 
    3663             : /* group functions */
    3664         773 : static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
    3665             :                                           const char *name)
    3666             : {
    3667             :         int i;
    3668             :         bool ok;
    3669             : 
    3670             :         (void) b; /* unused */
    3671             : 
    3672         773 :         ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3673         773 :         if (!ok) {
    3674           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3675           0 :                 return NULL;
    3676             :         }
    3677             : 
    3678        5498 :         for (i=0; i<nwrap_gr_global.num; i++) {
    3679        5108 :                 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
    3680         383 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
    3681         383 :                         return &nwrap_gr_global.list[i];
    3682             :                 }
    3683        4725 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3684             :                           "group[%s] does not match [%s]",
    3685             :                           name,
    3686             :                           nwrap_gr_global.list[i].gr_name);
    3687             :         }
    3688             : 
    3689         390 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
    3690             : 
    3691         390 :         errno = ENOENT;
    3692         390 :         return NULL;
    3693             : }
    3694             : 
    3695         167 : static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
    3696             :                                   const char *name, struct group *grdst,
    3697             :                                   char *buf, size_t buflen, struct group **grdstp)
    3698             : {
    3699             :         struct group *gr;
    3700             : 
    3701         167 :         gr = nwrap_files_getgrnam(b, name);
    3702         167 :         if (!gr) {
    3703         106 :                 if (errno == 0) {
    3704           0 :                         return ENOENT;
    3705             :                 }
    3706         106 :                 return errno;
    3707             :         }
    3708             : 
    3709          61 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3710             : }
    3711             : 
    3712        2158 : static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
    3713             :                                           gid_t gid)
    3714             : {
    3715             :         int i;
    3716             :         bool ok;
    3717             : 
    3718             :         (void) b; /* unused */
    3719             : 
    3720        2158 :         ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3721        2158 :         if (!ok) {
    3722           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3723           0 :                 return NULL;
    3724             :         }
    3725             : 
    3726        7056 :         for (i=0; i<nwrap_gr_global.num; i++) {
    3727        6820 :                 if (nwrap_gr_global.list[i].gr_gid == gid) {
    3728        1922 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
    3729        1922 :                         return &nwrap_gr_global.list[i];
    3730             :                 }
    3731        4898 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3732             :                           "gid[%u] does not match [%u]",
    3733             :                           gid,
    3734             :                           nwrap_gr_global.list[i].gr_gid);
    3735             :         }
    3736             : 
    3737         236 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
    3738             : 
    3739         236 :         errno = ENOENT;
    3740         236 :         return NULL;
    3741             : }
    3742             : 
    3743         116 : static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
    3744             :                                   gid_t gid, struct group *grdst,
    3745             :                                   char *buf, size_t buflen, struct group **grdstp)
    3746             : {
    3747             :         struct group *gr;
    3748             : 
    3749         116 :         gr = nwrap_files_getgrgid(b, gid);
    3750         116 :         if (!gr) {
    3751          72 :                 if (errno == 0) {
    3752           0 :                         return ENOENT;
    3753             :                 }
    3754          72 :                 return errno;
    3755             :         }
    3756             : 
    3757          44 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3758             : }
    3759             : 
    3760             : /* group enum functions */
    3761        3090 : static void nwrap_files_setgrent(struct nwrap_backend *b)
    3762             : {
    3763             :         (void) b; /* unused */
    3764             : 
    3765        3090 :         nwrap_gr_global.idx = 0;
    3766        3090 : }
    3767             : 
    3768       36046 : static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
    3769             : {
    3770             :         struct group *gr;
    3771             : 
    3772             :         (void) b; /* unused */
    3773             : 
    3774       36046 :         if (nwrap_gr_global.idx == 0) {
    3775             :                 bool ok;
    3776             : 
    3777        3090 :                 ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3778        3090 :                 if (!ok) {
    3779           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3780           0 :                         return NULL;
    3781             :                 }
    3782             :         }
    3783             : 
    3784       36046 :         if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
    3785        5646 :                 errno = ENOENT;
    3786        5646 :                 return NULL;
    3787             :         }
    3788             : 
    3789       30400 :         gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
    3790             : 
    3791       30400 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3792             :                   "return group[%s] gid[%u]",
    3793             :                   gr->gr_name, gr->gr_gid);
    3794             : 
    3795       30400 :         return gr;
    3796             : }
    3797             : 
    3798         120 : static int nwrap_files_getgrent_r(struct nwrap_backend *b,
    3799             :                                   struct group *grdst, char *buf,
    3800             :                                   size_t buflen, struct group **grdstp)
    3801             : {
    3802             :         struct group *gr;
    3803             : 
    3804         120 :         gr = nwrap_files_getgrent(b);
    3805         120 :         if (!gr) {
    3806          76 :                 if (errno == 0) {
    3807           0 :                         return ENOENT;
    3808             :                 }
    3809          76 :                 return errno;
    3810             :         }
    3811             : 
    3812          44 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3813             : }
    3814             : 
    3815        3090 : static void nwrap_files_endgrent(struct nwrap_backend *b)
    3816             : {
    3817             :         (void) b; /* unused */
    3818             : 
    3819        3090 :         nwrap_gr_global.idx = 0;
    3820        3090 : }
    3821             : 
    3822             : /* hosts functions */
    3823          36 : static int nwrap_files_internal_gethostbyname(const char *name, int af,
    3824             :                                               struct hostent *result,
    3825             :                                               struct nwrap_vector *addr_list)
    3826             : {
    3827             :         struct nwrap_entlist *el;
    3828             :         struct hostent *he;
    3829             :         char *h_name_lower;
    3830             :         ENTRY e;
    3831             :         ENTRY *e_p;
    3832          36 :         char canon_name[DNS_NAME_MAX] = { 0 };
    3833             :         size_t name_len;
    3834          36 :         bool he_found = false;
    3835             :         bool ok;
    3836             : 
    3837             :         /*
    3838             :          * We need to make sure we have zeroed return pointer for consumers
    3839             :          * which don't check return values, e.g. OpenLDAP.
    3840             :          */
    3841          36 :         ZERO_STRUCTP(result);
    3842             : 
    3843          36 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    3844          36 :         if (!ok) {
    3845           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    3846           0 :                 goto no_ent;
    3847             :         }
    3848             : 
    3849          36 :         name_len = strlen(name);
    3850          36 :         if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
    3851           0 :                 memcpy(canon_name, name, name_len - 1);
    3852           0 :                 canon_name[name_len] = '\0';
    3853           0 :                 name = canon_name;
    3854             :         }
    3855             : 
    3856          36 :         if (!str_tolower_copy(&h_name_lower, name)) {
    3857           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3858             :                           "Out of memory while converting to lower case");
    3859           0 :                 goto no_ent;
    3860             :         }
    3861             : 
    3862             :         /* Look at hash table for element */
    3863          36 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
    3864          36 :         e.key = h_name_lower;
    3865          36 :         e.data = NULL;
    3866          36 :         e_p = hsearch(e, FIND);
    3867          36 :         if (e_p == NULL) {
    3868          27 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
    3869          27 :                 SAFE_FREE(h_name_lower);
    3870          27 :                 goto no_ent;
    3871             :         }
    3872           9 :         SAFE_FREE(h_name_lower);
    3873             : 
    3874             :         /* Always cleanup vector and results */
    3875           9 :         if (!nwrap_vector_is_initialized(addr_list)) {
    3876           9 :                 if (!nwrap_vector_init(addr_list)) {
    3877           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3878             :                                   "Unable to initialize memory for addr_list vector");
    3879           0 :                         goto no_ent;
    3880             :                 }
    3881             :         } else {
    3882             :                 /* When vector is initialized data are valid no more.
    3883             :                  * Quick way how to free vector is: */
    3884           0 :                 addr_list->count = 0;
    3885             :         }
    3886             : 
    3887             :         /* Iterate through results */
    3888          27 :         for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
    3889             :         {
    3890          18 :                 he = &(el->ed->ht);
    3891             : 
    3892             :                 /* Filter by address familiy if provided */
    3893          18 :                 if (af != AF_UNSPEC && he->h_addrtype != af) {
    3894           0 :                         continue;
    3895             :                 }
    3896             : 
    3897             :                 /*
    3898             :                  * GLIBC HACK?
    3899             :                  * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
    3900             :                  */
    3901          18 :                 if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
    3902           9 :                         continue;
    3903             :                 }
    3904             : 
    3905           9 :                 if (!he_found) {
    3906           9 :                         memcpy(result, he, sizeof(struct hostent));
    3907           9 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3908             :                                   "Name found. Returning record for %s",
    3909             :                                   he->h_name);
    3910           9 :                         he_found = true;
    3911             :                 }
    3912           9 :                 nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
    3913           9 :                 result->h_addr_list = nwrap_vector_head(addr_list);
    3914             :         }
    3915             : 
    3916           9 :         if (he_found) {
    3917           9 :                 return 0;
    3918             :         }
    3919           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3920             :                   "Name found in database. No records matches type.");
    3921             : 
    3922          27 : no_ent:
    3923          27 :         errno = ENOENT;
    3924          27 :         return -1;
    3925             : }
    3926             : 
    3927          36 : static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
    3928             :                                         const char *name, int af,
    3929             :                                         struct hostent *hedst,
    3930             :                                         char *buf, size_t buflen,
    3931             :                                         struct hostent **hedstp)
    3932             : {
    3933          36 :         struct nwrap_vector *addr_list = NULL;
    3934             :         union {
    3935             :                 char *ptr;
    3936             :                 char **list;
    3937             :         } g;
    3938             :         int rc;
    3939             : 
    3940             :         (void) b; /* unused */
    3941             :         (void) af; /* unused */
    3942             : 
    3943          36 :         if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) {
    3944           0 :                 errno = EINVAL;
    3945           0 :                 return -1;
    3946             :         }
    3947          36 :         *hedstp = NULL;
    3948          36 :         buf[0] = '\0';
    3949             : 
    3950          36 :         addr_list = calloc(1, sizeof(struct nwrap_vector));
    3951          36 :         if (addr_list == NULL) {
    3952           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3953             :                           "Unable to allocate memory for address list");
    3954           0 :                 errno = ENOENT;
    3955           0 :                 return -1;
    3956             :         }
    3957             : 
    3958          36 :         rc = nwrap_files_internal_gethostbyname(name, af, hedst,
    3959             :                                                 addr_list);
    3960          36 :         if (rc == -1) {
    3961          27 :                 SAFE_FREE(addr_list->items);
    3962          27 :                 SAFE_FREE(addr_list);
    3963          27 :                 errno = ENOENT;
    3964          27 :                 return -1;
    3965             :         }
    3966             : 
    3967             :         /* +1 i for ending NULL pointer */
    3968           9 :         if (buflen < ((addr_list->count + 1) * sizeof(void *))) {
    3969           0 :                 SAFE_FREE(addr_list->items);
    3970           0 :                 SAFE_FREE(addr_list);
    3971           0 :                 return ERANGE;
    3972             :         }
    3973             : 
    3974             :         /* Copy all to user provided buffer and change
    3975             :          * pointers in returned structure.
    3976             :          * +1 is for ending NULL pointer. */
    3977           9 :         memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
    3978             : 
    3979           9 :         SAFE_FREE(addr_list->items);
    3980           9 :         SAFE_FREE(addr_list);
    3981             : 
    3982           9 :         g.ptr = buf;
    3983           9 :         hedst->h_addr_list = g.list;
    3984           9 :         *hedstp = hedst;
    3985           9 :         return 0;
    3986             : }
    3987             : 
    3988             : #ifdef HAVE_GETHOSTBYNAME_R
    3989          36 : static int nwrap_gethostbyname_r(const char *name,
    3990             :                                  struct hostent *ret,
    3991             :                                  char *buf, size_t buflen,
    3992             :                                  struct hostent **result, int *h_errnop)
    3993             : {
    3994             :         int rc;
    3995             :         size_t i;
    3996             : 
    3997          80 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    3998          53 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    3999          53 :                 rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret,
    4000             :                                                  buf, buflen, result);
    4001          53 :                 if (rc == 0) {
    4002           9 :                         return 0;
    4003          44 :                 } else if (rc == ERANGE) {
    4004           0 :                         return ERANGE;
    4005             :                 }
    4006             :         }
    4007          27 :         *h_errnop = h_errno;
    4008          27 :         return ENOENT;
    4009             : }
    4010             : 
    4011             : int gethostbyname_r(const char *name,
    4012             :                     struct hostent *ret,
    4013             :                     char *buf, size_t buflen,
    4014             :                     struct hostent **result, int *h_errnop)
    4015             : {
    4016          39 :         if (!nss_wrapper_hosts_enabled()) {
    4017           3 :                 return libc_gethostbyname_r(name,
    4018             :                                             ret,
    4019             :                                             buf,
    4020             :                                             buflen,
    4021             :                                             result,
    4022             :                                             h_errnop);
    4023             :         }
    4024             : 
    4025          36 :         return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
    4026             : }
    4027             : #endif
    4028             : 
    4029             : #ifdef HAVE_GETHOSTBYNAME2_R
    4030           0 : static int nwrap_gethostbyname2_r(const char *name, int af,
    4031             :                                  struct hostent *ret,
    4032             :                                  char *buf, size_t buflen,
    4033             :                                  struct hostent **result, int *h_errnop)
    4034             : {
    4035             :         int rc;
    4036             :         size_t i;
    4037             : 
    4038           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4039           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4040           0 :                 rc = b->ops->nw_gethostbyname2_r(b, name, af, ret,
    4041             :                                                  buf, buflen, result);
    4042           0 :                 if (rc == 0) {
    4043           0 :                         return 0;
    4044           0 :                 } else if (rc == ERANGE) {
    4045           0 :                         return ERANGE;
    4046             :                 }
    4047             :         }
    4048           0 :         *h_errnop = h_errno;
    4049           0 :         return ENOENT;
    4050             : }
    4051             : 
    4052             : int gethostbyname2_r(const char *name, int af,
    4053             :                      struct hostent *ret,
    4054             :                      char *buf, size_t buflen,
    4055             :                      struct hostent **result, int *h_errnop)
    4056             : {
    4057           0 :         if (!nss_wrapper_hosts_enabled()) {
    4058           0 :                 return libc_gethostbyname2_r(name, af, ret, buf, buflen,
    4059             :                                              result, h_errnop);
    4060             :         }
    4061             : 
    4062           0 :         return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result,
    4063             :                                       h_errnop);
    4064             : }
    4065             : #endif
    4066             : 
    4067      625953 : static int nwrap_files_getaddrinfo(const char *name,
    4068             :                                    unsigned short port,
    4069             :                                    const struct addrinfo *hints,
    4070             :                                    struct addrinfo **ai)
    4071             : {
    4072             :         struct nwrap_entlist *el;
    4073             :         struct hostent *he;
    4074      625953 :         struct addrinfo *ai_head = NULL;
    4075      625953 :         struct addrinfo *ai_cur = NULL;
    4076             :         char *h_name_lower;
    4077             :         size_t name_len;
    4078      625953 :         char canon_name[DNS_NAME_MAX] = { 0 };
    4079      625953 :         bool skip_canonname = false;
    4080      625953 :         ENTRY e = {
    4081             :                 .key = NULL,
    4082             :         };
    4083      625953 :         ENTRY *e_p = NULL;
    4084             :         int rc;
    4085             :         bool ok;
    4086             : 
    4087      625953 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4088      625953 :         if (!ok) {
    4089           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    4090           0 :                 return EAI_SYSTEM;
    4091             :         }
    4092             : 
    4093      625953 :         name_len = strlen(name);
    4094      625953 :         if (name_len == 0) {
    4095           0 :                 return EAI_NONAME;
    4096             :         }
    4097             : 
    4098      625953 :         if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
    4099          37 :                 memcpy(canon_name, name, name_len - 1);
    4100          37 :                 canon_name[name_len] = '\0';
    4101          37 :                 name = canon_name;
    4102             :         }
    4103             : 
    4104      625953 :         if (!str_tolower_copy(&h_name_lower, name)) {
    4105           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    4106             :                           "Out of memory while converting to lower case");
    4107           0 :                 return EAI_MEMORY;
    4108             :         }
    4109             : 
    4110      625953 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
    4111      625953 :         e.key = h_name_lower;
    4112      625953 :         e.data = NULL;
    4113      625953 :         e_p = hsearch(e, FIND);
    4114      625953 :         if (e_p == NULL) {
    4115      451869 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
    4116      451869 :                 SAFE_FREE(h_name_lower);
    4117      451869 :                 errno = ENOENT;
    4118      451869 :                 return EAI_NONAME;
    4119             :         }
    4120      174084 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
    4121      174084 :         SAFE_FREE(h_name_lower);
    4122             : 
    4123      174084 :         rc = EAI_NONAME;
    4124      355307 :         for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
    4125             :         {
    4126             :                 int rc2;
    4127      181223 :                 struct addrinfo *ai_new = NULL;
    4128             : 
    4129      181223 :                 he = &(el->ed->ht);
    4130             : 
    4131      181905 :                 if (hints->ai_family != AF_UNSPEC &&
    4132         682 :                     he->h_addrtype != hints->ai_family)
    4133             :                 {
    4134           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    4135             :                                   "Entry found but with wrong AF - "
    4136             :                                   "remembering EAI_ADDRINFO.");
    4137           0 :                         rc = EAI_ADDRFAMILY;
    4138           0 :                         continue;
    4139             :                 }
    4140             : 
    4141             :                 /* Function allocates memory and returns it in ai. */
    4142      181223 :                 rc2 = nwrap_convert_he_ai(he,
    4143             :                                          port,
    4144             :                                          hints,
    4145             :                                          &ai_new,
    4146             :                                          skip_canonname);
    4147      181223 :                 if (rc2 != 0) {
    4148           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
    4149           0 :                         if (ai_head != NULL) {
    4150           0 :                                 freeaddrinfo(ai_head);
    4151             :                         }
    4152           0 :                         return rc2;
    4153             :                 }
    4154      181223 :                 skip_canonname = true;
    4155             : 
    4156      181223 :                 if (ai_head == NULL) {
    4157      174084 :                         ai_head = ai_new;
    4158             :                 }
    4159      181223 :                 if (ai_cur != NULL) {
    4160        7139 :                         ai_cur->ai_next = ai_new;
    4161             :                 }
    4162      181223 :                 ai_cur = ai_new;
    4163             :         }
    4164             : 
    4165      174084 :         if (ai_head != NULL) {
    4166      174084 :                 rc = 0;
    4167             :         }
    4168             : 
    4169      174084 :         *ai = ai_head;
    4170             : 
    4171      174084 :         return rc;
    4172             : }
    4173             : 
    4174          97 : static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
    4175             :                                                  const void *addr,
    4176             :                                                  socklen_t len, int type)
    4177             : {
    4178             :         struct hostent *he;
    4179          97 :         char ip[NWRAP_INET_ADDRSTRLEN] = {0};
    4180             :         struct nwrap_entdata *ed;
    4181             :         const char *a;
    4182             :         size_t i;
    4183             :         bool ok;
    4184             : 
    4185             :         (void) b; /* unused */
    4186             :         (void) len; /* unused */
    4187             : 
    4188          97 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4189          97 :         if (!ok) {
    4190           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    4191           0 :                 return NULL;
    4192             :         }
    4193             : 
    4194          97 :         a = inet_ntop(type, addr, ip, sizeof(ip));
    4195          97 :         if (a == NULL) {
    4196           0 :                 errno = EINVAL;
    4197           0 :                 return NULL;
    4198             :         }
    4199             : 
    4200         391 :         nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
    4201             :         {
    4202         391 :                 he = &(ed->ht);
    4203         391 :                 if (he->h_addrtype != type) {
    4204         147 :                         continue;
    4205             :                 }
    4206             : 
    4207         244 :                 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
    4208          97 :                         return he;
    4209             :                 }
    4210             :         }
    4211             : 
    4212           0 :         errno = ENOENT;
    4213           0 :         return NULL;
    4214             : }
    4215             : 
    4216             : #ifdef HAVE_GETHOSTBYADDR_R
    4217           0 : static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
    4218             :                                  struct hostent *ret,
    4219             :                                  char *buf, size_t buflen,
    4220             :                                  struct hostent **result, int *h_errnop)
    4221             : {
    4222             :         size_t i;
    4223           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4224           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4225           0 :                 *result = b->ops->nw_gethostbyaddr(b, addr, len, type);
    4226           0 :                 if (*result != NULL) {
    4227           0 :                         break;
    4228             :                 }
    4229             :         }
    4230             : 
    4231           0 :         if (*result != NULL) {
    4232           0 :                 memset(buf, '\0', buflen);
    4233           0 :                 *ret = **result;
    4234           0 :                 return 0;
    4235             :         }
    4236             : 
    4237           0 :         *h_errnop = h_errno;
    4238           0 :         return -1;
    4239             : }
    4240             : 
    4241             : int gethostbyaddr_r(const void *addr, socklen_t len, int type,
    4242             :                     struct hostent *ret,
    4243             :                     char *buf, size_t buflen,
    4244             :                     struct hostent **result, int *h_errnop)
    4245             : {
    4246           0 :         if (!nss_wrapper_hosts_enabled()) {
    4247           0 :                 return libc_gethostbyaddr_r(addr,
    4248             :                                             len,
    4249             :                                             type,
    4250             :                                             ret,
    4251             :                                             buf,
    4252             :                                             buflen,
    4253             :                                             result,
    4254             :                                             h_errnop);
    4255             :         }
    4256             : 
    4257           0 :         return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
    4258             : }
    4259             : #endif
    4260             : 
    4261             : /* hosts enum functions */
    4262           0 : static void nwrap_files_sethostent(void)
    4263             : {
    4264           0 :         nwrap_he_global.idx = 0;
    4265           0 : }
    4266             : 
    4267           0 : static struct hostent *nwrap_files_gethostent(void)
    4268             : {
    4269             :         struct hostent *he;
    4270             : 
    4271           0 :         if (nwrap_he_global.idx == 0) {
    4272             :                 bool ok;
    4273             : 
    4274           0 :                 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4275           0 :                 if (!ok) {
    4276           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
    4277           0 :                         return NULL;
    4278             :                 }
    4279             :         }
    4280             : 
    4281           0 :         if (nwrap_he_global.idx >= nwrap_he_global.num) {
    4282           0 :                 errno = ENOENT;
    4283           0 :                 return NULL;
    4284             :         }
    4285             : 
    4286           0 :         he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
    4287             : 
    4288           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
    4289             : 
    4290           0 :         return he;
    4291             : }
    4292             : 
    4293           0 : static void nwrap_files_endhostent(void)
    4294             : {
    4295           0 :         nwrap_he_global.idx = 0;
    4296           0 : }
    4297             : 
    4298             : /*
    4299             :  * module backend
    4300             :  */
    4301             : 
    4302             : 
    4303        6002 : static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
    4304             :                                             const char *name)
    4305             : {
    4306             :         static struct passwd pwd;
    4307             :         static char buf[1000];
    4308             :         NSS_STATUS status;
    4309             : 
    4310        6002 :         if (b->symbols->_nss_getpwnam_r.f == NULL) {
    4311           0 :                 return NULL;
    4312             :         }
    4313             : 
    4314        6002 :         status = b->symbols->_nss_getpwnam_r.f(name,
    4315             :                                                &pwd,
    4316             :                                                buf,
    4317             :                                                sizeof(buf),
    4318             :                                                &errno);
    4319        6002 :         if (status == NSS_STATUS_NOTFOUND) {
    4320         917 :                 return NULL;
    4321             :         }
    4322        5085 :         if (status != NSS_STATUS_SUCCESS) {
    4323           2 :                 return NULL;
    4324             :         }
    4325             : 
    4326        5083 :         return &pwd;
    4327             : }
    4328             : 
    4329          52 : static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
    4330             :                                    const char *name, struct passwd *pwdst,
    4331             :                                    char *buf, size_t buflen, struct passwd **pwdstp)
    4332             : {
    4333             :         int ret;
    4334             : 
    4335          52 :         *pwdstp = NULL;
    4336             : 
    4337          52 :         if (b->symbols->_nss_getpwnam_r.f == NULL) {
    4338           0 :                 return NSS_STATUS_NOTFOUND;
    4339             :         }
    4340             : 
    4341          52 :         ret = b->symbols->_nss_getpwnam_r.f(name, pwdst, buf, buflen, &errno);
    4342          52 :         switch (ret) {
    4343          52 :         case NSS_STATUS_SUCCESS:
    4344          52 :                 *pwdstp = pwdst;
    4345          52 :                 return 0;
    4346           0 :         case NSS_STATUS_NOTFOUND:
    4347           0 :                 if (errno != 0) {
    4348           0 :                         return errno;
    4349             :                 }
    4350           0 :                 return ENOENT;
    4351           0 :         case NSS_STATUS_TRYAGAIN:
    4352           0 :                 if (errno != 0) {
    4353           0 :                         return errno;
    4354             :                 }
    4355           0 :                 return ERANGE;
    4356           0 :         default:
    4357           0 :                 if (errno != 0) {
    4358           0 :                         return errno;
    4359             :                 }
    4360           0 :                 return ret;
    4361             :         }
    4362             : }
    4363             : 
    4364        2547 : static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
    4365             :                                             uid_t uid)
    4366             : {
    4367             :         static struct passwd pwd;
    4368             :         static char buf[1000];
    4369             :         NSS_STATUS status;
    4370             : 
    4371        2547 :         if (b->symbols->_nss_getpwuid_r.f == NULL) {
    4372           0 :                 return NULL;
    4373             :         }
    4374             : 
    4375        2547 :         status = b->symbols->_nss_getpwuid_r.f(uid,
    4376             :                                                &pwd,
    4377             :                                                buf,
    4378             :                                                sizeof(buf),
    4379             :                                                &errno);
    4380        2547 :         if (status == NSS_STATUS_NOTFOUND) {
    4381        1673 :                 return NULL;
    4382             :         }
    4383         874 :         if (status != NSS_STATUS_SUCCESS) {
    4384          11 :                 return NULL;
    4385             :         }
    4386         863 :         return &pwd;
    4387             : }
    4388             : 
    4389          52 : static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
    4390             :                                    uid_t uid, struct passwd *pwdst,
    4391             :                                    char *buf, size_t buflen, struct passwd **pwdstp)
    4392             : {
    4393             :         int ret;
    4394             : 
    4395          52 :         *pwdstp = NULL;
    4396             : 
    4397          52 :         if (b->symbols->_nss_getpwuid_r.f == NULL) {
    4398           0 :                 return ENOENT;
    4399             :         }
    4400             : 
    4401          52 :         ret = b->symbols->_nss_getpwuid_r.f(uid, pwdst, buf, buflen, &errno);
    4402          52 :         switch (ret) {
    4403          52 :         case NSS_STATUS_SUCCESS:
    4404          52 :                 *pwdstp = pwdst;
    4405          52 :                 return 0;
    4406           0 :         case NSS_STATUS_NOTFOUND:
    4407           0 :                 if (errno != 0) {
    4408           0 :                         return errno;
    4409             :                 }
    4410           0 :                 return ENOENT;
    4411           0 :         case NSS_STATUS_TRYAGAIN:
    4412           0 :                 if (errno != 0) {
    4413           0 :                         return errno;
    4414             :                 }
    4415           0 :                 return ERANGE;
    4416           0 :         default:
    4417           0 :                 if (errno != 0) {
    4418           0 :                         return errno;
    4419             :                 }
    4420           0 :                 return ret;
    4421             :         }
    4422             : }
    4423             : 
    4424          10 : static void nwrap_module_setpwent(struct nwrap_backend *b)
    4425             : {
    4426          10 :         if (b->symbols->_nss_setpwent.f == NULL) {
    4427           0 :                 return;
    4428             :         }
    4429             : 
    4430          10 :         b->symbols->_nss_setpwent.f();
    4431             : }
    4432             : 
    4433          84 : static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
    4434             : {
    4435             :         static struct passwd pwd;
    4436             :         static char buf[1000];
    4437             :         NSS_STATUS status;
    4438             : 
    4439          84 :         if (b->symbols->_nss_getpwent_r.f == NULL) {
    4440           0 :                 return NULL;
    4441             :         }
    4442             : 
    4443          84 :         status = b->symbols->_nss_getpwent_r.f(&pwd, buf, sizeof(buf), &errno);
    4444          84 :         if (status == NSS_STATUS_NOTFOUND) {
    4445           6 :                 return NULL;
    4446             :         }
    4447          78 :         if (status != NSS_STATUS_SUCCESS) {
    4448           0 :                 return NULL;
    4449             :         }
    4450          78 :         return &pwd;
    4451             : }
    4452             : 
    4453          56 : static int nwrap_module_getpwent_r(struct nwrap_backend *b,
    4454             :                                    struct passwd *pwdst, char *buf,
    4455             :                                    size_t buflen, struct passwd **pwdstp)
    4456             : {
    4457             :         int ret;
    4458             : 
    4459          56 :         *pwdstp = NULL;
    4460             : 
    4461          56 :         if (b->symbols->_nss_getpwent_r.f == NULL) {
    4462           0 :                 return ENOENT;
    4463             :         }
    4464             : 
    4465          56 :         ret = b->symbols->_nss_getpwent_r.f(pwdst, buf, buflen, &errno);
    4466          56 :         switch (ret) {
    4467          52 :         case NSS_STATUS_SUCCESS:
    4468          52 :                 *pwdstp = pwdst;
    4469          52 :                 return 0;
    4470           4 :         case NSS_STATUS_NOTFOUND:
    4471           4 :                 if (errno != 0) {
    4472           4 :                         return errno;
    4473             :                 }
    4474           0 :                 return ENOENT;
    4475           0 :         case NSS_STATUS_TRYAGAIN:
    4476           0 :                 if (errno != 0) {
    4477           0 :                         return errno;
    4478             :                 }
    4479           0 :                 return ERANGE;
    4480           0 :         default:
    4481           0 :                 if (errno != 0) {
    4482           0 :                         return errno;
    4483             :                 }
    4484           0 :                 return ret;
    4485             :         }
    4486             : }
    4487             : 
    4488        3672 : static void nwrap_module_endpwent(struct nwrap_backend *b)
    4489             : {
    4490        3672 :         if (b->symbols->_nss_endpwent.f == NULL) {
    4491           0 :                 return;
    4492             :         }
    4493             : 
    4494        3672 :         b->symbols->_nss_endpwent.f();
    4495             : }
    4496             : 
    4497           0 : static int nwrap_module_initgroups(struct nwrap_backend *b,
    4498             :                                    const char *user, gid_t group)
    4499             : {
    4500             :         gid_t *groups;
    4501             :         long int start;
    4502             :         long int size;
    4503             : 
    4504           0 :         if (b->symbols->_nss_initgroups.f == NULL) {
    4505           0 :                 return NSS_STATUS_UNAVAIL;
    4506             :         }
    4507             : 
    4508           0 :         return b->symbols->_nss_initgroups.f(user,
    4509             :                                              group,
    4510             :                                              &start,
    4511             :                                              &size,
    4512             :                                              &groups,
    4513             :                                              0,
    4514             :                                              &errno);
    4515             : }
    4516             : 
    4517         226 : static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
    4518             :                                            const char *name)
    4519             : {
    4520             :         static struct group grp;
    4521             :         static char *buf;
    4522             :         static int buflen = 1000;
    4523             :         NSS_STATUS status;
    4524             : 
    4525         226 :         if (b->symbols->_nss_getgrnam_r.f == NULL) {
    4526           0 :                 return NULL;
    4527             :         }
    4528             : 
    4529         226 :         if (!buf) {
    4530         156 :                 buf = (char *)malloc(buflen);
    4531             :         }
    4532         261 : again:
    4533         226 :         status = b->symbols->_nss_getgrnam_r.f(name, &grp, buf, buflen, &errno);
    4534         226 :         if (status == NSS_STATUS_TRYAGAIN) {
    4535           0 :                 buflen *= 2;
    4536           0 :                 buf = (char *)realloc(buf, buflen);
    4537           0 :                 if (!buf) {
    4538           0 :                         return NULL;
    4539             :                 }
    4540           0 :                 goto again;
    4541             :         }
    4542         226 :         if (status == NSS_STATUS_NOTFOUND) {
    4543         146 :                 SAFE_FREE(buf);
    4544         146 :                 return NULL;
    4545             :         }
    4546          80 :         if (status != NSS_STATUS_SUCCESS) {
    4547           0 :                 SAFE_FREE(buf);
    4548           0 :                 return NULL;
    4549             :         }
    4550          80 :         return &grp;
    4551             : }
    4552             : 
    4553          76 : static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
    4554             :                                    const char *name, struct group *grdst,
    4555             :                                    char *buf, size_t buflen, struct group **grdstp)
    4556             : {
    4557             :         int ret;
    4558             : 
    4559          76 :         *grdstp = NULL;
    4560             : 
    4561          76 :         if (b->symbols->_nss_getgrnam_r.f == NULL) {
    4562           0 :                 return ENOENT;
    4563             :         }
    4564             : 
    4565          76 :         ret = b->symbols->_nss_getgrnam_r.f(name, grdst, buf, buflen, &errno);
    4566          76 :         switch (ret) {
    4567          72 :         case NSS_STATUS_SUCCESS:
    4568          72 :                 *grdstp = grdst;
    4569          72 :                 return 0;
    4570           4 :         case NSS_STATUS_NOTFOUND:
    4571           4 :                 if (errno != 0) {
    4572           4 :                         return errno;
    4573             :                 }
    4574           0 :                 return ENOENT;
    4575           0 :         case NSS_STATUS_TRYAGAIN:
    4576           0 :                 if (errno != 0) {
    4577           0 :                         return errno;
    4578             :                 }
    4579           0 :                 return ERANGE;
    4580           0 :         default:
    4581           0 :                 if (errno != 0) {
    4582           0 :                         return errno;
    4583             :                 }
    4584           0 :                 return ret;
    4585             :         }
    4586             : }
    4587             : 
    4588         164 : static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
    4589             :                                            gid_t gid)
    4590             : {
    4591             :         static struct group grp;
    4592             :         static char *buf;
    4593             :         static int buflen = 1000;
    4594             :         NSS_STATUS status;
    4595             : 
    4596         164 :         if (b->symbols->_nss_getgrgid_r.f == NULL) {
    4597           0 :                 return NULL;
    4598             :         }
    4599             : 
    4600         164 :         if (!buf) {
    4601          32 :                 buf = (char *)malloc(buflen);
    4602             :         }
    4603             : 
    4604         230 : again:
    4605         164 :         status = b->symbols->_nss_getgrgid_r.f(gid, &grp, buf, buflen, &errno);
    4606         164 :         if (status == NSS_STATUS_TRYAGAIN) {
    4607           0 :                 buflen *= 2;
    4608           0 :                 buf = (char *)realloc(buf, buflen);
    4609           0 :                 if (!buf) {
    4610           0 :                         return NULL;
    4611             :                 }
    4612           0 :                 goto again;
    4613             :         }
    4614         164 :         if (status == NSS_STATUS_NOTFOUND) {
    4615           4 :                 SAFE_FREE(buf);
    4616           4 :                 return NULL;
    4617             :         }
    4618         160 :         if (status != NSS_STATUS_SUCCESS) {
    4619           0 :                 SAFE_FREE(buf);
    4620           0 :                 return NULL;
    4621             :         }
    4622         160 :         return &grp;
    4623             : }
    4624             : 
    4625          72 : static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
    4626             :                                    gid_t gid, struct group *grdst,
    4627             :                                    char *buf, size_t buflen, struct group **grdstp)
    4628             : {
    4629             :         int ret;
    4630             : 
    4631          72 :         *grdstp = NULL;
    4632             : 
    4633          72 :         if (b->symbols->_nss_getgrgid_r.f == NULL) {
    4634           0 :                 return ENOENT;
    4635             :         }
    4636             : 
    4637          72 :         ret = b->symbols->_nss_getgrgid_r.f(gid, grdst, buf, buflen, &errno);
    4638          72 :         switch (ret) {
    4639          72 :         case NSS_STATUS_SUCCESS:
    4640          72 :                 *grdstp = grdst;
    4641          72 :                 return 0;
    4642           0 :         case NSS_STATUS_NOTFOUND:
    4643           0 :                 if (errno != 0) {
    4644           0 :                         return errno;
    4645             :                 }
    4646           0 :                 return ENOENT;
    4647           0 :         case NSS_STATUS_TRYAGAIN:
    4648           0 :                 if (errno != 0) {
    4649           0 :                         return errno;
    4650             :                 }
    4651           0 :                 return ERANGE;
    4652           0 :         default:
    4653           0 :                 if (errno != 0) {
    4654           0 :                         return errno;
    4655             :                 }
    4656           0 :                 return ret;
    4657             :         }
    4658             : }
    4659             : 
    4660        3006 : static void nwrap_module_setgrent(struct nwrap_backend *b)
    4661             : {
    4662        3006 :         if (b->symbols->_nss_setgrent.f == NULL) {
    4663           0 :                 return;
    4664             :         }
    4665             : 
    4666        3006 :         b->symbols->_nss_setgrent.f();
    4667             : }
    4668             : 
    4669        5486 : static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
    4670             : {
    4671             :         static struct group grp;
    4672             :         static char *buf;
    4673             :         static int buflen = 1024;
    4674             :         NSS_STATUS status;
    4675             : 
    4676        5486 :         if (b->symbols->_nss_getgrent_r.f == NULL) {
    4677           0 :                 return NULL;
    4678             :         }
    4679             : 
    4680        5486 :         if (!buf) {
    4681        3002 :                 buf = (char *)malloc(buflen);
    4682             :         }
    4683             : 
    4684        6728 : again:
    4685        5486 :         status = b->symbols->_nss_getgrent_r.f(&grp, buf, buflen, &errno);
    4686        5486 :         if (status == NSS_STATUS_TRYAGAIN) {
    4687           0 :                 buflen *= 2;
    4688           0 :                 buf = (char *)realloc(buf, buflen);
    4689           0 :                 if (!buf) {
    4690           0 :                         return NULL;
    4691             :                 }
    4692           0 :                 goto again;
    4693             :         }
    4694        5486 :         if (status == NSS_STATUS_NOTFOUND) {
    4695        3002 :                 SAFE_FREE(buf);
    4696        3002 :                 return NULL;
    4697             :         }
    4698        2484 :         if (status != NSS_STATUS_SUCCESS) {
    4699           0 :                 SAFE_FREE(buf);
    4700           0 :                 return NULL;
    4701             :         }
    4702        2484 :         return &grp;
    4703             : }
    4704             : 
    4705          76 : static int nwrap_module_getgrent_r(struct nwrap_backend *b,
    4706             :                                    struct group *grdst, char *buf,
    4707             :                                    size_t buflen, struct group **grdstp)
    4708             : {
    4709             :         int ret;
    4710             : 
    4711          76 :         *grdstp = NULL;
    4712             : 
    4713          76 :         if (b->symbols->_nss_getgrent_r.f == NULL) {
    4714           0 :                 return ENOENT;
    4715             :         }
    4716             : 
    4717          76 :         ret = b->symbols->_nss_getgrent_r.f(grdst, buf, buflen, &errno);
    4718          76 :         switch (ret) {
    4719          72 :         case NSS_STATUS_SUCCESS:
    4720          72 :                 *grdstp = grdst;
    4721          72 :                 return 0;
    4722           4 :         case NSS_STATUS_NOTFOUND:
    4723           4 :                 if (errno != 0) {
    4724           4 :                         return errno;
    4725             :                 }
    4726           0 :                 return ENOENT;
    4727           0 :         case NSS_STATUS_TRYAGAIN:
    4728           0 :                 if (errno != 0) {
    4729           0 :                         return errno;
    4730             :                 }
    4731           0 :                 return ERANGE;
    4732           0 :         default:
    4733           0 :                 if (errno != 0) {
    4734           0 :                         return errno;
    4735             :                 }
    4736           0 :                 return ret;
    4737             :         }
    4738             : }
    4739             : 
    4740        3006 : static void nwrap_module_endgrent(struct nwrap_backend *b)
    4741             : {
    4742        3006 :         if (b->symbols->_nss_endgrent.f == NULL) {
    4743           0 :                 return;
    4744             :         }
    4745             : 
    4746        3006 :         b->symbols->_nss_endgrent.f();
    4747             : }
    4748             : 
    4749           0 : static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
    4750             :                                                   const void *addr,
    4751             :                                                   socklen_t len, int type)
    4752             : {
    4753             :         static struct hostent he;
    4754             :         static char *buf = NULL;
    4755             :         static size_t buflen = 1000;
    4756             :         NSS_STATUS status;
    4757             : 
    4758           0 :         if (b->symbols->_nss_gethostbyaddr_r.f == NULL) {
    4759           0 :                 return NULL;
    4760             :         }
    4761             : 
    4762           0 :         if (buf == NULL) {
    4763           0 :                 buf = (char *)malloc(buflen);
    4764           0 :                 if (buf == NULL) {
    4765           0 :                         return NULL;
    4766             :                 }
    4767             :         }
    4768           0 : again:
    4769           0 :         status = b->symbols->_nss_gethostbyaddr_r.f(addr,
    4770             :                                                     len,
    4771             :                                                     type,
    4772             :                                                     &he,
    4773             :                                                     buf,
    4774             :                                                     buflen,
    4775             :                                                     &errno,
    4776             :                                                     &h_errno);
    4777           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4778           0 :                 char *p = NULL;
    4779             : 
    4780           0 :                 buflen *= 2;
    4781           0 :                 p = (char *)realloc(buf, buflen);
    4782           0 :                 if (p == NULL) {
    4783           0 :                         SAFE_FREE(buf);
    4784           0 :                         return NULL;
    4785             :                 }
    4786           0 :                 buf = p;
    4787           0 :                 goto again;
    4788             :         }
    4789           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4790           0 :                 SAFE_FREE(buf);
    4791           0 :                 return NULL;
    4792             :         }
    4793           0 :         if (status != NSS_STATUS_SUCCESS) {
    4794           0 :                 SAFE_FREE(buf);
    4795           0 :                 return NULL;
    4796             :         }
    4797             : 
    4798           0 :         return &he;
    4799             : }
    4800             : 
    4801          17 : static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
    4802             :                                          const char *name, int af,
    4803             :                                          struct hostent *hedst,
    4804             :                                          char *buf, size_t buflen,
    4805             :                                          struct hostent **hedstp)
    4806             : {
    4807             :         NSS_STATUS status;
    4808             : 
    4809          17 :         *hedstp = NULL;
    4810             : 
    4811          17 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4812          17 :                 return ENOENT;
    4813             :         }
    4814             : 
    4815           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4816             :                                                      af,
    4817             :                                                      hedst,
    4818             :                                                      buf,
    4819             :                                                      buflen,
    4820             :                                                      &errno,
    4821             :                                                      &h_errno);
    4822           0 :         switch (status) {
    4823           0 :         case NSS_STATUS_SUCCESS:
    4824           0 :                 *hedstp = hedst;
    4825           0 :                 return 0;
    4826           0 :         case NSS_STATUS_NOTFOUND:
    4827           0 :                 if (errno != 0) {
    4828           0 :                         return errno;
    4829             :                 }
    4830           0 :                 return ENOENT;
    4831           0 :         case NSS_STATUS_TRYAGAIN:
    4832           0 :                 if (errno != 0) {
    4833           0 :                         return errno;
    4834             :                 }
    4835           0 :                 return ERANGE;
    4836           0 :         default:
    4837           0 :                 if (errno != 0) {
    4838           0 :                         return errno;
    4839             :                 }
    4840           0 :                 return status;
    4841             :         }
    4842             : }
    4843             : 
    4844           0 : static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
    4845             :                                                   const char *name)
    4846             : {
    4847             :         static struct hostent he;
    4848             :         static char *buf = NULL;
    4849             :         static size_t buflen = 1000;
    4850             :         NSS_STATUS status;
    4851             : 
    4852           0 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4853           0 :                 return NULL;
    4854             :         }
    4855             : 
    4856           0 :         if (buf == NULL) {
    4857           0 :                 buf = (char *)malloc(buflen);
    4858           0 :                 if (buf == NULL) {
    4859           0 :                         return NULL;
    4860             :                 }
    4861             :         }
    4862             : 
    4863           0 : again:
    4864           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4865             :                                                      AF_UNSPEC,
    4866             :                                                      &he,
    4867             :                                                      buf,
    4868             :                                                      buflen,
    4869             :                                                      &errno,
    4870             :                                                      &h_errno);
    4871           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4872           0 :                 char *p = NULL;
    4873             : 
    4874           0 :                 buflen *= 2;
    4875           0 :                 p = (char *)realloc(buf, buflen);
    4876           0 :                 if (p == NULL) {
    4877           0 :                         SAFE_FREE(buf);
    4878           0 :                         return NULL;
    4879             :                 }
    4880           0 :                 buf = p;
    4881           0 :                 goto again;
    4882             :         }
    4883           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4884           0 :                 SAFE_FREE(buf);
    4885           0 :                 return NULL;
    4886             :         }
    4887           0 :         if (status != NSS_STATUS_SUCCESS) {
    4888           0 :                 SAFE_FREE(buf);
    4889           0 :                 return NULL;
    4890             :         }
    4891             : 
    4892           0 :         return &he;
    4893             : }
    4894             : 
    4895           0 : static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
    4896             :                                                    const char *name, int af)
    4897             : {
    4898             :         static struct hostent he;
    4899             :         static char *buf = NULL;
    4900             :         static size_t buflen = 1000;
    4901             :         NSS_STATUS status;
    4902             : 
    4903           0 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4904           0 :                 return NULL;
    4905             :         }
    4906             : 
    4907           0 :         if (buf == NULL) {
    4908           0 :                 buf = (char *)malloc(buflen);
    4909           0 :                 if (buf == NULL) {
    4910           0 :                         return NULL;
    4911             :                 }
    4912             :         }
    4913             : 
    4914           0 : again:
    4915           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4916             :                                                      af,
    4917             :                                                      &he,
    4918             :                                                      buf,
    4919             :                                                      buflen,
    4920             :                                                      &errno,
    4921             :                                                      &h_errno);
    4922           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4923           0 :                 char *p = NULL;
    4924             : 
    4925           0 :                 buflen *= 2;
    4926           0 :                 p = (char *)realloc(buf, buflen);
    4927           0 :                 if (p == NULL) {
    4928           0 :                         SAFE_FREE(buf);
    4929           0 :                         return NULL;
    4930             :                 }
    4931           0 :                 buf = p;
    4932           0 :                 goto again;
    4933             :         }
    4934           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4935           0 :                 SAFE_FREE(buf);
    4936           0 :                 return NULL;
    4937             :         }
    4938           0 :         if (status != NSS_STATUS_SUCCESS) {
    4939           0 :                 SAFE_FREE(buf);
    4940           0 :                 return NULL;
    4941             :         }
    4942             : 
    4943           0 :         return &he;
    4944             : }
    4945             : 
    4946             : /****************************************************************************
    4947             :  *   GETPWNAM
    4948             :  ***************************************************************************/
    4949             : 
    4950       13419 : static struct passwd *nwrap_getpwnam(const char *name)
    4951             : {
    4952             :         size_t i;
    4953             :         struct passwd *pwd;
    4954             : 
    4955       25324 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4956       19421 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4957       19421 :                 pwd = b->ops->nw_getpwnam(b, name);
    4958       19421 :                 if (pwd) {
    4959        7516 :                         return pwd;
    4960             :                 }
    4961             :         }
    4962             : 
    4963        5903 :         return NULL;
    4964             : }
    4965             : 
    4966             : struct passwd *getpwnam(const char *name)
    4967             : {
    4968       13949 :         if (!nss_wrapper_enabled()) {
    4969         530 :                 return libc_getpwnam(name);
    4970             :         }
    4971             : 
    4972       13419 :         return nwrap_getpwnam(name);
    4973             : }
    4974             : 
    4975             : /****************************************************************************
    4976             :  *   GETPWNAM_R
    4977             :  ***************************************************************************/
    4978             : 
    4979         160 : static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
    4980             :                             char *buf, size_t buflen, struct passwd **pwdstp)
    4981             : {
    4982             :         size_t i;
    4983             :         int ret;
    4984             : 
    4985         300 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4986         212 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4987         212 :                 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
    4988         212 :                 if (ret == ENOENT) {
    4989          52 :                         continue;
    4990             :                 }
    4991         160 :                 return ret;
    4992             :         }
    4993             : 
    4994           0 :         return ENOENT;
    4995             : }
    4996             : 
    4997             : #ifdef HAVE_GETPWNAM_R
    4998             : # ifdef HAVE_SOLARIS_GETPWNAM_R
    4999             : int getpwnam_r(const char *name, struct passwd *pwdst,
    5000             :                char *buf, int buflen, struct passwd **pwdstp)
    5001             : # else /* HAVE_SOLARIS_GETPWNAM_R */
    5002             : int getpwnam_r(const char *name, struct passwd *pwdst,
    5003             :                char *buf, size_t buflen, struct passwd **pwdstp)
    5004             : # endif /* HAVE_SOLARIS_GETPWNAM_R */
    5005             : {
    5006         160 :         if (!nss_wrapper_enabled()) {
    5007           0 :                 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
    5008             :         }
    5009             : 
    5010         160 :         return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
    5011             : }
    5012             : #endif
    5013             : 
    5014             : /****************************************************************************
    5015             :  *   GETPWUID
    5016             :  ***************************************************************************/
    5017             : 
    5018       25692 : static struct passwd *nwrap_getpwuid(uid_t uid)
    5019             : {
    5020             :         size_t i;
    5021             :         struct passwd *pwd;
    5022             : 
    5023       30125 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5024       28239 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5025       28239 :                 pwd = b->ops->nw_getpwuid(b, uid);
    5026       28239 :                 if (pwd) {
    5027       23806 :                         return pwd;
    5028             :                 }
    5029             :         }
    5030             : 
    5031        1886 :         return NULL;
    5032             : }
    5033             : 
    5034             : struct passwd *getpwuid(uid_t uid)
    5035             : {
    5036       28578 :         if (!nss_wrapper_enabled()) {
    5037        2886 :                 return libc_getpwuid(uid);
    5038             :         }
    5039             : 
    5040       25692 :         return nwrap_getpwuid(uid);
    5041             : }
    5042             : 
    5043             : /****************************************************************************
    5044             :  *   GETPWUID_R
    5045             :  ***************************************************************************/
    5046             : 
    5047         141 : static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
    5048             :                             char *buf, size_t buflen, struct passwd **pwdstp)
    5049             : {
    5050             :         size_t i;
    5051             :         int ret;
    5052             : 
    5053         281 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5054         193 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5055         193 :                 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
    5056         193 :                 if (ret == ENOENT) {
    5057          52 :                         continue;
    5058             :                 }
    5059         141 :                 return ret;
    5060             :         }
    5061             : 
    5062           0 :         return ENOENT;
    5063             : }
    5064             : 
    5065             : #ifdef HAVE_SOLARIS_GETPWUID_R
    5066             : int getpwuid_r(uid_t uid, struct passwd *pwdst,
    5067             :                char *buf, int buflen, struct passwd **pwdstp)
    5068             : #else
    5069             : int getpwuid_r(uid_t uid, struct passwd *pwdst,
    5070             :                char *buf, size_t buflen, struct passwd **pwdstp)
    5071             : #endif
    5072             : {
    5073         141 :         if (!nss_wrapper_enabled()) {
    5074           0 :                 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
    5075             :         }
    5076             : 
    5077         141 :         return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
    5078             : }
    5079             : 
    5080             : /****************************************************************************
    5081             :  *   SETPWENT
    5082             :  ***************************************************************************/
    5083             : 
    5084          10 : static void nwrap_setpwent(void)
    5085             : {
    5086             :         size_t i;
    5087             : 
    5088          30 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5089          20 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5090          20 :                 b->ops->nw_setpwent(b);
    5091             :         }
    5092          10 : }
    5093             : 
    5094             : void setpwent(void)
    5095             : {
    5096          10 :         if (!nss_wrapper_enabled()) {
    5097           0 :                 libc_setpwent();
    5098           0 :                 return;
    5099             :         }
    5100             : 
    5101          10 :         nwrap_setpwent();
    5102             : }
    5103             : 
    5104             : /****************************************************************************
    5105             :  *   GETPWENT
    5106             :  ***************************************************************************/
    5107             : 
    5108         192 : static struct passwd *nwrap_getpwent(void)
    5109             : {
    5110             :         size_t i;
    5111             :         struct passwd *pwd;
    5112             : 
    5113         282 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5114         276 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5115         276 :                 pwd = b->ops->nw_getpwent(b);
    5116         276 :                 if (pwd) {
    5117         186 :                         return pwd;
    5118             :                 }
    5119             :         }
    5120             : 
    5121           6 :         return NULL;
    5122             : }
    5123             : 
    5124             : struct passwd *getpwent(void)
    5125             : {
    5126         192 :         if (!nss_wrapper_enabled()) {
    5127           0 :                 return libc_getpwent();
    5128             :         }
    5129             : 
    5130         192 :         return nwrap_getpwent();
    5131             : }
    5132             : 
    5133             : /****************************************************************************
    5134             :  *   GETPWENT_R
    5135             :  ***************************************************************************/
    5136             : 
    5137             : #ifdef HAVE_GETPWENT_R
    5138         128 : static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
    5139             :                             size_t buflen, struct passwd **pwdstp)
    5140             : {
    5141             :         size_t i;
    5142             :         int ret;
    5143             : 
    5144         282 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5145         184 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5146         184 :                 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
    5147         184 :                 if (ret == ENOENT) {
    5148          60 :                         continue;
    5149             :                 }
    5150         124 :                 return ret;
    5151             :         }
    5152             : 
    5153           4 :         return ENOENT;
    5154             : }
    5155             : 
    5156             : #  ifdef HAVE_SOLARIS_GETPWENT_R
    5157             : struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
    5158             : {
    5159             :         struct passwd *pwdstp = NULL;
    5160             :         int rc;
    5161             : 
    5162             :         if (!nss_wrapper_enabled()) {
    5163             :                 return libc_getpwent_r(pwdst, buf, buflen);
    5164             :         }
    5165             :         rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
    5166             :         if (rc < 0) {
    5167             :                 return NULL;
    5168             :         }
    5169             : 
    5170             :         return pwdstp;
    5171             : }
    5172             : #  else /* HAVE_SOLARIS_GETPWENT_R */
    5173             : int getpwent_r(struct passwd *pwdst, char *buf,
    5174             :                size_t buflen, struct passwd **pwdstp)
    5175             : {
    5176         128 :         if (!nss_wrapper_enabled()) {
    5177           0 :                 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
    5178             :         }
    5179             : 
    5180         128 :         return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
    5181             : }
    5182             : #  endif /* HAVE_SOLARIS_GETPWENT_R */
    5183             : #endif /* HAVE_GETPWENT_R */
    5184             : 
    5185             : /****************************************************************************
    5186             :  *   ENDPWENT
    5187             :  ***************************************************************************/
    5188             : 
    5189        3678 : static void nwrap_endpwent(void)
    5190             : {
    5191             :         size_t i;
    5192             : 
    5193       11028 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5194        7350 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5195        7350 :                 b->ops->nw_endpwent(b);
    5196             :         }
    5197        3678 : }
    5198             : 
    5199             : void endpwent(void)
    5200             : {
    5201        3886 :         if (!nss_wrapper_enabled()) {
    5202         208 :                 libc_endpwent();
    5203         208 :                 return;
    5204             :         }
    5205             : 
    5206        3678 :         nwrap_endpwent();
    5207             : }
    5208             : 
    5209             : /****************************************************************************
    5210             :  *   INITGROUPS
    5211             :  ***************************************************************************/
    5212             : 
    5213           0 : static int nwrap_initgroups(const char *user, gid_t group)
    5214             : {
    5215             :         size_t i;
    5216             : 
    5217           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5218           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5219             :                 int rc;
    5220             : 
    5221           0 :                 rc = b->ops->nw_initgroups(b, user, group);
    5222           0 :                 if (rc == 0) {
    5223           0 :                         return 0;
    5224             :                 }
    5225             :         }
    5226             : 
    5227           0 :         errno = ENOENT;
    5228           0 :         return -1;
    5229             : }
    5230             : 
    5231             : int initgroups(const char *user, gid_t group)
    5232             : {
    5233           0 :         if (!nss_wrapper_enabled()) {
    5234           0 :                 return libc_initgroups(user, group);
    5235             :         }
    5236             : 
    5237           0 :         return nwrap_initgroups(user, group);
    5238             : }
    5239             : 
    5240             : /****************************************************************************
    5241             :  *   GETGRNAM
    5242             :  ***************************************************************************/
    5243             : 
    5244         606 : static struct group *nwrap_getgrnam(const char *name)
    5245             : {
    5246             :         size_t i;
    5247             :         struct group *grp;
    5248             : 
    5249        1036 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5250         832 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5251         832 :                 grp = b->ops->nw_getgrnam(b, name);
    5252         832 :                 if (grp) {
    5253         402 :                         return grp;
    5254             :                 }
    5255             :         }
    5256             : 
    5257         204 :         return NULL;
    5258             : }
    5259             : 
    5260             : struct group *getgrnam(const char *name)
    5261             : {
    5262         737 :         if (!nss_wrapper_enabled()) {
    5263         131 :                 return libc_getgrnam(name);
    5264             :         }
    5265             : 
    5266         606 :         return nwrap_getgrnam(name);
    5267             : }
    5268             : 
    5269             : /****************************************************************************
    5270             :  *   GETGRNAM_R
    5271             :  ***************************************************************************/
    5272             : 
    5273         167 : static int nwrap_getgrnam_r(const char *name, struct group *grdst,
    5274             :                             char *buf, size_t buflen, struct group **grdstp)
    5275             : {
    5276             :         size_t i;
    5277             :         int ret;
    5278             : 
    5279         369 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5280         243 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5281         243 :                 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
    5282         243 :                 if (ret == ENOENT) {
    5283         108 :                         continue;
    5284             :                 }
    5285         135 :                 return ret;
    5286             :         }
    5287             : 
    5288          32 :         return ENOENT;
    5289             : }
    5290             : 
    5291             : #ifdef HAVE_GETGRNAM_R
    5292             : # ifdef HAVE_SOLARIS_GETGRNAM_R
    5293             : int getgrnam_r(const char *name, struct group *grp,
    5294             :                 char *buf, int buflen, struct group **pgrp)
    5295             : # else /* HAVE_SOLARIS_GETGRNAM_R */
    5296             : int getgrnam_r(const char *name, struct group *grp,
    5297             :                char *buf, size_t buflen, struct group **pgrp)
    5298             : # endif /* HAVE_SOLARIS_GETGRNAM_R */
    5299             : {
    5300         167 :         if (!nss_wrapper_enabled()) {
    5301           0 :                 return libc_getgrnam_r(name,
    5302             :                                        grp,
    5303             :                                        buf,
    5304             :                                        buflen,
    5305             :                                        pgrp);
    5306             :         }
    5307             : 
    5308         167 :         return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
    5309             : }
    5310             : #endif /* HAVE_GETGRNAM_R */
    5311             : 
    5312             : /****************************************************************************
    5313             :  *   GETGRGID
    5314             :  ***************************************************************************/
    5315             : 
    5316        2042 : static struct group *nwrap_getgrgid(gid_t gid)
    5317             : {
    5318             :         size_t i;
    5319             :         struct group *grp;
    5320             : 
    5321        2210 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5322        2206 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5323        2206 :                 grp = b->ops->nw_getgrgid(b, gid);
    5324        2206 :                 if (grp) {
    5325        2038 :                         return grp;
    5326             :                 }
    5327             :         }
    5328             : 
    5329           4 :         return NULL;
    5330             : }
    5331             : 
    5332             : struct group *getgrgid(gid_t gid)
    5333             : {
    5334        2278 :         if (!nss_wrapper_enabled()) {
    5335         236 :                 return libc_getgrgid(gid);
    5336             :         }
    5337             : 
    5338        2042 :         return nwrap_getgrgid(gid);
    5339             : }
    5340             : 
    5341             : /****************************************************************************
    5342             :  *   GETGRGID_R
    5343             :  ***************************************************************************/
    5344             : 
    5345         116 : static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
    5346             :                             char *buf, size_t buflen, struct group **grdstp)
    5347             : {
    5348             :         size_t i;
    5349             :         int ret;
    5350             : 
    5351         282 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5352         188 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5353         188 :                 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
    5354         188 :                 if (ret == ENOENT) {
    5355          72 :                         continue;
    5356             :                 }
    5357         116 :                 return ret;
    5358             :         }
    5359             : 
    5360           0 :         return ENOENT;
    5361             : }
    5362             : 
    5363             : #ifdef HAVE_GETGRGID_R
    5364             : # ifdef HAVE_SOLARIS_GETGRGID_R
    5365             : int getgrgid_r(gid_t gid, struct group *grdst,
    5366             :                char *buf, int buflen, struct group **grdstp)
    5367             : # else /* HAVE_SOLARIS_GETGRGID_R */
    5368             : int getgrgid_r(gid_t gid, struct group *grdst,
    5369             :                char *buf, size_t buflen, struct group **grdstp)
    5370             : # endif /* HAVE_SOLARIS_GETGRGID_R */
    5371             : {
    5372         116 :         if (!nss_wrapper_enabled()) {
    5373           0 :                 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
    5374             :         }
    5375             : 
    5376         116 :         return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
    5377             : }
    5378             : #endif
    5379             : 
    5380             : /****************************************************************************
    5381             :  *   SETGRENT
    5382             :  ***************************************************************************/
    5383             : 
    5384        3090 : static void nwrap_setgrent(void)
    5385             : {
    5386             :         size_t i;
    5387             : 
    5388        9186 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5389        6096 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5390        6096 :                 b->ops->nw_setgrent(b);
    5391             :         }
    5392        3090 : }
    5393             : 
    5394             : #ifdef HAVE_BSD_SETGRENT
    5395             : int setgrent(void)
    5396             : #else
    5397             : void setgrent(void)
    5398             : #endif
    5399             : {
    5400          10 :         if (!nss_wrapper_enabled()) {
    5401           0 :                 libc_setgrent();
    5402           0 :                 goto out;
    5403             :         }
    5404             : 
    5405          10 :         nwrap_setgrent();
    5406             : 
    5407          10 : out:
    5408             : #ifdef HAVE_BSD_SETGRENT
    5409             :         return 0;
    5410             : #else
    5411          10 :         return;
    5412             : #endif
    5413             : }
    5414             : 
    5415             : /****************************************************************************
    5416             :  *   GETGRENT
    5417             :  ***************************************************************************/
    5418             : 
    5419       35926 : static struct group *nwrap_getgrent(void)
    5420             : {
    5421             :         size_t i;
    5422             :         struct group *grp;
    5423             : 
    5424       44498 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5425       41412 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5426       41412 :                 grp = b->ops->nw_getgrent(b);
    5427       41412 :                 if (grp) {
    5428       32840 :                         return grp;
    5429             :                 }
    5430             :         }
    5431             : 
    5432        3086 :         return NULL;
    5433             : }
    5434             : 
    5435             : struct group *getgrent(void)
    5436             : {
    5437         180 :         if (!nss_wrapper_enabled()) {
    5438           0 :                 return libc_getgrent();
    5439             :         }
    5440             : 
    5441         180 :         return nwrap_getgrent();
    5442             : }
    5443             : 
    5444             : /****************************************************************************
    5445             :  *   GETGRENT_R
    5446             :  ***************************************************************************/
    5447             : 
    5448             : #ifdef HAVE_GETGRENT_R
    5449         120 : static int nwrap_getgrent_r(struct group *grdst, char *buf,
    5450             :                             size_t buflen, struct group **grdstp)
    5451             : {
    5452             :         size_t i;
    5453             :         int ret;
    5454             : 
    5455         300 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5456         196 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5457         196 :                 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
    5458         196 :                 if (ret == ENOENT) {
    5459          80 :                         continue;
    5460             :                 }
    5461         116 :                 return ret;
    5462             :         }
    5463             : 
    5464           4 :         return ENOENT;
    5465             : }
    5466             : 
    5467             : #  ifdef HAVE_SOLARIS_GETGRENT_R
    5468             : struct group *getgrent_r(struct group *src, char *buf, int buflen)
    5469             : {
    5470             :         struct group *grdstp = NULL;
    5471             :         int rc;
    5472             : 
    5473             :         if (!nss_wrapper_enabled()) {
    5474             :                 return libc_getgrent_r(src, buf, buflen);
    5475             :         }
    5476             : 
    5477             :         rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
    5478             :         if (rc < 0) {
    5479             :                 return NULL;
    5480             :         }
    5481             : 
    5482             :         return grdstp;
    5483             : }
    5484             : #  else /* HAVE_SOLARIS_GETGRENT_R */
    5485             : int getgrent_r(struct group *src, char *buf,
    5486             :                size_t buflen, struct group **grdstp)
    5487             : {
    5488         120 :         if (!nss_wrapper_enabled()) {
    5489           0 :                 return libc_getgrent_r(src, buf, buflen, grdstp);
    5490             :         }
    5491             : 
    5492         120 :         return nwrap_getgrent_r(src, buf, buflen, grdstp);
    5493             : }
    5494             : #  endif /* HAVE_SOLARIS_GETGRENT_R */
    5495             : #endif /* HAVE_GETGRENT_R */
    5496             : 
    5497             : /****************************************************************************
    5498             :  *   ENDGRENT
    5499             :  ***************************************************************************/
    5500             : 
    5501        3090 : static void nwrap_endgrent(void)
    5502             : {
    5503             :         size_t i;
    5504             : 
    5505        9186 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5506        6096 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5507        6096 :                 b->ops->nw_endgrent(b);
    5508             :         }
    5509        3090 : }
    5510             : 
    5511             : void endgrent(void)
    5512             : {
    5513          10 :         if (!nss_wrapper_enabled()) {
    5514           0 :                 libc_endgrent();
    5515           0 :                 return;
    5516             :         }
    5517             : 
    5518          10 :         nwrap_endgrent();
    5519             : }
    5520             : 
    5521             : /****************************************************************************
    5522             :  *   GETGROUPLIST
    5523             :  ***************************************************************************/
    5524             : 
    5525             : #ifdef HAVE_GETGROUPLIST
    5526        3080 : static int nwrap_getgrouplist(const char *user, gid_t group,
    5527             :                               gid_t *groups, int *ngroups)
    5528             : {
    5529             :         struct group *grp;
    5530             :         gid_t *groups_tmp;
    5531        3080 :         int count = 1;
    5532             : 
    5533        3080 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
    5534             : 
    5535        3080 :         groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
    5536        3080 :         if (!groups_tmp) {
    5537           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    5538           0 :                 errno = ENOMEM;
    5539           0 :                 return -1;
    5540             :         }
    5541        3080 :         groups_tmp[0] = group;
    5542             : 
    5543        3080 :         nwrap_setgrent();
    5544       37748 :         while ((grp = nwrap_getgrent()) != NULL) {
    5545       32666 :                 int i = 0;
    5546             : 
    5547       32666 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    5548             :                           "Inspecting %s for group membership",
    5549             :                           grp->gr_name);
    5550             : 
    5551       42832 :                 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
    5552             : 
    5553       16002 :                         if (group != grp->gr_gid &&
    5554       10094 :                             (strcmp(user, grp->gr_mem[i]) == 0)) {
    5555             : 
    5556        1445 :                                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    5557             :                                           "%s is member of %s",
    5558             :                                           user,
    5559             :                                           grp->gr_name);
    5560             : 
    5561        1445 :                                 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
    5562        1445 :                                 if (!groups_tmp) {
    5563           0 :                                         NWRAP_LOG(NWRAP_LOG_ERROR,
    5564             :                                                   "Out of memory");
    5565           0 :                                         errno = ENOMEM;
    5566           0 :                                         return -1;
    5567             :                                 }
    5568        1445 :                                 groups_tmp[count] = grp->gr_gid;
    5569             : 
    5570        1445 :                                 count++;
    5571             :                         }
    5572             :                 }
    5573             :         }
    5574             : 
    5575        3080 :         nwrap_endgrent();
    5576             : 
    5577        3080 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    5578             :                   "%s is member of %d groups",
    5579             :                   user, *ngroups);
    5580             : 
    5581        3080 :         if (*ngroups < count) {
    5582          62 :                 *ngroups = count;
    5583          62 :                 free(groups_tmp);
    5584          62 :                 return -1;
    5585             :         }
    5586             : 
    5587        3018 :         *ngroups = count;
    5588        3018 :         memcpy(groups, groups_tmp, count * sizeof(gid_t));
    5589        3018 :         free(groups_tmp);
    5590             : 
    5591        3018 :         return count;
    5592             : }
    5593             : 
    5594             : int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
    5595             : {
    5596        3080 :         if (!nss_wrapper_enabled()) {
    5597           0 :                 return libc_getgrouplist(user, group, groups, ngroups);
    5598             :         }
    5599             : 
    5600        3080 :         return nwrap_getgrouplist(user, group, groups, ngroups);
    5601             : }
    5602             : #endif
    5603             : 
    5604             : /**********************************************************
    5605             :  * SHADOW
    5606             :  **********************************************************/
    5607             : 
    5608             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    5609             : 
    5610             : #ifdef HAVE_SETSPENT
    5611             : static void nwrap_setspent(void)
    5612             : {
    5613             :         nwrap_files_setspent();
    5614             : }
    5615             : 
    5616             : void setspent(void)
    5617             : {
    5618             :         if (!nss_wrapper_shadow_enabled()) {
    5619             :                 return;
    5620             :         }
    5621             : 
    5622             :         nwrap_setspent();
    5623             : }
    5624             : 
    5625             : static struct spwd *nwrap_getspent(void)
    5626             : {
    5627             :         return nwrap_files_getspent();
    5628             : }
    5629             : 
    5630             : struct spwd *getspent(void)
    5631             : {
    5632             :         if (!nss_wrapper_shadow_enabled()) {
    5633             :                 return NULL;
    5634             :         }
    5635             : 
    5636             :         return nwrap_getspent();
    5637             : }
    5638             : 
    5639             : static void nwrap_endspent(void)
    5640             : {
    5641             :         nwrap_files_endspent();
    5642             : }
    5643             : 
    5644             : void endspent(void)
    5645             : {
    5646             :         if (!nss_wrapper_shadow_enabled()) {
    5647             :                 return;
    5648             :         }
    5649             : 
    5650             :         nwrap_endspent();
    5651             : }
    5652             : #endif /* HAVE_SETSPENT */
    5653             : 
    5654           0 : static struct spwd *nwrap_getspnam(const char *name)
    5655             : {
    5656           0 :         return nwrap_files_getspnam(name);
    5657             : }
    5658             : 
    5659             : struct spwd *getspnam(const char *name)
    5660             : {
    5661           0 :         if (!nss_wrapper_shadow_enabled()) {
    5662           0 :                 return NULL;
    5663             :         }
    5664             : 
    5665           0 :         return nwrap_getspnam(name);
    5666             : }
    5667             : 
    5668             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    5669             : 
    5670             : /**********************************************************
    5671             :  * NETDB
    5672             :  **********************************************************/
    5673             : 
    5674           0 : static void nwrap_sethostent(int stayopen) {
    5675             :         (void) stayopen; /* ignored */
    5676             : 
    5677           0 :         nwrap_files_sethostent();
    5678           0 : }
    5679             : 
    5680             : #ifdef HAVE_SOLARIS_SETHOSTENT
    5681             : int sethostent(int stayopen)
    5682             : {
    5683             :         if (!nss_wrapper_hosts_enabled()) {
    5684             :                 libc_sethostent(stayopen);
    5685             :                 return 0;
    5686             :         }
    5687             : 
    5688             :         nwrap_sethostent(stayopen);
    5689             : 
    5690             :         return 0;
    5691             : }
    5692             : #else /* HAVE_SOLARIS_SETHOSTENT */
    5693             : void sethostent(int stayopen)
    5694             : {
    5695           0 :         if (!nss_wrapper_hosts_enabled()) {
    5696           0 :                 libc_sethostent(stayopen);
    5697           0 :                 return;
    5698             :         }
    5699             : 
    5700           0 :         nwrap_sethostent(stayopen);
    5701             : }
    5702             : #endif /* HAVE_SOLARIS_SETHOSTENT */
    5703             : 
    5704           0 : static struct hostent *nwrap_gethostent(void)
    5705             : {
    5706           0 :         return nwrap_files_gethostent();
    5707             : }
    5708             : 
    5709             : struct hostent *gethostent(void) {
    5710           0 :         if (!nss_wrapper_hosts_enabled()) {
    5711           0 :                 return libc_gethostent();
    5712             :         }
    5713             : 
    5714           0 :         return nwrap_gethostent();
    5715             : }
    5716             : 
    5717           0 : static void nwrap_endhostent(void) {
    5718           0 :         nwrap_files_endhostent();
    5719           0 : }
    5720             : 
    5721             : #ifdef HAVE_SOLARIS_ENDHOSTENT
    5722             : int endhostent(void)
    5723             : {
    5724             :         if (!nss_wrapper_hosts_enabled()) {
    5725             :                 libc_endhostent();
    5726             :                 return 0;
    5727             :         }
    5728             : 
    5729             :         nwrap_endhostent();
    5730             : 
    5731             :         return 0;
    5732             : }
    5733             : #else /* HAVE_SOLARIS_ENDHOSTENT */
    5734             : void endhostent(void)
    5735             : {
    5736           0 :         if (!nss_wrapper_hosts_enabled()) {
    5737           0 :                 libc_endhostent();
    5738           0 :                 return;
    5739             :         }
    5740             : 
    5741           0 :         nwrap_endhostent();
    5742             : }
    5743             : #endif /* HAVE_SOLARIS_ENDHOSTENT */
    5744             : 
    5745             : 
    5746             : #ifdef BSD
    5747             : /* BSD implementation stores data in thread local storage but GLIBC does not */
    5748             : static __thread struct hostent user_he;
    5749             : static __thread struct nwrap_vector user_addrlist;
    5750             : #else
    5751             : static struct hostent user_he;
    5752             : static struct nwrap_vector user_addrlist;
    5753             : #endif /* BSD */
    5754             : 
    5755           0 : static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
    5756             :                                                  const char *name)
    5757             : {
    5758             :         int ret;
    5759             : 
    5760             :         (void) b; /* unused */
    5761             : 
    5762           0 :         ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he,
    5763             :                                                  &user_addrlist);
    5764           0 :         if (ret == 0) {
    5765           0 :                 return &user_he;
    5766             :         }
    5767             : 
    5768           0 :         return NULL;
    5769             : }
    5770             : 
    5771           0 : static struct hostent *nwrap_gethostbyname(const char *name)
    5772             : {
    5773             :         size_t i;
    5774           0 :         struct hostent *he = NULL;
    5775             : 
    5776           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5777           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5778           0 :                 he = b->ops->nw_gethostbyname(b, name);
    5779           0 :                 if (he != NULL) {
    5780           0 :                         return he;
    5781             :                 }
    5782             :         }
    5783             : 
    5784           0 :         return NULL;
    5785             : }
    5786             : 
    5787             : struct hostent *gethostbyname(const char *name)
    5788             : {
    5789           0 :         if (!nss_wrapper_hosts_enabled()) {
    5790           0 :                 return libc_gethostbyname(name);
    5791             :         }
    5792             : 
    5793           0 :         return nwrap_gethostbyname(name);
    5794             : }
    5795             : 
    5796             : /* This is a GNU extension - Also can be found on BSD systems */
    5797             : #ifdef HAVE_GETHOSTBYNAME2
    5798             : #ifdef BSD
    5799             : /* BSD implementation stores data in  thread local storage but GLIBC not */
    5800             : static __thread struct hostent user_he2;
    5801             : static __thread struct nwrap_vector user_addrlist2;
    5802             : #else
    5803             : static struct hostent user_he2;
    5804             : static struct nwrap_vector user_addrlist2;
    5805             : #endif /* BSD */
    5806             : 
    5807           0 : static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
    5808             :                                                   const char *name, int af)
    5809             : {
    5810             :         int ret;
    5811             : 
    5812             :         (void) b; /* unused */
    5813             : 
    5814           0 :         ret = nwrap_files_internal_gethostbyname(name, af, &user_he2,
    5815             :                                                  &user_addrlist2);
    5816           0 :         if (ret == 0) {
    5817           0 :                 return &user_he2;
    5818             :         }
    5819             : 
    5820           0 :         return NULL;
    5821             : }
    5822             : 
    5823           0 : static struct hostent *nwrap_gethostbyname2(const char *name, int af)
    5824             : {
    5825             :         size_t i;
    5826           0 :         struct hostent *he = NULL;
    5827             : 
    5828           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5829           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5830           0 :                 he = b->ops->nw_gethostbyname2(b, name, af);
    5831           0 :                 if (he != NULL) {
    5832           0 :                         return he;
    5833             :                 }
    5834             :         }
    5835             : 
    5836           0 :         return NULL;
    5837             : }
    5838             : 
    5839             : struct hostent *gethostbyname2(const char *name, int af)
    5840             : {
    5841           0 :         if (!nss_wrapper_hosts_enabled()) {
    5842           0 :                 return libc_gethostbyname2(name, af);
    5843             :         }
    5844             : 
    5845           0 :         return nwrap_gethostbyname2(name, af);
    5846             : }
    5847             : #endif
    5848             : 
    5849           0 : static struct hostent *nwrap_gethostbyaddr(const void *addr,
    5850             :                                            socklen_t len, int type)
    5851             : {
    5852             :         size_t i;
    5853           0 :         struct hostent *he = NULL;
    5854             : 
    5855           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5856           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5857           0 :                 he = b->ops->nw_gethostbyaddr(b, addr, len, type);
    5858           0 :                 if (he != NULL) {
    5859           0 :                         return he;
    5860             :                 }
    5861             :         }
    5862             : 
    5863           0 :         return NULL;
    5864             : }
    5865             : 
    5866             : struct hostent *gethostbyaddr(const void *addr,
    5867             :                               socklen_t len, int type)
    5868             : {
    5869           0 :         if (!nss_wrapper_hosts_enabled()) {
    5870           0 :                 return libc_gethostbyaddr(addr, len, type);
    5871             :         }
    5872             : 
    5873           0 :         return nwrap_gethostbyaddr(addr, len, type);
    5874             : }
    5875             : 
    5876             : static const struct addrinfo default_hints =
    5877             : {
    5878             :         .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
    5879             :         .ai_family = AF_UNSPEC,
    5880             :         .ai_socktype = 0,
    5881             :         .ai_protocol = 0,
    5882             :         .ai_addrlen = 0,
    5883             :         .ai_addr = NULL,
    5884             :         .ai_canonname = NULL,
    5885             :         .ai_next = NULL
    5886             : };
    5887             : 
    5888      181223 : static int nwrap_convert_he_ai(const struct hostent *he,
    5889             :                                unsigned short port,
    5890             :                                const struct addrinfo *hints,
    5891             :                                struct addrinfo **pai,
    5892             :                                bool skip_canonname)
    5893             : {
    5894             :         struct addrinfo *ai;
    5895             :         socklen_t socklen;
    5896             : 
    5897      181223 :         if (he == NULL) {
    5898           0 :                 return EAI_MEMORY;
    5899             :         }
    5900             : 
    5901      181223 :         switch (he->h_addrtype) {
    5902      131759 :                 case AF_INET:
    5903      131759 :                         socklen = sizeof(struct sockaddr_in);
    5904      131759 :                         break;
    5905             : #ifdef HAVE_IPV6
    5906       49464 :                 case AF_INET6:
    5907       49464 :                         socklen = sizeof(struct sockaddr_in6);
    5908       49464 :                         break;
    5909             : #endif
    5910           0 :                 default:
    5911           0 :                         return EAI_FAMILY;
    5912             :         }
    5913             : 
    5914      181223 :         ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
    5915      181223 :         if (ai == NULL) {
    5916           0 :                 return EAI_MEMORY;
    5917             :         }
    5918             : 
    5919      181223 :         ai->ai_flags = hints->ai_flags;
    5920      181223 :         ai->ai_family = he->h_addrtype;
    5921      181223 :         ai->ai_socktype = hints->ai_socktype;
    5922      181223 :         ai->ai_protocol = hints->ai_protocol;
    5923      181223 :         ai->ai_canonname = NULL;
    5924             : 
    5925      181223 :         if (ai->ai_socktype == 0) {
    5926         194 :                 ai->ai_socktype = SOCK_DGRAM;
    5927             :         }
    5928      181223 :         if (ai->ai_protocol == 0) {
    5929      169285 :                 if (ai->ai_socktype == SOCK_DGRAM) {
    5930       17975 :                         ai->ai_protocol = IPPROTO_UDP;
    5931      151310 :                 } else if (ai->ai_socktype == SOCK_STREAM) {
    5932      151310 :                         ai->ai_protocol = IPPROTO_TCP;
    5933             :                 }
    5934             :         }
    5935             : 
    5936      181223 :         ai->ai_addrlen = socklen;
    5937      181223 :         ai->ai_addr = (void *)(ai + 1);
    5938             : 
    5939             : #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
    5940             :         ai->ai_addr->sa_len = socklen;
    5941             : #endif
    5942      181223 :         ai->ai_addr->sa_family = he->h_addrtype;
    5943             : 
    5944      181223 :         switch (he->h_addrtype) {
    5945      131759 :                 case AF_INET:
    5946      114555 :                 {
    5947             :                         union {
    5948             :                                 struct sockaddr *sa;
    5949             :                                 struct sockaddr_in *in;
    5950             :                         } addr;
    5951             : 
    5952      131759 :                         addr.sa = ai->ai_addr;
    5953             : 
    5954      131759 :                         memset(addr.in, 0, sizeof(struct sockaddr_in));
    5955             : 
    5956      131759 :                         addr.in->sin_port = htons(port);
    5957      131759 :                         addr.in->sin_family = AF_INET;
    5958             : 
    5959      131759 :                         memset(addr.in->sin_zero,
    5960             :                                '\0',
    5961             :                                sizeof (addr.in->sin_zero));
    5962      246314 :                         memcpy(&(addr.in->sin_addr),
    5963      131759 :                                he->h_addr_list[0],
    5964      131759 :                                he->h_length);
    5965             : 
    5966             :                 }
    5967      131759 :                 break;
    5968             : #ifdef HAVE_IPV6
    5969       49464 :                 case AF_INET6:
    5970       43968 :                 {
    5971             :                         union {
    5972             :                                 struct sockaddr *sa;
    5973             :                                 struct sockaddr_in6 *in6;
    5974             :                         } addr;
    5975             : 
    5976       49464 :                         addr.sa = ai->ai_addr;
    5977             : 
    5978       49464 :                         memset(addr.in6, 0, sizeof(struct sockaddr_in6));
    5979             : 
    5980       49464 :                         addr.in6->sin6_port = htons(port);
    5981       49464 :                         addr.in6->sin6_family = AF_INET6;
    5982             : 
    5983       93432 :                         memcpy(&addr.in6->sin6_addr,
    5984       49464 :                                he->h_addr_list[0],
    5985       49464 :                                he->h_length);
    5986             :                 }
    5987       49464 :                 break;
    5988             : #endif
    5989             :         }
    5990             : 
    5991      181223 :         ai->ai_next = NULL;
    5992             : 
    5993      181223 :         if (he->h_name && !skip_canonname) {
    5994      174084 :                 ai->ai_canonname = strdup(he->h_name);
    5995      174084 :                 if (ai->ai_canonname == NULL) {
    5996           0 :                         freeaddrinfo(ai);
    5997           0 :                         return EAI_MEMORY;
    5998             :                 }
    5999             :         }
    6000             : 
    6001      181223 :         *pai = ai;
    6002      181223 :         return 0;
    6003             : }
    6004             : 
    6005      633619 : static int nwrap_getaddrinfo(const char *node,
    6006             :                              const char *service,
    6007             :                              const struct addrinfo *hints,
    6008             :                              struct addrinfo **res)
    6009             : {
    6010      633619 :         struct addrinfo *ai = NULL;
    6011      633619 :         unsigned short port = 0;
    6012             :         struct {
    6013             :                 int family;
    6014             :                 union {
    6015             :                         struct in_addr v4;
    6016             : #ifdef HAVE_IPV6
    6017             :                         struct in6_addr v6;
    6018             :                 } in;
    6019             : #endif
    6020      633619 :         } addr = {
    6021             :                 .family = AF_UNSPEC,
    6022             :         };
    6023             :         int rc;
    6024             : 
    6025      633619 :         if (node == NULL && service == NULL) {
    6026           0 :                 return EAI_NONAME;
    6027             :         }
    6028             : 
    6029      633619 :         if (hints == NULL) {
    6030           0 :                 hints = &default_hints;
    6031             :         }
    6032             : 
    6033             :         /* EAI_BADFLAGS
    6034             :               hints.ai_flags   contains   invalid  flags;  or,  hints.ai_flags
    6035             :               included AI_CANONNAME and name was NULL.
    6036             :         */
    6037      633619 :         if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
    6038           0 :                 return EAI_BADFLAGS;
    6039             :         }
    6040             : 
    6041             :         /* If no node has been specified, let glibc deal with it */
    6042      633619 :         if (node == NULL) {
    6043             :                 int ret;
    6044           0 :                 struct addrinfo *p = NULL;
    6045             : 
    6046           0 :                 ret = libc_getaddrinfo(node, service, hints, &p);
    6047             : 
    6048           0 :                 if (ret == 0) {
    6049           0 :                         *res = p;
    6050             :                 }
    6051           0 :                 return ret;
    6052             :         }
    6053             : 
    6054      633619 :         if (service != NULL && service[0] != '\0') {
    6055      105835 :                 const char *proto = NULL;
    6056             :                 struct servent *s;
    6057             :                 char *end_ptr;
    6058             :                 long sl;
    6059             : 
    6060      105835 :                 errno = 0;
    6061      105835 :                 sl = strtol(service, &end_ptr, 10);
    6062             : 
    6063      105835 :                 if (*end_ptr == '\0') {
    6064      105835 :                         port = sl;
    6065      105835 :                         goto valid_port;
    6066           0 :                 } else if (hints->ai_flags & AI_NUMERICSERV) {
    6067           0 :                         return EAI_NONAME;
    6068             :                 }
    6069             : 
    6070           0 :                 if (hints->ai_protocol != 0) {
    6071             :                         struct protoent *pent;
    6072             : 
    6073           0 :                         pent = getprotobynumber(hints->ai_protocol);
    6074           0 :                         if (pent != NULL) {
    6075           0 :                                 proto = pent->p_name;
    6076             :                         }
    6077             :                 }
    6078             : 
    6079           0 :                 s = getservbyname(service, proto);
    6080           0 :                 if (s == NULL) {
    6081           0 :                         return EAI_NONAME;
    6082             :                 }
    6083           0 :                 port = ntohs(s->s_port);
    6084             :         }
    6085             : 
    6086      527784 : valid_port:
    6087             : 
    6088      633619 :         rc = inet_pton(AF_INET, node, &addr.in.v4);
    6089      633619 :         if (rc == 1) {
    6090      481955 :                 addr.family = AF_INET;
    6091             :         }
    6092             : #ifdef HAVE_IPV6
    6093      633619 :         if (addr.family == AF_UNSPEC) {
    6094      151664 :                 rc = inet_pton(AF_INET6, node, &addr.in.v6);
    6095      151664 :                 if (rc == 1) {
    6096      129836 :                         addr.family = AF_INET6;
    6097             :                 }
    6098             :         }
    6099             : #endif
    6100             : 
    6101      633619 :         if (addr.family == AF_UNSPEC) {
    6102       21828 :                if (hints->ai_flags & AI_NUMERICHOST) {
    6103        7666 :                         return EAI_NONAME;
    6104             :                 }
    6105      625129 :         } else if ((hints->ai_family != AF_UNSPEC) &&
    6106       13866 :                    (hints->ai_family != addr.family))
    6107             :         {
    6108           0 :                 return EAI_ADDRFAMILY;
    6109             :         }
    6110             : 
    6111      625953 :         rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
    6112      625953 :         if (rc != 0) {
    6113             :                 int ret;
    6114      451869 :                 struct addrinfo *p = NULL;
    6115             : 
    6116      451869 :                 ret = libc_getaddrinfo(node, service, hints, &p);
    6117             : 
    6118      451869 :                 if (ret == 0) {
    6119             :                         /*
    6120             :                          * nwrap_files_getaddrinfo failed, but libc was
    6121             :                          * successful -- use the result from libc.
    6122             :                          */
    6123      444856 :                         *res = p;
    6124      444856 :                         return 0;
    6125             :                 }
    6126             : 
    6127        7013 :                 return rc;
    6128             :         }
    6129             : 
    6130             :         /*
    6131             :          * If the socktype was not specified, duplicate
    6132             :          * each ai returned, so that we have variants for
    6133             :          * both UDP and TCP.
    6134             :          */
    6135      174084 :         if (hints->ai_socktype == 0) {
    6136             :                 struct addrinfo *ai_cur;
    6137             : 
    6138             :                 /* freeaddrinfo() frees ai_canonname and ai so allocate them */
    6139         291 :                 for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
    6140             :                         struct addrinfo *ai_new;
    6141             : 
    6142             :                         /* duplicate the current entry */
    6143             : 
    6144         194 :                         ai_new = malloc(sizeof(struct addrinfo));
    6145         194 :                         if (ai_new == NULL) {
    6146           0 :                                 freeaddrinfo(ai);
    6147           0 :                                 return EAI_MEMORY;
    6148             :                         }
    6149             : 
    6150         194 :                         memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
    6151         194 :                         ai_new->ai_next = NULL;
    6152             : 
    6153             :                         /* We need a deep copy or freeaddrinfo() will blow up */
    6154         194 :                         if (ai_cur->ai_canonname != NULL) {
    6155          97 :                                 ai_new->ai_canonname =
    6156          97 :                                         strdup(ai_cur->ai_canonname);
    6157             :                         }
    6158             : 
    6159         194 :                         if (ai_cur->ai_socktype == SOCK_DGRAM) {
    6160         194 :                                 ai_new->ai_socktype = SOCK_STREAM;
    6161           0 :                         } else if (ai_cur->ai_socktype == SOCK_STREAM) {
    6162           0 :                                 ai_new->ai_socktype = SOCK_DGRAM;
    6163             :                         }
    6164         194 :                         if (ai_cur->ai_protocol == IPPROTO_TCP) {
    6165           0 :                                 ai_new->ai_protocol = IPPROTO_UDP;
    6166         194 :                         } else if (ai_cur->ai_protocol == IPPROTO_UDP) {
    6167         194 :                                 ai_new->ai_protocol = IPPROTO_TCP;
    6168             :                         }
    6169             : 
    6170             :                         /* now insert the new entry */
    6171             : 
    6172         194 :                         ai_new->ai_next = ai_cur->ai_next;
    6173         194 :                         ai_cur->ai_next = ai_new;
    6174             : 
    6175             :                         /* and move on (don't duplicate the new entry) */
    6176             : 
    6177         194 :                         ai_cur = ai_new;
    6178             :                 }
    6179             :         }
    6180             : 
    6181      174084 :         *res = ai;
    6182             : 
    6183      174084 :         return 0;
    6184             : }
    6185             : 
    6186             : int getaddrinfo(const char *node, const char *service,
    6187             :                 const struct addrinfo *hints,
    6188             :                 struct addrinfo **res)
    6189             : {
    6190      675768 :         if (!nss_wrapper_hosts_enabled()) {
    6191       42149 :                 return libc_getaddrinfo(node, service, hints, res);
    6192             :         }
    6193             : 
    6194      633619 :         return nwrap_getaddrinfo(node, service, hints, res);
    6195             : }
    6196             : 
    6197     1403416 : static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6198             :                              char *host, size_t hostlen,
    6199             :                              char *serv, size_t servlen,
    6200             :                              int flags)
    6201             : {
    6202             :         struct hostent *he;
    6203             :         struct servent *service;
    6204             :         const char *proto;
    6205             :         const void *addr;
    6206             :         socklen_t addrlen;
    6207             :         uint16_t port;
    6208             :         sa_family_t type;
    6209             :         size_t i;
    6210             : 
    6211     1403416 :         if (sa == NULL || salen < sizeof(sa_family_t)) {
    6212           0 :                 return EAI_FAMILY;
    6213             :         }
    6214             : 
    6215     1403416 :         if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
    6216           0 :                 return EAI_NONAME;
    6217             :         }
    6218             : 
    6219     1403416 :         type = sa->sa_family;
    6220     1403416 :         switch (type) {
    6221     1115822 :         case AF_INET: {
    6222             :                 union {
    6223             :                         const struct sockaddr *sa;
    6224             :                         const struct sockaddr_in *in;
    6225             :                 } a;
    6226             : 
    6227     1115822 :                 if (salen < sizeof(struct sockaddr_in)) {
    6228           0 :                         return EAI_FAMILY;
    6229             :                 }
    6230             : 
    6231     1115822 :                 a.sa = sa;
    6232             : 
    6233     1115822 :                 addr = &(a.in->sin_addr);
    6234     1115822 :                 addrlen = sizeof(a.in->sin_addr);
    6235     1115822 :                 port = ntohs(a.in->sin_port);
    6236     1115822 :                 break;
    6237             :         }
    6238             : #ifdef HAVE_IPV6
    6239      287586 :         case AF_INET6: {
    6240             :                 union {
    6241             :                         const struct sockaddr *sa;
    6242             :                         const struct sockaddr_in6 *in6;
    6243             :                 } a;
    6244             : 
    6245      287586 :                 if (salen < sizeof(struct sockaddr_in6)) {
    6246           0 :                         return EAI_FAMILY;
    6247             :                 }
    6248             : 
    6249      287586 :                 a.sa = sa;
    6250             : 
    6251      287586 :                 addr = &(a.in6->sin6_addr);
    6252      287586 :                 addrlen = sizeof(a.in6->sin6_addr);
    6253      287586 :                 port = ntohs(a.in6->sin6_port);
    6254      287586 :                 break;
    6255             :         }
    6256             : #endif
    6257           8 :         default:
    6258           8 :                 return EAI_FAMILY;
    6259             :         }
    6260             : 
    6261     1403408 :         if (host != NULL) {
    6262     1403408 :                 he = NULL;
    6263     1403408 :                 if ((flags & NI_NUMERICHOST) == 0) {
    6264          97 :                         for (i=0; i < nwrap_main_global->num_backends; i++) {
    6265          97 :                                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    6266          97 :                                 he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type);
    6267          97 :                                 if (he != NULL) {
    6268          97 :                                         break;
    6269             :                                 }
    6270             :                         }
    6271          97 :                         if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
    6272           0 :                                 return EAI_NONAME;
    6273             :                 }
    6274     1403408 :                 if (he != NULL && he->h_name != NULL) {
    6275          97 :                         if (strlen(he->h_name) >= hostlen)
    6276           0 :                                 return EAI_OVERFLOW;
    6277          97 :                         snprintf(host, hostlen, "%s", he->h_name);
    6278          97 :                         if (flags & NI_NOFQDN)
    6279           0 :                                 host[strcspn(host, ".")] = '\0';
    6280             :                 } else {
    6281     1403311 :                         if (inet_ntop(type, addr, host, hostlen) == NULL)
    6282           0 :                                 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
    6283             :                 }
    6284             :         }
    6285             : 
    6286     1403408 :         if (serv != NULL) {
    6287        4498 :                 service = NULL;
    6288        4498 :                 if ((flags & NI_NUMERICSERV) == 0) {
    6289          16 :                         proto = (flags & NI_DGRAM) ? "udp" : "tcp";
    6290          16 :                         service = getservbyport(htons(port), proto);
    6291             :                 }
    6292        4498 :                 if (service != NULL) {
    6293          16 :                         if (strlen(service->s_name) >= servlen)
    6294           0 :                                 return EAI_OVERFLOW;
    6295          16 :                         snprintf(serv, servlen, "%s", service->s_name);
    6296             :                 } else {
    6297        4482 :                         if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
    6298           0 :                                 return EAI_OVERFLOW;
    6299             :                 }
    6300             :         }
    6301             : 
    6302     1403408 :         return 0;
    6303             : }
    6304             : 
    6305             : #ifdef HAVE_LINUX_GETNAMEINFO
    6306             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6307             :                 char *host, socklen_t hostlen,
    6308             :                 char *serv, socklen_t servlen,
    6309             :                 int flags)
    6310             : #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
    6311             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6312             :                 char *host, socklen_t hostlen,
    6313             :                 char *serv, socklen_t servlen,
    6314             :                 unsigned int flags)
    6315             : #else
    6316             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6317             :                 char *host, size_t hostlen,
    6318             :                 char *serv, size_t servlen,
    6319             :                 int flags)
    6320             : #endif
    6321             : {
    6322     1469848 :         if (!nss_wrapper_hosts_enabled()) {
    6323       66432 :                 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
    6324             :         }
    6325             : 
    6326     1403416 :         return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
    6327             : }
    6328             : 
    6329       25243 : static int nwrap_gethostname(char *name, size_t len)
    6330             : {
    6331       25243 :         const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
    6332             : 
    6333       25243 :         if (strlen(hostname) >= len) {
    6334           0 :                 errno = ENAMETOOLONG;
    6335           0 :                 return -1;
    6336             :         }
    6337       25243 :         snprintf(name, len, "%s", hostname);
    6338             : 
    6339       25243 :         return 0;
    6340             : }
    6341             : 
    6342             : #ifdef HAVE_SOLARIS_GETHOSTNAME
    6343             : int gethostname(char *name, int len)
    6344             : #else /* HAVE_SOLARIS_GETHOSTNAME */
    6345             : int gethostname(char *name, size_t len)
    6346             : #endif /* HAVE_SOLARIS_GETHOSTNAME */
    6347             : {
    6348       32423 :         if (!nwrap_hostname_enabled()) {
    6349        7180 :                 return libc_gethostname(name, len);
    6350             :         }
    6351             : 
    6352       25243 :         return nwrap_gethostname(name, len);
    6353             : }
    6354             : 
    6355             : /****************************
    6356             :  * CONSTRUCTOR
    6357             :  ***************************/
    6358       57816 : void nwrap_constructor(void)
    6359             : {
    6360             :         /*
    6361             :          * If we hold a lock and the application forks, then the child
    6362             :          * is not able to unlock the mutex and we are in a deadlock.
    6363             :          *
    6364             :          * Setting these handlers should prevent such deadlocks.
    6365             :          */
    6366       57816 :         pthread_atfork(&nwrap_thread_prepare,
    6367             :                        &nwrap_thread_parent,
    6368             :                        &nwrap_thread_child);
    6369             : 
    6370             :         /* Do not call nwrap_init() here. */
    6371       57816 : }
    6372             : 
    6373             : /****************************
    6374             :  * DESTRUCTOR
    6375             :  ***************************/
    6376             : 
    6377             : /*
    6378             :  * This function is called when the library is unloaded and makes sure that
    6379             :  * sockets get closed and the unix file for the socket are unlinked.
    6380             :  */
    6381       76865 : void nwrap_destructor(void)
    6382             : {
    6383             :         size_t i;
    6384             : 
    6385       76865 :         NWRAP_LOCK_ALL;
    6386       76865 :         if (nwrap_main_global != NULL) {
    6387       38758 :                 struct nwrap_main *m = nwrap_main_global;
    6388             : 
    6389             :                 /* libc */
    6390       38758 :                 if (m->libc != NULL) {
    6391       38758 :                         if (m->libc->handle != NULL) {
    6392       25496 :                                 dlclose(m->libc->handle);
    6393             :                         }
    6394       38758 :                         if (m->libc->nsl_handle != NULL) {
    6395        6145 :                                 dlclose(m->libc->nsl_handle);
    6396             :                         }
    6397       38758 :                         if (m->libc->sock_handle != NULL) {
    6398           0 :                                 dlclose(m->libc->sock_handle);
    6399             :                         }
    6400       38758 :                         SAFE_FREE(m->libc);
    6401             :                 }
    6402             : 
    6403             :                 /* backends */
    6404       38758 :                 if (m->backends != NULL) {
    6405      108315 :                         for (i = 0; i < m->num_backends; i++) {
    6406       69557 :                                 struct nwrap_backend *b = &(m->backends[i]);
    6407             : 
    6408       69557 :                                 if (b->so_handle != NULL) {
    6409       30799 :                                         dlclose(b->so_handle);
    6410             :                                 }
    6411       69557 :                                 SAFE_FREE(b->symbols);
    6412             :                         }
    6413       38758 :                         SAFE_FREE(m->backends);
    6414             :                 }
    6415             :         }
    6416             : 
    6417       76865 :         if (nwrap_pw_global.cache != NULL) {
    6418       38758 :                 struct nwrap_cache *c = nwrap_pw_global.cache;
    6419             : 
    6420       38758 :                 nwrap_files_cache_unload(c);
    6421       38758 :                 if (c->fd >= 0) {
    6422       14834 :                         fclose(c->fp);
    6423       14834 :                         c->fd = -1;
    6424             :                 }
    6425             : 
    6426       38758 :                 SAFE_FREE(nwrap_pw_global.list);
    6427       38758 :                 nwrap_pw_global.num = 0;
    6428             :         }
    6429             : 
    6430       76865 :         if (nwrap_gr_global.cache != NULL) {
    6431       38758 :                 struct nwrap_cache *c = nwrap_gr_global.cache;
    6432             : 
    6433       38758 :                 nwrap_files_cache_unload(c);
    6434       38758 :                 if (c->fd >= 0) {
    6435        5711 :                         fclose(c->fp);
    6436        5711 :                         c->fd = -1;
    6437             :                 }
    6438             : 
    6439       38758 :                 SAFE_FREE(nwrap_gr_global.list);
    6440       38758 :                 nwrap_pw_global.num = 0;
    6441             :         }
    6442             : 
    6443             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    6444       76865 :         if (nwrap_sp_global.cache != NULL) {
    6445       38758 :                 struct nwrap_cache *c = nwrap_sp_global.cache;
    6446             : 
    6447       38758 :                 nwrap_files_cache_unload(c);
    6448       38758 :                 if (c->fd >= 0) {
    6449           0 :                         fclose(c->fp);
    6450           0 :                         c->fd = -1;
    6451             :                 }
    6452             : 
    6453       38758 :                 nwrap_sp_global.num = 0;
    6454             :         }
    6455             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    6456             : 
    6457       76865 :         if (nwrap_he_global.cache != NULL) {
    6458       38758 :                 struct nwrap_cache *c = nwrap_he_global.cache;
    6459             : 
    6460       38758 :                 nwrap_files_cache_unload(c);
    6461       38758 :                 if (c->fd >= 0) {
    6462       25154 :                         fclose(c->fp);
    6463       25154 :                         c->fd = -1;
    6464             :                 }
    6465             : 
    6466       38758 :                 nwrap_he_global.num = 0;
    6467             :         }
    6468             : 
    6469       76865 :         free(user_addrlist.items);
    6470             : #ifdef HAVE_GETHOSTBYNAME2
    6471       76865 :         free(user_addrlist2.items);
    6472             : #endif
    6473             : 
    6474       76865 :         hdestroy();
    6475       76865 :         NWRAP_UNLOCK_ALL;
    6476       76865 : }

Generated by: LCOV version 1.13