LCOV - code coverage report
Current view: top level - third_party/nss_wrapper - nss_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 1436 2340 61.4 %
Date: 2021-08-25 13:27:56 Functions: 114 157 72.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      849641 : static void nwrap_thread_prepare(void)
     230             : {
     231      849641 :         nwrap_init();
     232      849641 :         NWRAP_LOCK_ALL;
     233      849641 : }
     234             : 
     235      797982 : static void nwrap_thread_parent(void)
     236             : {
     237      797982 :         NWRAP_UNLOCK_ALL;
     238      797982 : }
     239             : 
     240       51659 : static void nwrap_thread_child(void)
     241             : {
     242       51659 :         NWRAP_UNLOCK_ALL;
     243       51659 : }
     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    10907864 : static const char *getprogname(void)
     254             : {
     255             : #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
     256    10979158 :         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    10979158 : 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    10979158 :         unsigned int lvl = 0;
     276    10979158 :         const char *prefix = "NWRAP";
     277    10979158 :         const char *progname = getprogname();
     278             : 
     279    10979158 :         d = getenv("NSS_WRAPPER_DEBUGLEVEL");
     280    10979158 :         if (d != NULL) {
     281           0 :                 lvl = atoi(d);
     282             :         }
     283             : 
     284    10979158 :         if (lvl < dbglvl) {
     285    10979158 :                 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      319101 : static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
     895             : {
     896      319101 :         if (vector == NULL) {
     897           0 :                 return false;
     898             :         }
     899             : 
     900             :         /* count is initialized by ZERO_STRUCTP */
     901      318535 :         ZERO_STRUCTP(vector);
     902      319101 :         vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     903      319101 :         if (vector->items == NULL) {
     904           0 :                 return false;
     905             :         }
     906      319101 :         vector->capacity = DEFAULT_VECTOR_CAPACITY;
     907      319667 :         memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     908             : 
     909      319101 :         return true;
     910             : }
     911             : 
     912     1575736 : static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
     913             : {
     914     1575736 :         assert (vector != NULL);
     915             : 
     916     1575736 :         if (vector->items == NULL) {
     917      318941 :                 nwrap_vector_init(vector);
     918             :         }
     919             : 
     920     1575736 :         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       21269 :                 void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
     925       21269 :                 if (items == NULL) {
     926           0 :                         return false;
     927             :                 }
     928       21269 :                 vector->items = items;
     929             : 
     930             :                 /* Don't count ending NULL to capacity */
     931       21269 :                 vector->capacity *= 2;
     932             :         }
     933             : 
     934     1575736 :         vector->items[vector->count] = item;
     935             : 
     936     1575736 :         vector->count += 1;
     937     1575736 :         vector->items[vector->count] = NULL;
     938             : 
     939     1575736 :         return true;
     940             : }
     941             : 
     942         160 : static bool nwrap_vector_merge(struct nwrap_vector *dst,
     943             :                                struct nwrap_vector *src)
     944             : {
     945         160 :         void **dst_items = NULL;
     946             :         size_t count;
     947             : 
     948         160 :         if (src->count == 0) {
     949           0 :                 return true;
     950             :         }
     951             : 
     952         160 :         count = dst->count + src->count;
     953             : 
     954             :         /* We don't need reallocation if we have enough capacity. */
     955         160 :         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         320 :         memcpy((void *)(((long *)dst->items) + dst->count),
     965         160 :                src->items,
     966         160 :                src->count * sizeof(void *));
     967         160 :         dst->count = count;
     968             : 
     969         160 :         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             : void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE;
    1074             : void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
    1075             : 
    1076             : /*********************************************************
    1077             :  * NWRAP LIBC LOADER FUNCTIONS
    1078             :  *********************************************************/
    1079             : 
    1080             : enum nwrap_lib {
    1081             :     NWRAP_LIBC,
    1082             :     NWRAP_LIBNSL,
    1083             :     NWRAP_LIBSOCKET,
    1084             : };
    1085             : 
    1086       27521 : static const char *nwrap_str_lib(enum nwrap_lib lib)
    1087             : {
    1088       28614 :         switch (lib) {
    1089         130 :         case NWRAP_LIBC:
    1090         130 :                 return "libc";
    1091        7854 :         case NWRAP_LIBNSL:
    1092        7252 :                 return "libnsl";
    1093       20374 :         case NWRAP_LIBSOCKET:
    1094       20139 :                 return "libsocket";
    1095             :         }
    1096             : 
    1097             :         /* Compiler would warn us about unhandled enum value if we get here */
    1098           0 :         return "unknown";
    1099             : }
    1100             : 
    1101       28614 : static void *nwrap_load_lib_handle(enum nwrap_lib lib)
    1102             : {
    1103       28614 :         int flags = RTLD_LAZY;
    1104       28614 :         void *handle = NULL;
    1105             :         int i;
    1106             : 
    1107             : #ifdef RTLD_DEEPBIND
    1108       28614 :         const char *env_preload = getenv("LD_PRELOAD");
    1109       28614 :         const char *env_deepbind = getenv("NSS_WRAPPER_DISABLE_DEEPBIND");
    1110       28614 :         bool enable_deepbind = true;
    1111             : 
    1112             :         /* Don't do a deepbind if we run with libasan */
    1113       28614 :         if (env_preload != NULL && strlen(env_preload) < 1024) {
    1114       28614 :                 const char *p = strstr(env_preload, "libasan.so");
    1115       28614 :                 if (p != NULL) {
    1116           0 :                         enable_deepbind = false;
    1117             :                 }
    1118             :         }
    1119             : 
    1120       28614 :         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
    1121           0 :                 enable_deepbind = false;
    1122             :         }
    1123             : 
    1124       28614 :         if (enable_deepbind) {
    1125       28614 :                 flags |= RTLD_DEEPBIND;
    1126             :         }
    1127             : #endif
    1128             : 
    1129       28614 :         switch (lib) {
    1130        7854 :         case NWRAP_LIBNSL:
    1131             : #ifdef HAVE_LIBNSL
    1132        7854 :                 handle = nwrap_main_global->libc->nsl_handle;
    1133        7854 :                 if (handle == NULL) {
    1134       77908 :                         for (i = 10; i >= 0; i--) {
    1135       78510 :                                 char soname[256] = {0};
    1136             : 
    1137       78510 :                                 snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
    1138       78510 :                                 handle = dlopen(soname, flags);
    1139       78510 :                                 if (handle != NULL) {
    1140        7249 :                                         break;
    1141             :                                 }
    1142             :                         }
    1143             : 
    1144        7851 :                         nwrap_main_global->libc->nsl_handle = handle;
    1145             :                 }
    1146        7252 :                 break;
    1147             : #endif
    1148             :                 /* FALL TROUGH */
    1149       20760 :         case NWRAP_LIBSOCKET:
    1150             : #ifdef HAVE_LIBSOCKET
    1151             :                 handle = nwrap_main_global->libc->sock_handle;
    1152             :                 if (handle == NULL) {
    1153             :                         for (i = 10; i >= 0; i--) {
    1154             :                                 char soname[256] = {0};
    1155             : 
    1156             :                                 snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
    1157             :                                 handle = dlopen(soname, flags);
    1158             :                                 if (handle != NULL) {
    1159             :                                         break;
    1160             :                                 }
    1161             :                         }
    1162             : 
    1163             :                         nwrap_main_global->libc->sock_handle = handle;
    1164             :                 }
    1165             :                 break;
    1166             : #endif
    1167             :                 /* FALL TROUGH */
    1168             :         case NWRAP_LIBC:
    1169       20760 :                 handle = nwrap_main_global->libc->handle;
    1170       20760 :                 if (handle == NULL) {
    1171       94801 :                         for (i = 10; i >= 0; i--) {
    1172       95080 :                                 char soname[256] = {0};
    1173             : 
    1174       95080 :                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
    1175       95080 :                                 handle = dlopen(soname, flags);
    1176       95080 :                                 if (handle != NULL) {
    1177       18737 :                                         break;
    1178             :                                 }
    1179             :                         }
    1180             : 
    1181       19016 :                         nwrap_main_global->libc->handle = handle;
    1182             :                 }
    1183       20269 :                 break;
    1184             :         }
    1185             : 
    1186       28614 :         if (handle == NULL) {
    1187             : #ifdef RTLD_NEXT
    1188           0 :                 handle = nwrap_main_global->libc->handle
    1189           0 :                        = nwrap_main_global->libc->sock_handle
    1190           0 :                        = nwrap_main_global->libc->nsl_handle
    1191           0 :                        = RTLD_NEXT;
    1192             : #else
    1193             :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1194             :                           "Failed to dlopen library: %s\n",
    1195             :                           dlerror());
    1196             :                 exit(-1);
    1197             : #endif
    1198             :         }
    1199             : 
    1200       28614 :         return handle;
    1201             : }
    1202             : 
    1203       28614 : static void *_nwrap_bind_symbol(enum nwrap_lib lib, const char *fn_name)
    1204             : {
    1205             :         void *handle;
    1206             :         void *func;
    1207             : 
    1208       28614 :         nwrap_init();
    1209             : 
    1210       28614 :         handle = nwrap_load_lib_handle(lib);
    1211             : 
    1212       28614 :         func = dlsym(handle, fn_name);
    1213       28614 :         if (func == NULL) {
    1214           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1215             :                                 "Failed to find %s: %s\n",
    1216             :                                 fn_name, dlerror());
    1217           0 :                 exit(-1);
    1218             :         }
    1219             : 
    1220       28614 :         NWRAP_LOG(NWRAP_LOG_TRACE,
    1221             :                         "Loaded %s from %s",
    1222             :                         fn_name, nwrap_str_lib(lib));
    1223       28614 :         return func;
    1224             : }
    1225             : 
    1226             : #define nwrap_bind_symbol_libc(sym_name) \
    1227             :         NWRAP_LOCK(libc_symbol_binding); \
    1228             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1229             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1230             :                         _nwrap_bind_symbol(NWRAP_LIBC, #sym_name); \
    1231             :         } \
    1232             :         NWRAP_UNLOCK(libc_symbol_binding)
    1233             : 
    1234             : #define nwrap_bind_symbol_libc_posix(sym_name) \
    1235             :         NWRAP_LOCK(libc_symbol_binding); \
    1236             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1237             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1238             :                         _nwrap_bind_symbol(NWRAP_LIBC, "__posix_" #sym_name); \
    1239             :         } \
    1240             :         NWRAP_UNLOCK(libc_symbol_binding)
    1241             : 
    1242             : #define nwrap_bind_symbol_libnsl(sym_name) \
    1243             :         NWRAP_LOCK(libc_symbol_binding); \
    1244             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1245             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1246             :                         _nwrap_bind_symbol(NWRAP_LIBNSL, #sym_name); \
    1247             :         } \
    1248             :         NWRAP_UNLOCK(libc_symbol_binding)
    1249             : 
    1250             : #define nwrap_bind_symbol_libsocket(sym_name) \
    1251             :         NWRAP_LOCK(libc_symbol_binding); \
    1252             :         if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \
    1253             :                 nwrap_main_global->libc->symbols._libc_##sym_name.obj = \
    1254             :                         _nwrap_bind_symbol(NWRAP_LIBSOCKET, #sym_name); \
    1255             :         } \
    1256             :         NWRAP_UNLOCK(libc_symbol_binding)
    1257             : 
    1258             : /* INTERNAL HELPER FUNCTIONS */
    1259      350587 : static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
    1260             : {
    1261             :         size_t p;
    1262             :         void *item;
    1263     1961192 :         nwrap_vector_foreach(item, nwrap->lines, p) {
    1264             :                 /* Maybe some vectors were merged ... */
    1265     1610605 :                 SAFE_FREE(item);
    1266             :         }
    1267      350587 :         SAFE_FREE(nwrap->lines.items);
    1268      350587 :         ZERO_STRUCTP(&nwrap->lines);
    1269      350587 : }
    1270             : 
    1271             : /*
    1272             :  * IMPORTANT
    1273             :  *
    1274             :  * Functions expeciall from libc need to be loaded individually, you can't load
    1275             :  * all at once or gdb will segfault at startup. The same applies to valgrind and
    1276             :  * has probably something todo with with the linker.
    1277             :  * So we need load each function at the point it is called the first time.
    1278             :  */
    1279        1106 : static struct passwd *libc_getpwnam(const char *name)
    1280             : {
    1281        1106 :         nwrap_bind_symbol_libc(getpwnam);
    1282             : 
    1283        1106 :         return nwrap_main_global->libc->symbols._libc_getpwnam.f(name);
    1284             : }
    1285             : 
    1286             : #ifdef HAVE_GETPWNAM_R
    1287           0 : static int libc_getpwnam_r(const char *name,
    1288             :                            struct passwd *pwd,
    1289             :                            char *buf,
    1290             :                            size_t buflen,
    1291             :                            struct passwd **result)
    1292             : {
    1293             : #ifdef HAVE___POSIX_GETPWNAM_R
    1294             :         nwrap_bind_symbol_libc_posix(getpwnam_r);
    1295             : #else
    1296           0 :         nwrap_bind_symbol_libc(getpwnam_r);
    1297             : #endif
    1298             : 
    1299           0 :         return nwrap_main_global->libc->symbols._libc_getpwnam_r.f(name,
    1300             :                                                                    pwd,
    1301             :                                                                    buf,
    1302             :                                                                    buflen,
    1303             :                                                                    result);
    1304             : }
    1305             : #endif
    1306             : 
    1307         417 : static struct passwd *libc_getpwuid(uid_t uid)
    1308             : {
    1309         417 :         nwrap_bind_symbol_libc(getpwuid);
    1310             : 
    1311         417 :         return nwrap_main_global->libc->symbols._libc_getpwuid.f(uid);
    1312             : }
    1313             : 
    1314             : #ifdef HAVE_GETPWUID_R
    1315           3 : static int libc_getpwuid_r(uid_t uid,
    1316             :                            struct passwd *pwd,
    1317             :                            char *buf,
    1318             :                            size_t buflen,
    1319             :                            struct passwd **result)
    1320             : {
    1321             : #ifdef HAVE___POSIX_GETPWUID_R
    1322             :         nwrap_bind_symbol_libc_posix(getpwuid_r);
    1323             : #else
    1324           3 :         nwrap_bind_symbol_libc(getpwuid_r);
    1325             : #endif
    1326             : 
    1327           3 :         return nwrap_main_global->libc->symbols._libc_getpwuid_r.f(uid,
    1328             :                                                                    pwd,
    1329             :                                                                    buf,
    1330             :                                                                    buflen,
    1331             :                                                                    result);
    1332             : }
    1333             : #endif
    1334             : 
    1335     1367549 : static inline void str_tolower(char *dst, char *src)
    1336             : {
    1337     1367549 :         register char *src_tmp = src;
    1338     1367549 :         register char *dst_tmp = dst;
    1339             : 
    1340    26066914 :         while (*src_tmp != '\0') {
    1341    23331816 :                 *dst_tmp = tolower(*src_tmp);
    1342    23331816 :                 ++src_tmp;
    1343    23331816 :                 ++dst_tmp;
    1344             :         }
    1345     1367549 : }
    1346             : 
    1347      923415 : static bool str_tolower_copy(char **dst_name, const char *const src_name)
    1348             : {
    1349             :         char *h_name_lower;
    1350             : 
    1351      923415 :         if ((dst_name == NULL) || (src_name == NULL)) {
    1352           0 :                 return false;
    1353             :         }
    1354             : 
    1355      923415 :         h_name_lower = strdup(src_name);
    1356      923415 :         if (h_name_lower == NULL) {
    1357           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
    1358           0 :                 return false;
    1359             :         }
    1360             : 
    1361      923415 :         str_tolower(h_name_lower, h_name_lower);
    1362      923415 :         *dst_name = h_name_lower;
    1363      923415 :         return true;
    1364             : }
    1365             : 
    1366           0 : static void libc_setpwent(void)
    1367             : {
    1368           0 :         nwrap_bind_symbol_libc(setpwent);
    1369             : 
    1370           0 :         nwrap_main_global->libc->symbols._libc_setpwent.f();
    1371           0 : }
    1372             : 
    1373           0 : static struct passwd *libc_getpwent(void)
    1374             : {
    1375           0 :         nwrap_bind_symbol_libc(getpwent);
    1376             : 
    1377           0 :         return nwrap_main_global->libc->symbols._libc_getpwent.f();
    1378             : }
    1379             : 
    1380             : #ifdef HAVE_GETPWENT_R
    1381             : #  ifdef HAVE_SOLARIS_GETPWENT_R
    1382             : static struct passwd *libc_getpwent_r(struct passwd *pwdst,
    1383             :                                       char *buf,
    1384             :                                       int buflen)
    1385             : {
    1386             :         nwrap_bind_symbol_libc(getpwent_r);
    1387             : 
    1388             :         return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
    1389             :                                                                    buf,
    1390             :                                                                    buflen);
    1391             : }
    1392             : #  else /* HAVE_SOLARIS_GETPWENT_R */
    1393           0 : static int libc_getpwent_r(struct passwd *pwdst,
    1394             :                            char *buf,
    1395             :                            size_t buflen,
    1396             :                            struct passwd **pwdstp)
    1397             : {
    1398           0 :         nwrap_bind_symbol_libc(getpwent_r);
    1399             : 
    1400           0 :         return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst,
    1401             :                                                                    buf,
    1402             :                                                                    buflen,
    1403             :                                                                    pwdstp);
    1404             : }
    1405             : #  endif /* HAVE_SOLARIS_GETPWENT_R */
    1406             : #endif /* HAVE_GETPWENT_R */
    1407             : 
    1408          92 : static void libc_endpwent(void)
    1409             : {
    1410          92 :         nwrap_bind_symbol_libc(endpwent);
    1411             : 
    1412          92 :         nwrap_main_global->libc->symbols._libc_endpwent.f();
    1413          92 : }
    1414             : 
    1415           0 : static int libc_initgroups(const char *user, gid_t gid)
    1416             : {
    1417           0 :         nwrap_bind_symbol_libc(initgroups);
    1418             : 
    1419           0 :         return nwrap_main_global->libc->symbols._libc_initgroups.f(user, gid);
    1420             : }
    1421             : 
    1422         193 : static struct group *libc_getgrnam(const char *name)
    1423             : {
    1424         193 :         nwrap_bind_symbol_libc(getgrnam);
    1425             : 
    1426         193 :         return nwrap_main_global->libc->symbols._libc_getgrnam.f(name);
    1427             : }
    1428             : 
    1429             : #ifdef HAVE_GETGRNAM_R
    1430           0 : static int libc_getgrnam_r(const char *name,
    1431             :                            struct group *grp,
    1432             :                            char *buf,
    1433             :                            size_t buflen,
    1434             :                            struct group **result)
    1435             : {
    1436             : #ifdef HAVE___POSIX_GETGRNAM_R
    1437             :         nwrap_bind_symbol_libc_posix(getgrnam_r);
    1438             : #else
    1439           0 :         nwrap_bind_symbol_libc(getgrnam_r);
    1440             : #endif
    1441             : 
    1442           0 :         return nwrap_main_global->libc->symbols._libc_getgrnam_r.f(name,
    1443             :                                                                    grp,
    1444             :                                                                    buf,
    1445             :                                                                    buflen,
    1446             :                                                                    result);
    1447             : }
    1448             : #endif
    1449             : 
    1450         239 : static struct group *libc_getgrgid(gid_t gid)
    1451             : {
    1452         239 :         nwrap_bind_symbol_libc(getgrgid);
    1453             : 
    1454         239 :         return nwrap_main_global->libc->symbols._libc_getgrgid.f(gid);
    1455             : }
    1456             : 
    1457             : #ifdef HAVE_GETGRGID_R
    1458           0 : static int libc_getgrgid_r(gid_t gid,
    1459             :                            struct group *grp,
    1460             :                            char *buf,
    1461             :                            size_t buflen,
    1462             :                            struct group **result)
    1463             : {
    1464             : #ifdef HAVE___POSIX_GETGRGID_R
    1465             :         if (nwrap_main_global->libc->symbols._libc_getgrgid_r == NULL) {
    1466             :                 *(void **) (&nwrap_main_global->libc->symbols._libc_getgrgid_r) =
    1467             :                         _nwrap_bind_symbol_libc("__posix_getgrgid_r");
    1468             :         }
    1469             : #else
    1470           0 :         nwrap_bind_symbol_libc(getgrgid_r);
    1471             : #endif
    1472             : 
    1473           0 :         return nwrap_main_global->libc->symbols._libc_getgrgid_r.f(gid,
    1474             :                                                                    grp,
    1475             :                                                                    buf,
    1476             :                                                                    buflen,
    1477             :                                                                    result);
    1478             : }
    1479             : #endif
    1480             : 
    1481           0 : static void libc_setgrent(void)
    1482             : {
    1483           0 :         nwrap_bind_symbol_libc(setgrent);
    1484             : 
    1485           0 :         nwrap_main_global->libc->symbols._libc_setgrent.f();
    1486           0 : }
    1487             : 
    1488           0 : static struct group *libc_getgrent(void)
    1489             : {
    1490           0 :         nwrap_bind_symbol_libc(getgrent);
    1491             : 
    1492           0 :         return nwrap_main_global->libc->symbols._libc_getgrent.f();
    1493             : }
    1494             : 
    1495             : #ifdef HAVE_GETGRENT_R
    1496             : #  ifdef HAVE_SOLARIS_GETGRENT_R
    1497             : static struct group *libc_getgrent_r(struct group *group,
    1498             :                                      char *buf,
    1499             :                                      size_t buflen)
    1500             : {
    1501             :         nwrap_bind_symbol_libc(getgrent_r);
    1502             : 
    1503             :         return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
    1504             :                                                                    buf,
    1505             :                                                                    buflen);
    1506             : }
    1507             : #  else /* HAVE_SOLARIS_GETGRENT_R */
    1508           0 : static int libc_getgrent_r(struct group *group,
    1509             :                            char *buf,
    1510             :                            size_t buflen,
    1511             :                            struct group **result)
    1512             : {
    1513           0 :         nwrap_bind_symbol_libc(getgrent_r);
    1514             : 
    1515           0 :         return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group,
    1516             :                                                                    buf,
    1517             :                                                                    buflen,
    1518             :                                                                    result);
    1519             : }
    1520             : #  endif /* HAVE_SOLARIS_GETGRENT_R */
    1521             : #endif /* HAVE_GETGRENT_R */
    1522             : 
    1523           0 : static void libc_endgrent(void)
    1524             : {
    1525           0 :         nwrap_bind_symbol_libc(endgrent);
    1526             : 
    1527           0 :         nwrap_main_global->libc->symbols._libc_endgrent.f();
    1528           0 : }
    1529             : 
    1530             : #ifdef HAVE_GETGROUPLIST
    1531           3 : static int libc_getgrouplist(const char *user,
    1532             :                              gid_t group,
    1533             :                              gid_t *groups,
    1534             :                              int *ngroups)
    1535             : {
    1536           3 :         nwrap_bind_symbol_libc(getgrouplist);
    1537             : 
    1538           3 :         return nwrap_main_global->libc->symbols._libc_getgrouplist.f(user,
    1539             :                                                                      group,
    1540             :                                                                      groups,
    1541             :                                                                      ngroups);
    1542             : }
    1543             : #endif
    1544             : 
    1545           0 : static void libc_sethostent(int stayopen)
    1546             : {
    1547           0 :         nwrap_bind_symbol_libnsl(sethostent);
    1548             : 
    1549           0 :         nwrap_main_global->libc->symbols._libc_sethostent.f(stayopen);
    1550           0 : }
    1551             : 
    1552           0 : static struct hostent *libc_gethostent(void)
    1553             : {
    1554           0 :         nwrap_bind_symbol_libnsl(gethostent);
    1555             : 
    1556           0 :         return nwrap_main_global->libc->symbols._libc_gethostent.f();
    1557             : }
    1558             : 
    1559           0 : static void libc_endhostent(void)
    1560             : {
    1561           0 :         nwrap_bind_symbol_libnsl(endhostent);
    1562             : 
    1563           0 :         nwrap_main_global->libc->symbols._libc_endhostent.f();
    1564           0 : }
    1565             : 
    1566           0 : static struct hostent *libc_gethostbyname(const char *name)
    1567             : {
    1568           0 :         nwrap_bind_symbol_libnsl(gethostbyname);
    1569             : 
    1570           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname.f(name);
    1571             : }
    1572             : 
    1573             : #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
    1574           0 : static struct hostent *libc_gethostbyname2(const char *name, int af)
    1575             : {
    1576           0 :         nwrap_bind_symbol_libnsl(gethostbyname2);
    1577             : 
    1578           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname2.f(name, af);
    1579             : }
    1580             : #endif
    1581             : 
    1582             : #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */
    1583           0 : static int libc_gethostbyname2_r(const char *name,
    1584             :                                  int af,
    1585             :                                  struct hostent *ret,
    1586             :                                  char *buf,
    1587             :                                  size_t buflen,
    1588             :                                  struct hostent **result,
    1589             :                                  int *h_errnop)
    1590             : {
    1591           0 :         nwrap_bind_symbol_libnsl(gethostbyname2_r);
    1592             : 
    1593           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyname2_r.f(name,
    1594             :                                                                          af,
    1595             :                                                                          ret,
    1596             :                                                                          buf,
    1597             :                                                                          buflen,
    1598             :                                                                          result,
    1599             :                                                                          h_errnop);
    1600             : }
    1601             : #endif
    1602             : 
    1603           0 : static struct hostent *libc_gethostbyaddr(const void *addr,
    1604             :                                           socklen_t len,
    1605             :                                           int type)
    1606             : {
    1607           0 :         nwrap_bind_symbol_libnsl(gethostbyaddr);
    1608             : 
    1609           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyaddr.f(addr,
    1610             :                                                                       len,
    1611             :                                                                       type);
    1612             : }
    1613             : 
    1614        8007 : static int libc_gethostname(char *name, size_t len)
    1615             : {
    1616        8007 :         nwrap_bind_symbol_libnsl(gethostname);
    1617             : 
    1618        8007 :         return nwrap_main_global->libc->symbols._libc_gethostname.f(name, len);
    1619             : }
    1620             : 
    1621             : #ifdef HAVE_GETHOSTBYNAME_R
    1622           3 : static int libc_gethostbyname_r(const char *name,
    1623             :                                 struct hostent *ret,
    1624             :                                 char *buf,
    1625             :                                 size_t buflen,
    1626             :                                 struct hostent **result,
    1627             :                                 int *h_errnop)
    1628             : {
    1629           3 :         nwrap_bind_symbol_libnsl(gethostbyname_r);
    1630             : 
    1631           3 :         return nwrap_main_global->libc->symbols._libc_gethostbyname_r.f(name,
    1632             :                                                                         ret,
    1633             :                                                                         buf,
    1634             :                                                                         buflen,
    1635             :                                                                         result,
    1636             :                                                                         h_errnop);
    1637             : }
    1638             : #endif
    1639             : 
    1640             : #ifdef HAVE_GETHOSTBYADDR_R
    1641           0 : static int libc_gethostbyaddr_r(const void *addr,
    1642             :                                 socklen_t len,
    1643             :                                 int type,
    1644             :                                 struct hostent *ret,
    1645             :                                 char *buf,
    1646             :                                 size_t buflen,
    1647             :                                 struct hostent **result,
    1648             :                                 int *h_errnop)
    1649             : {
    1650           0 :         nwrap_bind_symbol_libnsl(gethostbyaddr_r);
    1651             : 
    1652           0 :         return nwrap_main_global->libc->symbols._libc_gethostbyaddr_r.f(addr,
    1653             :                                                                         len,
    1654             :                                                                         type,
    1655             :                                                                         ret,
    1656             :                                                                         buf,
    1657             :                                                                         buflen,
    1658             :                                                                         result,
    1659             :                                                                         h_errnop);
    1660             : }
    1661             : #endif
    1662             : 
    1663      809037 : static int libc_getaddrinfo(const char *node,
    1664             :                             const char *service,
    1665             :                             const struct addrinfo *hints,
    1666             :                             struct addrinfo **res)
    1667             : {
    1668      809037 :         nwrap_bind_symbol_libsocket(getaddrinfo);
    1669             : 
    1670      809037 :         return nwrap_main_global->libc->symbols._libc_getaddrinfo.f(node,
    1671             :                                                                     service,
    1672             :                                                                     hints,
    1673             :                                                                     res);
    1674             : }
    1675             : 
    1676      199106 : static int libc_getnameinfo(const struct sockaddr *sa,
    1677             :                             socklen_t salen,
    1678             :                             char *host,
    1679             :                             size_t hostlen,
    1680             :                             char *serv,
    1681             :                             size_t servlen,
    1682             :                             int flags)
    1683             : {
    1684      199106 :         nwrap_bind_symbol_libsocket(getnameinfo);
    1685             : 
    1686      199106 :         return nwrap_main_global->libc->symbols._libc_getnameinfo.f(sa,
    1687             :                                                                     salen,
    1688             :                                                                     host,
    1689             :                                                                     hostlen,
    1690             :                                                                     serv,
    1691             :                                                                     servlen,
    1692             :                                                                     flags);
    1693             : }
    1694             : 
    1695             : /*********************************************************
    1696             :  * NWRAP NSS MODULE LOADER FUNCTIONS
    1697             :  *********************************************************/
    1698             : 
    1699      368641 : static void *_nwrap_bind_nss_module_symbol(struct nwrap_backend *b,
    1700             :                                            const char *fn_name)
    1701             : {
    1702      368641 :         void *res = NULL;
    1703      368641 :         char *s = NULL;
    1704             :         int rc;
    1705             : 
    1706      368641 :         if (b->so_handle == NULL) {
    1707           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
    1708           0 :                 return NULL;
    1709             :         }
    1710             : 
    1711      369538 :         rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name);
    1712      368641 :         if (rc == -1) {
    1713           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    1714           0 :                 return NULL;
    1715             :         }
    1716             : 
    1717      368641 :         res = dlsym(b->so_handle, s);
    1718      368641 :         if (res == NULL) {
    1719       56714 :                 NWRAP_LOG(NWRAP_LOG_WARN,
    1720             :                           "Cannot find function %s in %s",
    1721             :                           s, b->so_path);
    1722             :         }
    1723      368641 :         SAFE_FREE(s);
    1724      367744 :         return res;
    1725             : }
    1726             : 
    1727             : #define nwrap_nss_module_bind_symbol(sym_name) \
    1728             :         NWRAP_LOCK(nss_module_symbol_binding); \
    1729             :         if (symbols->_nss_##sym_name.obj == NULL) { \
    1730             :                 symbols->_nss_##sym_name.obj = \
    1731             :                         _nwrap_bind_nss_module_symbol(b, #sym_name); \
    1732             :         } \
    1733             :         NWRAP_UNLOCK(nss_module_symbol_binding)
    1734             : 
    1735             : #define nwrap_nss_module_bind_symbol2(sym_name, alt_name) \
    1736             :         NWRAP_LOCK(nss_module_symbol_binding); \
    1737             :         if (symbols->_nss_##sym_name.obj == NULL) { \
    1738             :                 symbols->_nss_##sym_name.obj = \
    1739             :                         _nwrap_bind_nss_module_symbol(b, #alt_name); \
    1740             :         } \
    1741             :         NWRAP_UNLOCK(nss_module_symbol_binding)
    1742             : 
    1743             : static struct nwrap_nss_module_symbols *
    1744       28357 : nwrap_bind_nss_module_symbols(struct nwrap_backend *b)
    1745             : {
    1746             :         struct nwrap_nss_module_symbols *symbols;
    1747             : 
    1748       28357 :         if (!b->so_handle) {
    1749           0 :                 return NULL;
    1750             :         }
    1751             : 
    1752       28357 :         symbols = calloc(1, sizeof(struct nwrap_nss_module_symbols));
    1753       28357 :         if (symbols == NULL) {
    1754           0 :                 return NULL;
    1755             :         }
    1756             : 
    1757       28357 :         nwrap_nss_module_bind_symbol(getpwnam_r);
    1758       28357 :         nwrap_nss_module_bind_symbol(getpwuid_r);
    1759       28357 :         nwrap_nss_module_bind_symbol(setpwent);
    1760       28357 :         nwrap_nss_module_bind_symbol(getpwent_r);
    1761       28357 :         nwrap_nss_module_bind_symbol(endpwent);
    1762       28357 :         nwrap_nss_module_bind_symbol2(initgroups, initgroups_dyn);
    1763       28357 :         nwrap_nss_module_bind_symbol(getgrnam_r);
    1764       28357 :         nwrap_nss_module_bind_symbol(getgrgid_r);
    1765       28357 :         nwrap_nss_module_bind_symbol(setgrent);
    1766       28357 :         nwrap_nss_module_bind_symbol(getgrent_r);
    1767       28357 :         nwrap_nss_module_bind_symbol(endgrent);
    1768       28357 :         nwrap_nss_module_bind_symbol(gethostbyaddr_r);
    1769       28357 :         nwrap_nss_module_bind_symbol(gethostbyname2_r);
    1770             : 
    1771       28357 :         return symbols;
    1772             : }
    1773             : 
    1774       28357 : static void *nwrap_load_module(const char *so_path)
    1775             : {
    1776             :         void *h;
    1777             : 
    1778       28357 :         if (!so_path || !strlen(so_path)) {
    1779           0 :                 return NULL;
    1780             :         }
    1781             : 
    1782       28357 :         h = dlopen(so_path, RTLD_LAZY);
    1783       28357 :         if (!h) {
    1784           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1785             :                           "Cannot open shared library %s",
    1786             :                           so_path);
    1787           0 :                 return NULL;
    1788             :         }
    1789             : 
    1790       28288 :         return h;
    1791             : }
    1792             : 
    1793       65313 : static bool nwrap_module_init(const char *name,
    1794             :                               struct nwrap_ops *ops,
    1795             :                               const char *so_path,
    1796             :                               size_t *num_backends,
    1797             :                               struct nwrap_backend **backends)
    1798             : {
    1799       65313 :         struct nwrap_backend *b = NULL;
    1800       65313 :         size_t n = *num_backends + 1;
    1801             : 
    1802       65313 :         b = realloc(*backends, sizeof(struct nwrap_backend) * n);
    1803       65313 :         if (b == NULL) {
    1804           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    1805           0 :                 return false;
    1806             :         }
    1807       65313 :         *backends = b;
    1808             : 
    1809       65313 :         b = &((*backends)[*num_backends]);
    1810             : 
    1811       65313 :         *b = (struct nwrap_backend) {
    1812             :                 .name = name,
    1813             :                 .ops = ops,
    1814             :                 .so_path = so_path,
    1815             :         };
    1816             : 
    1817       65313 :         if (so_path != NULL) {
    1818       28357 :                 b->so_handle = nwrap_load_module(so_path);
    1819       28357 :                 b->symbols = nwrap_bind_nss_module_symbols(b);
    1820       28357 :                 if (b->symbols == NULL) {
    1821           0 :                         return false;
    1822             :                 }
    1823             :         }
    1824             : 
    1825       65313 :         *num_backends = n;
    1826             : 
    1827       65313 :         return true;
    1828             : }
    1829             : 
    1830       36956 : static void nwrap_libc_init(struct nwrap_main *r)
    1831             : {
    1832       36956 :         r->libc = calloc(1, sizeof(struct nwrap_libc));
    1833       36956 :         if (r->libc == NULL) {
    1834           0 :                 printf("Failed to allocate memory for libc");
    1835           0 :                 exit(-1);
    1836             :         }
    1837       36956 : }
    1838             : 
    1839       36956 : static void nwrap_backend_init(struct nwrap_main *r)
    1840             : {
    1841       36956 :         const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
    1842       36956 :         const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
    1843             : 
    1844       36956 :         r->num_backends = 0;
    1845       36956 :         r->backends = NULL;
    1846             : 
    1847       36956 :         if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
    1848             :                                &r->num_backends,
    1849             :                                &r->backends)) {
    1850           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1851             :                           "Failed to initialize 'files' backend");
    1852           0 :                 return;
    1853             :         }
    1854             : 
    1855       65340 :         if (module_so_path != NULL &&
    1856       56741 :             module_so_path[0] != '\0' &&
    1857       28357 :             module_fn_name != NULL &&
    1858       28357 :             module_fn_name[0] != '\0') {
    1859       28357 :                 if (!nwrap_module_init(module_fn_name,
    1860             :                                        &nwrap_module_ops,
    1861             :                                        module_so_path,
    1862             :                                        &r->num_backends,
    1863             :                                        &r->backends)) {
    1864           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    1865             :                                   "Failed to initialize '%s' backend",
    1866             :                                   module_fn_name);
    1867           0 :                         return;
    1868             :                 }
    1869             :         }
    1870             : }
    1871             : 
    1872     4321850 : static void nwrap_init(void)
    1873             : {
    1874             :         const char *env;
    1875             :         char *endptr;
    1876             :         size_t max_hostents_tmp;
    1877             :         int ok;
    1878             : 
    1879     4321850 :         NWRAP_LOCK(nwrap_initialized);
    1880     4321850 :         if (nwrap_initialized) {
    1881     4284894 :                 NWRAP_UNLOCK(nwrap_initialized);
    1882     4284894 :                 return;
    1883             :         }
    1884             : 
    1885             :         /*
    1886             :          * Still holding nwrap_initialized lock here.
    1887             :          * We don't use NWRAP_(UN)LOCK_ALL macros here because we
    1888             :          * want to avoid overhead when other threads do their job.
    1889             :          */
    1890       36956 :         NWRAP_LOCK(nwrap_global);
    1891       36956 :         NWRAP_LOCK(nwrap_gr_global);
    1892       36956 :         NWRAP_LOCK(nwrap_he_global);
    1893       36956 :         NWRAP_LOCK(nwrap_pw_global);
    1894       36956 :         NWRAP_LOCK(nwrap_sp_global);
    1895             : 
    1896       36956 :         nwrap_initialized = true;
    1897             : 
    1898       36956 :         env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
    1899       36956 :         if (env != NULL) {
    1900       36956 :                 max_hostents_tmp = (size_t)strtoul(env, &endptr, 10);
    1901       73912 :                 if ((*env == '\0') ||
    1902       73912 :                     (*endptr != '\0') ||
    1903             :                     (max_hostents_tmp == 0)) {
    1904           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    1905             :                                   "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
    1906             :                                   "value or value is too small. "
    1907             :                                   "Using default value: %lu.",
    1908             :                                   (unsigned long)max_hostents);
    1909             :                 } else {
    1910       36956 :                         max_hostents = max_hostents_tmp;
    1911             :                 }
    1912             :         }
    1913             :         /* Initialize hash table */
    1914       36956 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    1915             :                   "Initializing hash table of size %lu items.",
    1916             :                   (unsigned long)max_hostents);
    1917       36956 :         ok = hcreate(max_hostents);
    1918       36956 :         if (!ok) {
    1919           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    1920             :                           "Failed to initialize hash table");
    1921           0 :                 exit(-1);
    1922             :         }
    1923             : 
    1924       36956 :         nwrap_main_global = &__nwrap_main_global;
    1925             : 
    1926       36956 :         nwrap_libc_init(nwrap_main_global);
    1927             : 
    1928       36956 :         nwrap_backend_init(nwrap_main_global);
    1929             : 
    1930             :         /* passwd */
    1931       36956 :         nwrap_pw_global.cache = &__nwrap_cache_pw;
    1932             : 
    1933       36956 :         nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
    1934       36956 :         nwrap_pw_global.cache->fp = NULL;
    1935       36956 :         nwrap_pw_global.cache->fd = -1;
    1936       36956 :         nwrap_pw_global.cache->private_data = &nwrap_pw_global;
    1937       36956 :         nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
    1938       36956 :         nwrap_pw_global.cache->unload = nwrap_pw_unload;
    1939             : 
    1940             :         /* shadow */
    1941             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    1942       36956 :         nwrap_sp_global.cache = &__nwrap_cache_sp;
    1943             : 
    1944       36956 :         nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
    1945       36956 :         nwrap_sp_global.cache->fp = NULL;
    1946       36956 :         nwrap_sp_global.cache->fd = -1;
    1947       36956 :         nwrap_sp_global.cache->private_data = &nwrap_sp_global;
    1948       36956 :         nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
    1949       36956 :         nwrap_sp_global.cache->unload = nwrap_sp_unload;
    1950             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    1951             : 
    1952             :         /* group */
    1953       36956 :         nwrap_gr_global.cache = &__nwrap_cache_gr;
    1954             : 
    1955       36956 :         nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
    1956       36956 :         nwrap_gr_global.cache->fp = NULL;
    1957       36956 :         nwrap_gr_global.cache->fd = -1;
    1958       36956 :         nwrap_gr_global.cache->private_data = &nwrap_gr_global;
    1959       36956 :         nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
    1960       36956 :         nwrap_gr_global.cache->unload = nwrap_gr_unload;
    1961             : 
    1962             :         /* hosts */
    1963       36956 :         nwrap_he_global.cache = &__nwrap_cache_he;
    1964             : 
    1965       36956 :         nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
    1966       36956 :         nwrap_he_global.cache->fp = NULL;
    1967       36956 :         nwrap_he_global.cache->fd = -1;
    1968       36956 :         nwrap_he_global.cache->private_data = &nwrap_he_global;
    1969       36956 :         nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
    1970       36956 :         nwrap_he_global.cache->unload = nwrap_he_unload;
    1971             : 
    1972             :         /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
    1973       36956 :         NWRAP_UNLOCK_ALL;
    1974             : }
    1975             : 
    1976      366691 : bool nss_wrapper_enabled(void)
    1977             : {
    1978      366691 :         nwrap_init();
    1979             : 
    1980      731184 :         if (nwrap_pw_global.cache->path == NULL ||
    1981      364493 :             nwrap_pw_global.cache->path[0] == '\0') {
    1982        1291 :                 return false;
    1983             :         }
    1984      728986 :         if (nwrap_gr_global.cache->path == NULL ||
    1985      364493 :             nwrap_gr_global.cache->path[0] == '\0') {
    1986           0 :                 return false;
    1987             :         }
    1988             : 
    1989      364493 :         return true;
    1990             : }
    1991             : 
    1992             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    1993           0 : bool nss_wrapper_shadow_enabled(void)
    1994             : {
    1995           0 :         nwrap_init();
    1996             : 
    1997           0 :         if (nwrap_sp_global.cache->path == NULL ||
    1998           0 :             nwrap_sp_global.cache->path[0] == '\0') {
    1999           0 :                 return false;
    2000             :         }
    2001             : 
    2002           0 :         return true;
    2003             : }
    2004             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    2005             : 
    2006     3013688 : bool nss_wrapper_hosts_enabled(void)
    2007             : {
    2008     3013688 :         nwrap_init();
    2009             : 
    2010     5702327 :         if (nwrap_he_global.cache->path == NULL ||
    2011     2688639 :             nwrap_he_global.cache->path[0] == '\0') {
    2012      297085 :                 return false;
    2013             :         }
    2014             : 
    2015     2679899 :         return true;
    2016             : }
    2017             : 
    2018       62373 : static bool nwrap_hostname_enabled(void)
    2019             : {
    2020       63216 :         nwrap_init();
    2021             : 
    2022       63216 :         if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
    2023        7305 :                 return false;
    2024             :         }
    2025             : 
    2026       55068 :         return true;
    2027             : }
    2028             : 
    2029       41131 : static bool nwrap_parse_file(struct nwrap_cache *nwrap)
    2030             : {
    2031       41131 :         char *line = NULL;
    2032             :         ssize_t n;
    2033             :         /* Unused but getline needs it */
    2034             :         size_t len;
    2035             :         bool ok;
    2036             : 
    2037       41131 :         if (nwrap->st.st_size == 0) {
    2038           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
    2039           0 :                 return true;
    2040             :         }
    2041             : 
    2042             :         /* Support for 32-bit system I guess */
    2043       41131 :         if (nwrap->st.st_size > INT32_MAX) {
    2044           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2045             :                           "Size[%u] larger than INT32_MAX",
    2046             :                           (unsigned)nwrap->st.st_size);
    2047           0 :                 return false;
    2048             :         }
    2049             : 
    2050       41131 :         rewind(nwrap->fp);
    2051             : 
    2052             :         do {
    2053      739375 :                 n = getline(&line, &len, nwrap->fp);
    2054      738754 :                 if (n < 0) {
    2055       41131 :                         SAFE_FREE(line);
    2056       41131 :                         if (feof(nwrap->fp)) {
    2057       41013 :                                 break;
    2058             :                         }
    2059             : 
    2060           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2061             :                                   "Unable to read line from file: %s",
    2062             :                                   nwrap->path);
    2063           0 :                         return false;
    2064             :                 }
    2065             : 
    2066      697623 :                 if (line[n - 1] == '\n') {
    2067      697623 :                         line[n - 1] = '\0';
    2068             :                 }
    2069             : 
    2070      697623 :                 if (line[0] == '\0') {
    2071           0 :                         SAFE_FREE(line);
    2072           0 :                         continue;
    2073             :                 }
    2074             : 
    2075      697623 :                 ok = nwrap->parse_line(nwrap, line);
    2076      697623 :                 if (!ok) {
    2077           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2078             :                                   "Unable to parse line file: %s",
    2079             :                                   line);
    2080           0 :                         SAFE_FREE(line);
    2081           0 :                         return false;
    2082             :                 }
    2083             : 
    2084             :                 /* Line is parsed without issues so add it to list */
    2085      697623 :                 ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
    2086      697623 :                 if (!ok) {
    2087           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2088             :                                   "Unable to add line to vector");
    2089           0 :                         return false;
    2090             :                 }
    2091             : 
    2092             :                 /* This forces getline to allocate new memory for line. */
    2093      697623 :                 line = NULL;
    2094      697623 :         } while (!feof(nwrap->fp));
    2095             : 
    2096       41013 :         return true;
    2097             : }
    2098             : 
    2099      345185 : static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
    2100             : {
    2101      350587 :         nwrap->unload(nwrap);
    2102             : 
    2103      350587 :         nwrap_lines_unload(nwrap);
    2104      345185 : }
    2105             : 
    2106     1056086 : static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
    2107             : {
    2108             :         struct stat st;
    2109             :         int ret;
    2110             :         bool ok;
    2111     1056086 :         bool retried = false;
    2112             : 
    2113     1056086 :         assert(nwrap != NULL);
    2114             : 
    2115     1062380 : reopen:
    2116     1062380 :         if (nwrap->fd < 0) {
    2117       32809 :                 nwrap->fp = fopen(nwrap->path, "re");
    2118       32809 :                 if (nwrap->fp == NULL) {
    2119           0 :                         nwrap->fd = -1;
    2120           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2121             :                                   "Unable to open '%s' readonly %d:%s",
    2122             :                                   nwrap->path, nwrap->fd,
    2123             :                                   strerror(errno));
    2124           0 :                         return false;
    2125             : 
    2126             :                 }
    2127       32809 :                 nwrap->fd = fileno(nwrap->fp);
    2128       32809 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
    2129             :         }
    2130             : 
    2131     1082139 :         ret = fstat(nwrap->fd, &st);
    2132     1062380 :         if (ret != 0) {
    2133           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2134             :                           "fstat(%s) - %d:%s",
    2135             :                           nwrap->path,
    2136             :                           ret,
    2137             :                           strerror(errno));
    2138           0 :                 fclose(nwrap->fp);
    2139           0 :                 nwrap->fp = NULL;
    2140           0 :                 nwrap->fd = -1;
    2141           0 :                 return false;
    2142             :         }
    2143             : 
    2144     1062380 :         if (retried == false && st.st_nlink == 0) {
    2145             :                 /* maybe someone has replaced the file... */
    2146        6294 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2147             :                           "st_nlink == 0, reopen %s",
    2148             :                           nwrap->path);
    2149        6294 :                 retried = true;
    2150        6294 :                 memset(&nwrap->st, 0, sizeof(nwrap->st));
    2151        6294 :                 fclose(nwrap->fp);
    2152        6294 :                 nwrap->fp = NULL;
    2153        6294 :                 nwrap->fd = -1;
    2154        6294 :                 goto reopen;
    2155             :         }
    2156             : 
    2157     1056086 :         if (st.st_mtime == nwrap->st.st_mtime) {
    2158     1014955 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2159             :                           "st_mtime[%u] hasn't changed, skip reload",
    2160             :                           (unsigned)st.st_mtime);
    2161     1014955 :                 return true;
    2162             :         }
    2163             : 
    2164       41131 :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2165             :                   "st_mtime has changed [%u] => [%u], start reload",
    2166             :                   (unsigned)st.st_mtime,
    2167             :                   (unsigned)nwrap->st.st_mtime);
    2168             : 
    2169       41131 :         nwrap->st = st;
    2170             : 
    2171       41131 :         nwrap_files_cache_unload(nwrap);
    2172             : 
    2173       41131 :         ok = nwrap_parse_file(nwrap);
    2174       41131 :         if (!ok) {
    2175           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
    2176           0 :                 nwrap_files_cache_unload(nwrap);
    2177           0 :                 return false;
    2178             :         }
    2179             : 
    2180       41131 :         NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
    2181       41131 :         return true;
    2182             : }
    2183             : 
    2184             : /*
    2185             :  * the caller has to call nwrap_unload() on failure
    2186             :  */
    2187      305938 : static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
    2188             : {
    2189             :         struct nwrap_pw *nwrap_pw;
    2190             :         char *c;
    2191             :         char *p;
    2192             :         char *e;
    2193             :         struct passwd *pw;
    2194             :         size_t list_size;
    2195             : 
    2196      305938 :         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
    2197             : 
    2198      305938 :         list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
    2199      305938 :         pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
    2200      305938 :         if (!pw) {
    2201           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2202             :                           "realloc(%u) failed",
    2203             :                           (unsigned)list_size);
    2204           0 :                 return false;
    2205             :         }
    2206      305938 :         nwrap_pw->list = pw;
    2207             : 
    2208      305938 :         pw = &nwrap_pw->list[nwrap_pw->num];
    2209             : 
    2210      305938 :         c = line;
    2211             : 
    2212             :         /* name */
    2213      305938 :         p = strchr(c, ':');
    2214      305938 :         if (!p) {
    2215           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2216             :                           "Invalid line[%s]: '%s'",
    2217             :                           line,
    2218             :                           c);
    2219           0 :                 return false;
    2220             :         }
    2221      305938 :         *p = '\0';
    2222      305938 :         p++;
    2223      305938 :         pw->pw_name = c;
    2224      305938 :         c = p;
    2225             : 
    2226      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
    2227             : 
    2228             :         /* password */
    2229      305938 :         p = strchr(c, ':');
    2230      305938 :         if (!p) {
    2231           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2232           0 :                 return false;
    2233             :         }
    2234      305938 :         *p = '\0';
    2235      305938 :         p++;
    2236      305938 :         pw->pw_passwd = c;
    2237      305938 :         c = p;
    2238             : 
    2239      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
    2240             : 
    2241             :         /* uid */
    2242      305938 :         p = strchr(c, ':');
    2243      305938 :         if (!p) {
    2244           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2245           0 :                 return false;
    2246             :         }
    2247      305938 :         *p = '\0';
    2248      305938 :         p++;
    2249      305938 :         e = NULL;
    2250      305938 :         pw->pw_uid = (uid_t)strtoul(c, &e, 10);
    2251      305938 :         if (c == e) {
    2252           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2253             :                           "Invalid line[%s]: '%s' - %s",
    2254             :                           line, c, strerror(errno));
    2255           0 :                 return false;
    2256             :         }
    2257      305938 :         if (e == NULL) {
    2258           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2259             :                           "Invalid line[%s]: '%s' - %s",
    2260             :                           line, c, strerror(errno));
    2261           0 :                 return false;
    2262             :         }
    2263      305938 :         if (e[0] != '\0') {
    2264           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2265             :                           "Invalid line[%s]: '%s' - %s",
    2266             :                           line, c, strerror(errno));
    2267           0 :                 return false;
    2268             :         }
    2269      305938 :         c = p;
    2270             : 
    2271      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
    2272             : 
    2273             :         /* gid */
    2274      305938 :         p = strchr(c, ':');
    2275      305938 :         if (!p) {
    2276           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2277           0 :                 return false;
    2278             :         }
    2279      305938 :         *p = '\0';
    2280      305938 :         p++;
    2281      305938 :         e = NULL;
    2282      305938 :         pw->pw_gid = (gid_t)strtoul(c, &e, 10);
    2283      305938 :         if (c == e) {
    2284           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2285             :                           "Invalid line[%s]: '%s' - %s",
    2286             :                           line, c, strerror(errno));
    2287           0 :                 return false;
    2288             :         }
    2289      305938 :         if (e == NULL) {
    2290           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2291             :                           "Invalid line[%s]: '%s' - %s",
    2292             :                           line, c, strerror(errno));
    2293           0 :                 return false;
    2294             :         }
    2295      305938 :         if (e[0] != '\0') {
    2296           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2297             :                           "Invalid line[%s]: '%s' - %s",
    2298             :                           line, c, strerror(errno));
    2299           0 :                 return false;
    2300             :         }
    2301      305938 :         c = p;
    2302             : 
    2303      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
    2304             : 
    2305             : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
    2306             :         pw->pw_class = discard_const_p(char, "");
    2307             : 
    2308             :         NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class);
    2309             : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
    2310             : 
    2311             : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
    2312             :         pw->pw_change = 0;
    2313             : 
    2314             :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2315             :                   "change[%lu]",
    2316             :                   (unsigned long)pw->pw_change);
    2317             : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
    2318             : 
    2319             : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
    2320             :         pw->pw_expire = 0;
    2321             : 
    2322             :         NWRAP_LOG(NWRAP_LOG_TRACE,
    2323             :                   "expire[%lu]",
    2324             :                   (unsigned long)pw->pw_expire);
    2325             : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
    2326             : 
    2327             :         /* gecos */
    2328      305938 :         p = strchr(c, ':');
    2329      305938 :         if (!p) {
    2330           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
    2331           0 :                 return false;
    2332             :         }
    2333      305938 :         *p = '\0';
    2334      305938 :         p++;
    2335      305938 :         pw->pw_gecos = c;
    2336      305938 :         c = p;
    2337             : 
    2338      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
    2339             : 
    2340             :         /* dir */
    2341      305938 :         p = strchr(c, ':');
    2342      305938 :         if (!p) {
    2343           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
    2344           0 :                 return false;
    2345             :         }
    2346      305938 :         *p = '\0';
    2347      305938 :         p++;
    2348      305938 :         pw->pw_dir = c;
    2349      305938 :         c = p;
    2350             : 
    2351      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
    2352             : 
    2353             :         /* shell */
    2354      305938 :         pw->pw_shell = c;
    2355      305938 :         NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
    2356             : 
    2357      305938 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    2358             :                   "Added user[%s:%s:%u:%u:%s:%s:%s]",
    2359             :                   pw->pw_name, pw->pw_passwd,
    2360             :                   pw->pw_uid, pw->pw_gid,
    2361             :                   pw->pw_gecos, pw->pw_dir, pw->pw_shell);
    2362             : 
    2363      305938 :         nwrap_pw->num++;
    2364      305938 :         return true;
    2365             : }
    2366             : 
    2367       87117 : static void nwrap_pw_unload(struct nwrap_cache *nwrap)
    2368             : {
    2369             :         struct nwrap_pw *nwrap_pw;
    2370       87117 :         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
    2371             : 
    2372       87117 :         SAFE_FREE(nwrap_pw->list);
    2373       87117 :         nwrap_pw->num = 0;
    2374       87117 :         nwrap_pw->idx = 0;
    2375       87117 : }
    2376             : 
    2377        2416 : static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
    2378             :                            char *buf, size_t buflen, struct passwd **dstp)
    2379             : {
    2380             :         char *first;
    2381             :         char *last;
    2382             :         off_t ofs;
    2383             : 
    2384        2416 :         first = src->pw_name;
    2385             : 
    2386        2416 :         last = src->pw_shell;
    2387        2416 :         while (*last) last++;
    2388             : 
    2389        2416 :         ofs = PTR_DIFF(last + 1, first);
    2390             : 
    2391        2416 :         if (ofs > (off_t) buflen) {
    2392           0 :                 return ERANGE;
    2393             :         }
    2394             : 
    2395        2416 :         memcpy(buf, first, ofs);
    2396             : 
    2397        2416 :         ofs = PTR_DIFF(src->pw_name, first);
    2398        2416 :         dst->pw_name = buf + ofs;
    2399        2416 :         ofs = PTR_DIFF(src->pw_passwd, first);
    2400        2416 :         dst->pw_passwd = buf + ofs;
    2401        2416 :         dst->pw_uid = src->pw_uid;
    2402        2416 :         dst->pw_gid = src->pw_gid;
    2403             : #ifdef HAVE_STRUCT_PASSWD_PW_CLASS
    2404             :         ofs = PTR_DIFF(src->pw_class, first);
    2405             :         dst->pw_class = buf + ofs;
    2406             : #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */
    2407             : 
    2408             : #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
    2409             :         dst->pw_change = 0;
    2410             : #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */
    2411             : 
    2412             : #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
    2413             :         dst->pw_expire = 0;
    2414             : #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */
    2415             : 
    2416        2416 :         ofs = PTR_DIFF(src->pw_gecos, first);
    2417        2416 :         dst->pw_gecos = buf + ofs;
    2418        2416 :         ofs = PTR_DIFF(src->pw_dir, first);
    2419        2416 :         dst->pw_dir = buf + ofs;
    2420        2416 :         ofs = PTR_DIFF(src->pw_shell, first);
    2421        2416 :         dst->pw_shell = buf + ofs;
    2422             : 
    2423        2416 :         if (dstp) {
    2424        2416 :                 *dstp = dst;
    2425             :         }
    2426             : 
    2427        2416 :         return 0;
    2428             : }
    2429             : 
    2430             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    2431           0 : static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
    2432             : {
    2433             :         struct nwrap_sp *nwrap_sp;
    2434             :         struct spwd *sp;
    2435             :         size_t list_size;
    2436             :         char *c;
    2437             :         char *e;
    2438             :         char *p;
    2439             : 
    2440           0 :         nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
    2441             : 
    2442           0 :         list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
    2443           0 :         sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
    2444           0 :         if (sp == NULL) {
    2445           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2446             :                           "realloc(%u) failed",
    2447             :                           (unsigned)list_size);
    2448           0 :                 return false;
    2449             :         }
    2450           0 :         nwrap_sp->list = sp;
    2451             : 
    2452           0 :         sp = &nwrap_sp->list[nwrap_sp->num];
    2453             : 
    2454           0 :         c = line;
    2455             : 
    2456             :         /* name */
    2457           0 :         p = strchr(c, ':');
    2458           0 :         if (p == NULL) {
    2459           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2460             :                           "name -- Invalid line[%s]: '%s'",
    2461             :                           line,
    2462             :                           c);
    2463           0 :                 return false;
    2464             :         }
    2465           0 :         *p = '\0';
    2466           0 :         p++;
    2467           0 :         sp->sp_namp = c;
    2468           0 :         c = p;
    2469             : 
    2470           0 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
    2471             : 
    2472             :         /* pwd */
    2473           0 :         p = strchr(c, ':');
    2474           0 :         if (p == NULL) {
    2475           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2476             :                           "pwd -- Invalid line[%s]: '%s'",
    2477             :                           line,
    2478             :                           c);
    2479           0 :                 return false;
    2480             :         }
    2481           0 :         *p = '\0';
    2482           0 :         p++;
    2483           0 :         sp->sp_pwdp = c;
    2484           0 :         c = p;
    2485             : 
    2486             :         /* lstchg (long) */
    2487           0 :         if (c[0] == ':') {
    2488           0 :                 sp->sp_lstchg = -1;
    2489           0 :                 p++;
    2490             :         } else {
    2491           0 :                 p = strchr(c, ':');
    2492           0 :                 if (p == NULL) {
    2493           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2494             :                                   "lstchg -- Invalid line[%s]: '%s'",
    2495             :                                   line,
    2496             :                                   c);
    2497           0 :                         return false;
    2498             :                 }
    2499           0 :                 *p = '\0';
    2500           0 :                 p++;
    2501           0 :                 sp->sp_lstchg = strtol(c, &e, 10);
    2502           0 :                 if (c == e) {
    2503           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2504             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2505             :                                   line, c, strerror(errno));
    2506           0 :                         return false;
    2507             :                 }
    2508           0 :                 if (e == NULL) {
    2509           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2510             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2511             :                                   line, c, strerror(errno));
    2512           0 :                         return false;
    2513             :                 }
    2514           0 :                 if (e[0] != '\0') {
    2515           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2516             :                                   "lstchg -- Invalid line[%s]: '%s' - %s",
    2517             :                                   line, c, strerror(errno));
    2518           0 :                         return false;
    2519             :                 }
    2520             :         }
    2521           0 :         c = p;
    2522             : 
    2523             :         /* min (long) */
    2524           0 :         if (c[0] == ':') {
    2525           0 :                 sp->sp_min = -1;
    2526           0 :                 p++;
    2527             :         } else {
    2528           0 :                 p = strchr(c, ':');
    2529           0 :                 if (p == NULL) {
    2530           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2531             :                                   "min -- Invalid line[%s]: '%s'",
    2532             :                                   line,
    2533             :                                   c);
    2534           0 :                         return false;
    2535             :                 }
    2536           0 :                 *p = '\0';
    2537           0 :                 p++;
    2538           0 :                 sp->sp_min = strtol(c, &e, 10);
    2539           0 :                 if (c == e) {
    2540           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2541             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2542             :                                   line, c, strerror(errno));
    2543           0 :                         return false;
    2544             :                 }
    2545           0 :                 if (e == NULL) {
    2546           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2547             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2548             :                                   line, c, strerror(errno));
    2549           0 :                         return false;
    2550             :                 }
    2551           0 :                 if (e[0] != '\0') {
    2552           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2553             :                                   "min -- Invalid line[%s]: '%s' - %s",
    2554             :                                   line, c, strerror(errno));
    2555           0 :                         return false;
    2556             :                 }
    2557             :         }
    2558           0 :         c = p;
    2559             : 
    2560             :         /* max (long) */
    2561           0 :         if (c[0] == ':') {
    2562           0 :                 sp->sp_max = -1;
    2563           0 :                 p++;
    2564             :         } else {
    2565           0 :                 p = strchr(c, ':');
    2566           0 :                 if (p == NULL) {
    2567           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2568             :                                   "max -- Invalid line[%s]: '%s'",
    2569             :                                   line,
    2570             :                                   c);
    2571           0 :                         return false;
    2572             :                 }
    2573           0 :                 *p = '\0';
    2574           0 :                 p++;
    2575           0 :                 sp->sp_max = strtol(c, &e, 10);
    2576           0 :                 if (c == e) {
    2577           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2578             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2579             :                                   line, c, strerror(errno));
    2580           0 :                         return false;
    2581             :                 }
    2582           0 :                 if (e == NULL) {
    2583           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2584             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2585             :                                   line, c, strerror(errno));
    2586           0 :                         return false;
    2587             :                 }
    2588           0 :                 if (e[0] != '\0') {
    2589           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2590             :                                   "max -- Invalid line[%s]: '%s' - %s",
    2591             :                                   line, c, strerror(errno));
    2592           0 :                         return false;
    2593             :                 }
    2594             :         }
    2595           0 :         c = p;
    2596             : 
    2597             :         /* warn (long) */
    2598           0 :         if (c[0] == ':') {
    2599           0 :                 sp->sp_warn = -1;
    2600           0 :                 p++;
    2601             :         } else {
    2602           0 :                 p = strchr(c, ':');
    2603           0 :                 if (p == NULL) {
    2604           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2605             :                                   "warn -- Invalid line[%s]: '%s'",
    2606             :                                   line,
    2607             :                                   c);
    2608           0 :                         return false;
    2609             :                 }
    2610           0 :                 *p = '\0';
    2611           0 :                 p++;
    2612           0 :                 sp->sp_warn = strtol(c, &e, 10);
    2613           0 :                 if (c == e) {
    2614           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2615             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2616             :                                   line, c, strerror(errno));
    2617           0 :                         return false;
    2618             :                 }
    2619           0 :                 if (e == NULL) {
    2620           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2621             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2622             :                                   line, c, strerror(errno));
    2623           0 :                         return false;
    2624             :                 }
    2625           0 :                 if (e[0] != '\0') {
    2626           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2627             :                                   "warn -- Invalid line[%s]: '%s' - %s",
    2628             :                                   line, c, strerror(errno));
    2629           0 :                         return false;
    2630             :                 }
    2631             :         }
    2632           0 :         c = p;
    2633             : 
    2634             :         /* inact (long) */
    2635           0 :         if (c[0] == ':') {
    2636           0 :                 sp->sp_inact = -1;
    2637           0 :                 p++;
    2638             :         } else {
    2639           0 :                 p = strchr(c, ':');
    2640           0 :                 if (p == NULL) {
    2641           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2642             :                                   "inact -- Invalid line[%s]: '%s'",
    2643             :                                   line,
    2644             :                                   c);
    2645           0 :                         return false;
    2646             :                 }
    2647           0 :                 *p = '\0';
    2648           0 :                 p++;
    2649           0 :                 sp->sp_inact = strtol(c, &e, 10);
    2650           0 :                 if (c == e) {
    2651           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2652             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2653             :                                   line, c, strerror(errno));
    2654           0 :                         return false;
    2655             :                 }
    2656           0 :                 if (e == NULL) {
    2657           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2658             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2659             :                                   line, c, strerror(errno));
    2660           0 :                         return false;
    2661             :                 }
    2662           0 :                 if (e[0] != '\0') {
    2663           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2664             :                                   "inact -- Invalid line[%s]: '%s' - %s",
    2665             :                                   line, c, strerror(errno));
    2666           0 :                         return false;
    2667             :                 }
    2668             :         }
    2669           0 :         c = p;
    2670             : 
    2671             :         /* expire (long) */
    2672           0 :         if (c[0] == ':') {
    2673           0 :                 sp->sp_expire = -1;
    2674           0 :                 p++;
    2675             :         } else {
    2676           0 :                 p = strchr(c, ':');
    2677           0 :                 if (p == NULL) {
    2678           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2679             :                                   "expire -- Invalid line[%s]: '%s'",
    2680             :                                   line,
    2681             :                                   c);
    2682           0 :                         return false;
    2683             :                 }
    2684           0 :                 *p = '\0';
    2685           0 :                 p++;
    2686           0 :                 sp->sp_expire = strtol(c, &e, 10);
    2687           0 :                 if (c == e) {
    2688           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2689             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2690             :                                   line, c, strerror(errno));
    2691           0 :                         return false;
    2692             :                 }
    2693           0 :                 if (e == NULL) {
    2694           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2695             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2696             :                                   line, c, strerror(errno));
    2697           0 :                         return false;
    2698             :                 }
    2699           0 :                 if (e[0] != '\0') {
    2700           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2701             :                                   "expire -- Invalid line[%s]: '%s' - %s",
    2702             :                                   line, c, strerror(errno));
    2703           0 :                         return false;
    2704             :                 }
    2705             :         }
    2706           0 :         c = p;
    2707             : 
    2708           0 :         nwrap_sp->num++;
    2709           0 :         return true;
    2710             : }
    2711             : 
    2712       77364 : static void nwrap_sp_unload(struct nwrap_cache *nwrap)
    2713             : {
    2714             :         struct nwrap_sp *nwrap_sp;
    2715       77364 :         nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
    2716             : 
    2717       77364 :         SAFE_FREE(nwrap_sp->list);
    2718       77364 :         nwrap_sp->num = 0;
    2719       77364 :         nwrap_sp->idx = 0;
    2720       77364 : }
    2721             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    2722             : 
    2723             : /*
    2724             :  * the caller has to call nwrap_unload() on failure
    2725             :  */
    2726      173003 : static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
    2727             : {
    2728             :         struct nwrap_gr *nwrap_gr;
    2729             :         char *c;
    2730             :         char *p;
    2731             :         char *e;
    2732             :         struct group *gr;
    2733             :         size_t list_size;
    2734             :         unsigned nummem;
    2735             : 
    2736      173003 :         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
    2737             : 
    2738      173003 :         list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
    2739      173003 :         gr = (struct group *)realloc(nwrap_gr->list, list_size);
    2740      173003 :         if (!gr) {
    2741           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
    2742           0 :                 return false;
    2743             :         }
    2744      173003 :         nwrap_gr->list = gr;
    2745             : 
    2746      173003 :         gr = &nwrap_gr->list[nwrap_gr->num];
    2747             : 
    2748      173003 :         c = line;
    2749             : 
    2750             :         /* name */
    2751      173003 :         p = strchr(c, ':');
    2752      173003 :         if (!p) {
    2753           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2754           0 :                 return false;
    2755             :         }
    2756      173003 :         *p = '\0';
    2757      173003 :         p++;
    2758      173003 :         gr->gr_name = c;
    2759      173003 :         c = p;
    2760             : 
    2761      173003 :         NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
    2762             : 
    2763             :         /* password */
    2764      173003 :         p = strchr(c, ':');
    2765      173003 :         if (!p) {
    2766           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2767           0 :                 return false;
    2768             :         }
    2769      173003 :         *p = '\0';
    2770      173003 :         p++;
    2771      173003 :         gr->gr_passwd = c;
    2772      173003 :         c = p;
    2773             : 
    2774      173003 :         NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
    2775             : 
    2776             :         /* gid */
    2777      173003 :         p = strchr(c, ':');
    2778      173003 :         if (!p) {
    2779           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    2780           0 :                 return false;
    2781             :         }
    2782      173003 :         *p = '\0';
    2783      173003 :         p++;
    2784      173003 :         e = NULL;
    2785      173003 :         gr->gr_gid = (gid_t)strtoul(c, &e, 10);
    2786      173003 :         if (c == e) {
    2787           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2788             :                           "Invalid line[%s]: '%s' - %s",
    2789             :                           line, c, strerror(errno));
    2790           0 :                 return false;
    2791             :         }
    2792      173003 :         if (e == NULL) {
    2793           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2794             :                           "Invalid line[%s]: '%s' - %s",
    2795             :                           line, c, strerror(errno));
    2796           0 :                 return false;
    2797             :         }
    2798      173003 :         if (e[0] != '\0') {
    2799           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2800             :                           "Invalid line[%s]: '%s' - %s",
    2801             :                           line, c, strerror(errno));
    2802           0 :                 return false;
    2803             :         }
    2804      173003 :         c = p;
    2805             : 
    2806      173003 :         NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
    2807             : 
    2808             :         /* members */
    2809      173003 :         gr->gr_mem = (char **)malloc(sizeof(char *));
    2810      173003 :         if (!gr->gr_mem) {
    2811           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    2812           0 :                 return false;
    2813             :         }
    2814      173003 :         gr->gr_mem[0] = NULL;
    2815             : 
    2816      176308 :         for(nummem = 0; p != NULL && p[0] != '\0'; nummem++) {
    2817             :                 char **m;
    2818             :                 size_t m_size;
    2819        3305 :                 c = p;
    2820        3305 :                 p = strchr(c, ',');
    2821        3305 :                 if (p) {
    2822           0 :                         *p = '\0';
    2823           0 :                         p++;
    2824             :                 }
    2825             : 
    2826        3305 :                 if (strlen(c) == 0) {
    2827           0 :                         break;
    2828             :                 }
    2829             : 
    2830        3305 :                 m_size = sizeof(char *) * (nummem+2);
    2831        3305 :                 m = (char **)realloc(gr->gr_mem, m_size);
    2832        3305 :                 if (!m) {
    2833           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    2834             :                                   "realloc(%zd) failed",
    2835             :                                   m_size);
    2836           0 :                         return false;
    2837             :                 }
    2838        3305 :                 gr->gr_mem = m;
    2839        3305 :                 gr->gr_mem[nummem] = c;
    2840        3305 :                 gr->gr_mem[nummem+1] = NULL;
    2841             : 
    2842        3305 :                 NWRAP_LOG(NWRAP_LOG_TRACE,
    2843             :                           "member[%u]: '%s'",
    2844             :                           nummem, gr->gr_mem[nummem]);
    2845             :         }
    2846             : 
    2847      173003 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    2848             :                   "Added group[%s:%s:%u:] with %u members",
    2849             :                   gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
    2850             : 
    2851      173003 :         nwrap_gr->num++;
    2852      173003 :         return true;
    2853             : }
    2854             : 
    2855       79178 : static void nwrap_gr_unload(struct nwrap_cache *nwrap)
    2856             : {
    2857             :         int i;
    2858             :         struct nwrap_gr *nwrap_gr;
    2859       79178 :         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
    2860             : 
    2861       79178 :         if (nwrap_gr->list) {
    2862      513319 :                 for (i=0; i < nwrap_gr->num; i++) {
    2863      484559 :                         SAFE_FREE(nwrap_gr->list[i].gr_mem);
    2864             :                 }
    2865       29294 :                 SAFE_FREE(nwrap_gr->list);
    2866             :         }
    2867             : 
    2868       79178 :         nwrap_gr->num = 0;
    2869       79178 :         nwrap_gr->idx = 0;
    2870       79178 : }
    2871             : 
    2872        2124 : static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
    2873             :                            char *buf, size_t buflen, struct group **dstp)
    2874             : {
    2875        2124 :         char *p = NULL;
    2876        2124 :         uintptr_t align = 0;
    2877        2124 :         unsigned int gr_mem_cnt = 0;
    2878             :         unsigned i;
    2879             :         size_t total_len;
    2880        2124 :         size_t gr_name_len = strlen(src->gr_name) + 1;
    2881        2124 :         size_t gr_passwd_len = strlen(src->gr_passwd) + 1;
    2882             :         union {
    2883             :                 char *ptr;
    2884             :                 char **data;
    2885             :         } g_mem;
    2886             : 
    2887        2196 :         for (i = 0; src->gr_mem[i] != NULL; i++) {
    2888          72 :                 gr_mem_cnt++;
    2889             :         }
    2890             : 
    2891             :         /* Align the memory for storing pointers */
    2892        2124 :         align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *));
    2893        4248 :         total_len = align +
    2894        4248 :                     (1 + gr_mem_cnt) * sizeof(char *) +
    2895             :                     gr_name_len + gr_passwd_len;
    2896             : 
    2897        2124 :         if (total_len > buflen) {
    2898           0 :                 errno = ERANGE;
    2899           0 :                 return -1;
    2900             :         }
    2901        2124 :         buflen -= total_len;
    2902             : 
    2903             :         /* gr_mem */
    2904        2124 :         p = buf + align;
    2905        2124 :         g_mem.ptr = p;
    2906        2124 :         dst->gr_mem = g_mem.data;
    2907             : 
    2908             :         /* gr_name */
    2909        2124 :         p += (1 + gr_mem_cnt) * sizeof(char *);
    2910        2124 :         dst->gr_name = p;
    2911             : 
    2912             :         /* gr_passwd */
    2913        2124 :         p += gr_name_len;
    2914        2124 :         dst->gr_passwd = p;
    2915             : 
    2916             :         /* gr_mem[x] */
    2917        2124 :         p += gr_passwd_len;
    2918             : 
    2919             :         /* gr_gid */
    2920        2124 :         dst->gr_gid = src->gr_gid;
    2921             : 
    2922        2124 :         memcpy(dst->gr_name, src->gr_name, gr_name_len);
    2923             : 
    2924        2124 :         memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len);
    2925             : 
    2926             :         /* Set the terminating entry */
    2927        2124 :         dst->gr_mem[gr_mem_cnt] = NULL;
    2928             : 
    2929             :         /* Now add the group members content */
    2930        2124 :         total_len = 0;
    2931        2196 :         for (i = 0; i < gr_mem_cnt; i++) {
    2932          72 :                 size_t len = strlen(src->gr_mem[i]) + 1;
    2933             : 
    2934          72 :                 dst->gr_mem[i] = p;
    2935          72 :                 total_len += len;
    2936          72 :                 p += len;
    2937             :         }
    2938             : 
    2939        2124 :         if (total_len > buflen) {
    2940           0 :                 errno = ERANGE;
    2941           0 :                 return -1;
    2942             :         }
    2943             : 
    2944        2196 :         for (i = 0; i < gr_mem_cnt; i++) {
    2945          72 :                 size_t len = strlen(src->gr_mem[i]) + 1;
    2946             : 
    2947          72 :                 memcpy(dst->gr_mem[i],
    2948          72 :                        src->gr_mem[i],
    2949             :                        len);
    2950             :         }
    2951             : 
    2952        2124 :         if (dstp != NULL) {
    2953        2124 :                 *dstp = dst;
    2954             :         }
    2955             : 
    2956        2124 :         return 0;
    2957             : }
    2958             : 
    2959      662816 : static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
    2960             : {
    2961             :         struct nwrap_entlist *el;
    2962             : 
    2963      662816 :         if (ed == NULL) {
    2964           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    2965             :                           "entry is NULL, can't create list item");
    2966           0 :                 return NULL;
    2967             :         }
    2968             : 
    2969      662816 :         el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
    2970      662816 :         if (el == NULL) {
    2971           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
    2972           0 :                 return NULL;
    2973             :         }
    2974             : 
    2975      662816 :         el->next = NULL;
    2976      662816 :         el->ed = ed;
    2977             : 
    2978      662816 :         return el;
    2979             : }
    2980             : 
    2981      440749 : static bool nwrap_ed_inventarize_add_new(char *const h_name,
    2982             :                                          struct nwrap_entdata *const ed)
    2983             : {
    2984             :         ENTRY e;
    2985             :         ENTRY *p;
    2986             :         struct nwrap_entlist *el;
    2987             :         bool ok;
    2988             : 
    2989      440749 :         if (h_name == NULL) {
    2990           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
    2991           0 :                 return false;
    2992             :         }
    2993             : 
    2994      440749 :         el = nwrap_entlist_init(ed);
    2995      440749 :         if (el == NULL) {
    2996           0 :                 return false;
    2997             :         }
    2998             : 
    2999      440749 :         e.key = h_name;
    3000      440749 :         e.data = (void *)el;
    3001             : 
    3002      440749 :         p = hsearch(e, ENTER);
    3003      440749 :         if (p == NULL) {
    3004           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3005             :                           "Hash table is full (%s)!",
    3006             :                           strerror(errno));
    3007           0 :                 return false;
    3008             :         }
    3009             : 
    3010      440749 :         ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
    3011      440749 :         if (!ok) {
    3012           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3013             :                           "Failed to add list entry to vector.");
    3014           0 :                 return false;
    3015             :         }
    3016             : 
    3017      440193 :         return true;
    3018             : }
    3019             : 
    3020      222067 : static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
    3021             :                                                  struct nwrap_entlist *const el)
    3022             : {
    3023             :         struct nwrap_entlist *cursor;
    3024             :         struct nwrap_entlist *el_new;
    3025             : 
    3026      222067 :         if (el == NULL) {
    3027           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
    3028           0 :                 return false;
    3029             :         }
    3030             : 
    3031             : 
    3032      222067 :         for (cursor = el; cursor->next != NULL; cursor = cursor->next)
    3033             :         {
    3034           0 :                 if (cursor->ed == ed) {
    3035             :                         /* The entry already exists in this list. */
    3036           0 :                         return true;
    3037             :                 }
    3038             :         }
    3039             : 
    3040      222067 :         if (cursor->ed == ed) {
    3041             :                 /* The entry already exists in this list. */
    3042           0 :                 return true;
    3043             :         }
    3044             : 
    3045      222067 :         el_new = nwrap_entlist_init(ed);
    3046      222067 :         if (el_new == NULL) {
    3047           0 :                 return false;
    3048             :         }
    3049             : 
    3050      222067 :         cursor->next = el_new;
    3051      222067 :         return true;
    3052             : }
    3053             : 
    3054      662816 : static bool nwrap_ed_inventarize(char *const name,
    3055             :                                  struct nwrap_entdata *const ed)
    3056             : {
    3057             :         ENTRY e;
    3058             :         ENTRY *p;
    3059             :         bool ok;
    3060             : 
    3061      662816 :         e.key = name;
    3062      662816 :         e.data = NULL;
    3063             : 
    3064      662816 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
    3065             : 
    3066      662816 :         p = hsearch(e, FIND);
    3067      662816 :         if (p == NULL) {
    3068      440749 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
    3069      440749 :                 ok = nwrap_ed_inventarize_add_new(name, ed);
    3070             :         } else {
    3071      222067 :                 struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
    3072             : 
    3073      222067 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
    3074      222067 :                 ok = nwrap_ed_inventarize_add_to_existing(ed, el);
    3075             :         }
    3076             : 
    3077      662816 :         return ok;
    3078             : }
    3079             : 
    3080      218682 : static bool nwrap_add_hname(struct nwrap_entdata *const ed)
    3081             : {
    3082      218682 :         char *const h_name = (char *const)(ed->ht.h_name);
    3083             :         unsigned i;
    3084             :         bool ok;
    3085             : 
    3086      218682 :         ok = nwrap_ed_inventarize(h_name, ed);
    3087      218682 :         if (!ok) {
    3088           0 :                 return false;
    3089             :         }
    3090             : 
    3091      218682 :         if (ed->ht.h_aliases == NULL) {
    3092           0 :                 return true;
    3093             :         }
    3094             : 
    3095             :         /* Itemize aliases */
    3096      443856 :         for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
    3097             :                 char *h_name_alias;
    3098             : 
    3099      225452 :                 h_name_alias = ed->ht.h_aliases[i];
    3100             : 
    3101      225452 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
    3102             : 
    3103      225452 :                 if (!nwrap_ed_inventarize(h_name_alias, ed)) {
    3104           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3105             :                                   "Unable to add alias: %s", h_name_alias);
    3106           0 :                         return false;
    3107             :                 }
    3108             :         }
    3109             : 
    3110      218404 :         return true;
    3111             : }
    3112             : 
    3113      218682 : static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
    3114             : {
    3115      218682 :         struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
    3116      218682 :         bool do_aliases = true;
    3117      218682 :         ssize_t aliases_count = 0;
    3118             :         char *p;
    3119             :         char *i;
    3120             :         char *n;
    3121             : 
    3122             :         char *ip;
    3123             :         bool ok;
    3124             : 
    3125      218682 :         struct nwrap_entdata *ed = (struct nwrap_entdata *)
    3126             :                                    malloc(sizeof(struct nwrap_entdata));
    3127      218682 :         if (ed == NULL) {
    3128           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3129             :                           "Unable to allocate memory for nwrap_entdata");
    3130           0 :                 return false;
    3131             :         }
    3132      218404 :         ZERO_STRUCTP(ed);
    3133             : 
    3134      218682 :         i = line;
    3135             : 
    3136             :         /*
    3137             :          * IP
    3138             :          */
    3139             : 
    3140             :         /* Walk to first char */
    3141      218682 :         for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
    3142           0 :                 if (*p == '\0') {
    3143           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3144             :                                   "Invalid line[%s]: '%s'",
    3145             :                                   line, i);
    3146           0 :                         free(ed);
    3147           0 :                         return false;
    3148             :                 }
    3149             :         }
    3150             : 
    3151     5633940 :         for (i = p; !isspace((int)*p); p++) {
    3152     5415536 :                 if (*p == '\0') {
    3153           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3154             :                                   "Invalid line[%s]: '%s'",
    3155             :                                   line, i);
    3156           0 :                         free(ed);
    3157           0 :                         return false;
    3158             :                 }
    3159             :         }
    3160             : 
    3161      218682 :         *p = '\0';
    3162             : 
    3163      218682 :         if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
    3164      109341 :                 ed->ht.h_addrtype = AF_INET;
    3165      109341 :                 ed->ht.h_length = 4;
    3166             : #ifdef HAVE_IPV6
    3167      109341 :         } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
    3168      109341 :                 ed->ht.h_addrtype = AF_INET6;
    3169      109341 :                 ed->ht.h_length = 16;
    3170             : #endif
    3171             :         } else {
    3172           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3173             :                           "Invalid line[%s]: '%s'",
    3174             :                           line, i);
    3175             : 
    3176           0 :                 free(ed);
    3177           0 :                 return false;
    3178             :         }
    3179      218682 :         ip = i;
    3180             : 
    3181      218682 :         ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
    3182      218404 :                                    (void *const)ed->addr.host_addr);
    3183      218682 :         if (!ok) {
    3184           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
    3185           0 :                 free(ed);
    3186           0 :                 return false;
    3187             :         }
    3188      218682 :         ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
    3189             : 
    3190      218682 :         p++;
    3191             : 
    3192             :         /*
    3193             :          * FQDN
    3194             :          */
    3195             : 
    3196             :         /* Walk to first char */
    3197      218682 :         for (n = p; *p != '_' && !isalnum((int) *p); p++) {
    3198           0 :                 if (*p == '\0') {
    3199           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3200             :                                   "Invalid line[%s]: '%s'",
    3201             :                                   line, n);
    3202             : 
    3203           0 :                         free(ed);
    3204           0 :                         return false;
    3205             :                 }
    3206             :         }
    3207             : 
    3208     6724996 :         for (n = p; !isspace((int)*p); p++) {
    3209     6506592 :                 if (*p == '\0') {
    3210           0 :                         do_aliases = false;
    3211           0 :                         break;
    3212             :                 }
    3213             :         }
    3214             : 
    3215      218682 :         *p = '\0';
    3216             : 
    3217             :         /* Convert to lowercase. This operate on same memory region */
    3218      218682 :         str_tolower(n, n);
    3219      218682 :         ed->ht.h_name = n;
    3220             : 
    3221             :         /* glib's getent always dereferences he->h_aliases */
    3222      218682 :         ed->ht.h_aliases = malloc(sizeof(char *));
    3223      218682 :         if (ed->ht.h_aliases == NULL) {
    3224           0 :                 free(ed);
    3225           0 :                 return false;
    3226             :         }
    3227      218682 :         ed->ht.h_aliases[0] = NULL;
    3228             : 
    3229             :         /*
    3230             :          * Aliases
    3231             :          */
    3232      662816 :         while (do_aliases) {
    3233             :                 char **aliases;
    3234             :                 char *a;
    3235             : 
    3236      225452 :                 p++;
    3237             : 
    3238             :                 /* Walk to first char */
    3239      225452 :                 for (a = p; *p != '_' && !isalnum((int) *p); p++) {
    3240           0 :                         if (*p == '\0') {
    3241           0 :                                 do_aliases = false;
    3242           0 :                                 break;
    3243             :                         }
    3244             :                 }
    3245             :                 /* Only trailing spaces are left */
    3246      225452 :                 if (!do_aliases) {
    3247           0 :                         break;
    3248             :                 }
    3249             : 
    3250     2682002 :                 for (a = p; !isspace((int)*p); p++) {
    3251     2675510 :                         if (*p == '\0') {
    3252      218404 :                                 do_aliases = false;
    3253      218404 :                                 break;
    3254             :                         }
    3255             :                 }
    3256             : 
    3257      225452 :                 *p = '\0';
    3258             : 
    3259      225452 :                 aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
    3260      225452 :                 if (aliases == NULL) {
    3261           0 :                         free(ed);
    3262           0 :                         return false;
    3263             :                 }
    3264      225452 :                 ed->ht.h_aliases = aliases;
    3265             : 
    3266      225452 :                 str_tolower(a, a);
    3267      225452 :                 aliases[aliases_count] = a;
    3268      225452 :                 aliases[aliases_count + 1] = NULL;
    3269             : 
    3270      225452 :                 aliases_count += 1;
    3271             :         }
    3272             : 
    3273      218682 :         ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
    3274      218682 :         if (!ok) {
    3275           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
    3276           0 :                 free(ed);
    3277           0 :                 return false;
    3278             :         }
    3279             : 
    3280      218682 :         ed->aliases_count = aliases_count;
    3281             :         /* Inventarize item */
    3282      218682 :         ok = nwrap_add_hname(ed);
    3283      218682 :         if (!ok) {
    3284           0 :                 return false;
    3285             :         }
    3286             : 
    3287      218682 :         ok = nwrap_ed_inventarize(ip, ed);
    3288      218682 :         if (!ok) {
    3289           0 :                 return false;
    3290             :         }
    3291             : 
    3292      218682 :         nwrap_he->num++;
    3293      218682 :         return true;
    3294             : }
    3295             : 
    3296      106928 : static void nwrap_he_unload(struct nwrap_cache *nwrap)
    3297             : {
    3298      106928 :         struct nwrap_he *nwrap_he =
    3299             :                 (struct nwrap_he *)nwrap->private_data;
    3300             :         struct nwrap_entdata *ed;
    3301             :         struct nwrap_entlist *el;
    3302             :         size_t i;
    3303             :         int rc;
    3304             : 
    3305      511600 :         nwrap_vector_foreach (ed, nwrap_he->entries, i)
    3306             :         {
    3307      404672 :                 SAFE_FREE(ed->nwrap_addrdata.items);
    3308      404672 :                 SAFE_FREE(ed->ht.h_aliases);
    3309      404672 :                 SAFE_FREE(ed);
    3310             :         }
    3311      106928 :         SAFE_FREE(nwrap_he->entries.items);
    3312      106928 :         nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
    3313             : 
    3314      924247 :         nwrap_vector_foreach(el, nwrap_he->lists, i)
    3315             :         {
    3316     2860200 :                 while (el != NULL) {
    3317             :                         struct nwrap_entlist *el_next;
    3318             : 
    3319     1229966 :                         el_next = el->next;
    3320     1229966 :                         SAFE_FREE(el);
    3321     1229966 :                         el = el_next;
    3322             :                 }
    3323             :         }
    3324      106928 :         SAFE_FREE(nwrap_he->lists.items);
    3325      106928 :         nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
    3326             : 
    3327      106928 :         nwrap_he->num = 0;
    3328      106928 :         nwrap_he->idx = 0;
    3329             : 
    3330             :         /*
    3331             :          * If we unload the file, the pointers in the hash table point to
    3332             :          * invalid memory. So we need to destroy the hash table and recreate
    3333             :          * it.
    3334             :          */
    3335      106928 :         hdestroy();
    3336      106928 :         rc = hcreate(max_hostents);
    3337      106928 :         if (rc == 0) {
    3338           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
    3339           0 :                 exit(-1);
    3340             :         }
    3341      106928 : }
    3342             : 
    3343             : 
    3344             : /* user functions */
    3345       46259 : static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
    3346             :                                            const char *name)
    3347             : {
    3348             :         int i;
    3349             :         bool ok;
    3350             : 
    3351             :         (void) b; /* unused */
    3352             : 
    3353       46259 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
    3354             : 
    3355       46259 :         ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3356       46259 :         if (!ok) {
    3357           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3358           0 :                 return NULL;
    3359             :         }
    3360             : 
    3361      538965 :         for (i=0; i<nwrap_pw_global.num; i++) {
    3362      514371 :                 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
    3363       20783 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
    3364       20783 :                         return &nwrap_pw_global.list[i];
    3365             :                 }
    3366      493588 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3367             :                           "user[%s] does not match [%s]",
    3368             :                           name,
    3369             :                           nwrap_pw_global.list[i].pw_name);
    3370             :         }
    3371             : 
    3372       25476 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
    3373             : 
    3374       25476 :         errno = ENOENT;
    3375       25476 :         return NULL;
    3376             : }
    3377             : 
    3378        1741 : static int nwrap_files_getpwnam_r(struct nwrap_backend *b,
    3379             :                                   const char *name, struct passwd *pwdst,
    3380             :                                   char *buf, size_t buflen, struct passwd **pwdstp)
    3381             : {
    3382             :         struct passwd *pw;
    3383             : 
    3384        1741 :         pw = nwrap_files_getpwnam(b, name);
    3385        1741 :         if (!pw) {
    3386         937 :                 if (errno == 0) {
    3387           0 :                         return ENOENT;
    3388             :                 }
    3389         937 :                 return errno;
    3390             :         }
    3391             : 
    3392         804 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3393             : }
    3394             : 
    3395       37626 : static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
    3396             :                                            uid_t uid)
    3397             : {
    3398             :         int i;
    3399             :         bool ok;
    3400             : 
    3401             :         (void) b; /* unused */
    3402             : 
    3403       37626 :         ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3404       37626 :         if (!ok) {
    3405           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3406           0 :                 return NULL;
    3407             :         }
    3408             : 
    3409      250306 :         for (i=0; i<nwrap_pw_global.num; i++) {
    3410      247401 :                 if (nwrap_pw_global.list[i].pw_uid == uid) {
    3411       34260 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
    3412       34260 :                         return &nwrap_pw_global.list[i];
    3413             :                 }
    3414      213141 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3415             :                           "uid[%u] does not match [%u]",
    3416             :                           uid,
    3417             :                           nwrap_pw_global.list[i].pw_uid);
    3418             :         }
    3419             : 
    3420        3366 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
    3421             : 
    3422        3366 :         errno = ENOENT;
    3423        3366 :         return NULL;
    3424             : }
    3425             : 
    3426        1500 : static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
    3427             :                                   uid_t uid, struct passwd *pwdst,
    3428             :                                   char *buf, size_t buflen, struct passwd **pwdstp)
    3429             : {
    3430             :         struct passwd *pw;
    3431             : 
    3432        1500 :         pw = nwrap_files_getpwuid(b, uid);
    3433        1500 :         if (!pw) {
    3434         692 :                 if (errno == 0) {
    3435           0 :                         return ENOENT;
    3436             :                 }
    3437         692 :                 return errno;
    3438             :         }
    3439             : 
    3440         808 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3441             : }
    3442             : 
    3443             : /* user enum functions */
    3444          64 : static void nwrap_files_setpwent(struct nwrap_backend *b)
    3445             : {
    3446             :         (void) b; /* unused */
    3447             : 
    3448          64 :         nwrap_pw_global.idx = 0;
    3449          64 : }
    3450             : 
    3451        5786 : static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
    3452             : {
    3453             :         struct passwd *pw;
    3454             : 
    3455             :         (void) b; /* unused */
    3456             : 
    3457        5786 :         if (nwrap_pw_global.idx == 0) {
    3458             :                 bool ok;
    3459          64 :                 ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
    3460          64 :                 if (!ok) {
    3461           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
    3462           0 :                         return NULL;
    3463             :                 }
    3464             :         }
    3465             : 
    3466        5786 :         if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
    3467        3404 :                 errno = ENOENT;
    3468        3404 :                 return NULL;
    3469             :         }
    3470             : 
    3471        2382 :         pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
    3472             : 
    3473        2382 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3474             :                   "return user[%s] uid[%u]",
    3475             :                   pw->pw_name, pw->pw_uid);
    3476             : 
    3477        2382 :         return pw;
    3478             : }
    3479             : 
    3480        2156 : static int nwrap_files_getpwent_r(struct nwrap_backend *b,
    3481             :                                   struct passwd *pwdst, char *buf,
    3482             :                                   size_t buflen, struct passwd **pwdstp)
    3483             : {
    3484             :         struct passwd *pw;
    3485             : 
    3486        2156 :         pw = nwrap_files_getpwent(b);
    3487        2156 :         if (!pw) {
    3488        1352 :                 if (errno == 0) {
    3489           0 :                         return ENOENT;
    3490             :                 }
    3491        1352 :                 return errno;
    3492             :         }
    3493             : 
    3494         804 :         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
    3495             : }
    3496             : 
    3497        2639 : static void nwrap_files_endpwent(struct nwrap_backend *b)
    3498             : {
    3499             :         (void) b; /* unused */
    3500             : 
    3501        2639 :         nwrap_pw_global.idx = 0;
    3502        2639 : }
    3503             : 
    3504             : /* shadow */
    3505             : 
    3506             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    3507             : 
    3508             : #ifdef HAVE_SETSPENT
    3509             : static void nwrap_files_setspent(void)
    3510             : {
    3511             :         nwrap_sp_global.idx = 0;
    3512             : }
    3513             : 
    3514             : static struct spwd *nwrap_files_getspent(void)
    3515             : {
    3516             :         struct spwd *sp;
    3517             : 
    3518             :         if (nwrap_sp_global.idx == 0) {
    3519             :                 bool ok;
    3520             : 
    3521             :                 ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
    3522             :                 if (!ok) {
    3523             :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
    3524             :                         return NULL;
    3525             :                 }
    3526             :         }
    3527             : 
    3528             :         if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
    3529             :                 errno = ENOENT;
    3530             :                 return NULL;
    3531             :         }
    3532             : 
    3533             :         sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
    3534             : 
    3535             :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3536             :                   "return user[%s]",
    3537             :                   sp->sp_namp);
    3538             : 
    3539             :         return sp;
    3540             : }
    3541             : 
    3542             : static void nwrap_files_endspent(void)
    3543             : {
    3544             :         nwrap_sp_global.idx = 0;
    3545             : }
    3546             : #endif /* HAVE_SETSPENT */
    3547             : 
    3548           0 : static struct spwd *nwrap_files_getspnam(const char *name)
    3549             : {
    3550             :         int i;
    3551             :         bool ok;
    3552             : 
    3553           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
    3554             : 
    3555           0 :         ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
    3556           0 :         if (!ok) {
    3557           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
    3558           0 :                 return NULL;
    3559             :         }
    3560             : 
    3561           0 :         for (i=0; i<nwrap_sp_global.num; i++) {
    3562           0 :                 if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
    3563           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
    3564           0 :                         return &nwrap_sp_global.list[i];
    3565             :                 }
    3566           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3567             :                           "user[%s] does not match [%s]",
    3568             :                           name,
    3569             :                           nwrap_sp_global.list[i].sp_namp);
    3570             :         }
    3571             : 
    3572           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
    3573             : 
    3574           0 :         errno = ENOENT;
    3575           0 :         return NULL;
    3576             : }
    3577             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    3578             : 
    3579             : /* misc functions */
    3580           0 : static int nwrap_files_initgroups(struct nwrap_backend *b,
    3581             :                                   const char *user,
    3582             :                                   gid_t group)
    3583             : {
    3584             :         struct group *grp;
    3585             :         gid_t *groups;
    3586           0 :         int size = 1;
    3587             :         int rc;
    3588             : 
    3589           0 :         groups = (gid_t *)malloc(size * sizeof(gid_t));
    3590           0 :         if (groups == NULL) {
    3591           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    3592           0 :                 errno = ENOMEM;
    3593           0 :                 return -1;
    3594             :         }
    3595           0 :         groups[0] = group;
    3596             : 
    3597           0 :         nwrap_files_setgrent(b);
    3598           0 :         while ((grp = nwrap_files_getgrent(b)) != NULL) {
    3599           0 :                 int i = 0;
    3600             : 
    3601           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3602             :                           "Inspecting %s for group membership",
    3603             :                           grp->gr_name);
    3604             : 
    3605           0 :                 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
    3606           0 :                         if (group != grp->gr_gid &&
    3607           0 :                             (strcmp(user, grp->gr_mem[i]) == 0)) {
    3608           0 :                                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3609             :                                           "%s is member of %s",
    3610             :                                           user,
    3611             :                                           grp->gr_name);
    3612             : 
    3613           0 :                                 groups = (gid_t *)realloc(groups,
    3614           0 :                                                           (size + 1) * sizeof(gid_t));
    3615           0 :                                 if (groups == NULL) {
    3616           0 :                                         NWRAP_LOG(NWRAP_LOG_ERROR,
    3617             :                                                   "Out of memory");
    3618           0 :                                         errno = ENOMEM;
    3619           0 :                                         return -1;
    3620             :                                 }
    3621             : 
    3622           0 :                                 groups[size] = grp->gr_gid;
    3623           0 :                                 size++;
    3624             :                         }
    3625             :                 }
    3626             :         }
    3627             : 
    3628           0 :         nwrap_files_endgrent(b);
    3629             : 
    3630           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3631             :                   "%s is member of %d groups",
    3632             :                   user, size);
    3633             : 
    3634             :         /* This really only works if uid_wrapper is loaded */
    3635           0 :         rc = setgroups(size, groups);
    3636             : 
    3637           0 :         free(groups);
    3638             : 
    3639           0 :         return rc;
    3640             : }
    3641             : 
    3642             : /* group functions */
    3643        2816 : static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
    3644             :                                           const char *name)
    3645             : {
    3646             :         int i;
    3647             :         bool ok;
    3648             : 
    3649             :         (void) b; /* unused */
    3650             : 
    3651        2816 :         ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3652        2816 :         if (!ok) {
    3653           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3654           0 :                 return NULL;
    3655             :         }
    3656             : 
    3657      157830 :         for (i=0; i<nwrap_gr_global.num; i++) {
    3658      157185 :                 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
    3659        2165 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
    3660        2165 :                         return &nwrap_gr_global.list[i];
    3661             :                 }
    3662      155020 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3663             :                           "group[%s] does not match [%s]",
    3664             :                           name,
    3665             :                           nwrap_gr_global.list[i].gr_name);
    3666             :         }
    3667             : 
    3668         651 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
    3669             : 
    3670         651 :         errno = ENOENT;
    3671         651 :         return NULL;
    3672             : }
    3673             : 
    3674         708 : static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
    3675             :                                   const char *name, struct group *grdst,
    3676             :                                   char *buf, size_t buflen, struct group **grdstp)
    3677             : {
    3678             :         struct group *gr;
    3679             : 
    3680         708 :         gr = nwrap_files_getgrnam(b, name);
    3681         708 :         if (!gr) {
    3682           0 :                 if (errno == 0) {
    3683           0 :                         return ENOENT;
    3684             :                 }
    3685           0 :                 return errno;
    3686             :         }
    3687             : 
    3688         708 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3689             : }
    3690             : 
    3691        5921 : static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
    3692             :                                           gid_t gid)
    3693             : {
    3694             :         int i;
    3695             :         bool ok;
    3696             : 
    3697             :         (void) b; /* unused */
    3698             : 
    3699        5921 :         ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3700        5921 :         if (!ok) {
    3701           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3702           0 :                 return NULL;
    3703             :         }
    3704             : 
    3705      142842 :         for (i=0; i<nwrap_gr_global.num; i++) {
    3706      142244 :                 if (nwrap_gr_global.list[i].gr_gid == gid) {
    3707        5323 :                         NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
    3708        5323 :                         return &nwrap_gr_global.list[i];
    3709             :                 }
    3710      136921 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3711             :                           "gid[%u] does not match [%u]",
    3712             :                           gid,
    3713             :                           nwrap_gr_global.list[i].gr_gid);
    3714             :         }
    3715             : 
    3716         598 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
    3717             : 
    3718         598 :         errno = ENOENT;
    3719         598 :         return NULL;
    3720             : }
    3721             : 
    3722         712 : static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
    3723             :                                   gid_t gid, struct group *grdst,
    3724             :                                   char *buf, size_t buflen, struct group **grdstp)
    3725             : {
    3726             :         struct group *gr;
    3727             : 
    3728         712 :         gr = nwrap_files_getgrgid(b, gid);
    3729         712 :         if (!gr) {
    3730           4 :                 if (errno == 0) {
    3731           0 :                         return ENOENT;
    3732             :                 }
    3733           4 :                 return errno;
    3734             :         }
    3735             : 
    3736         708 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3737             : }
    3738             : 
    3739             : /* group enum functions */
    3740       39880 : static void nwrap_files_setgrent(struct nwrap_backend *b)
    3741             : {
    3742             :         (void) b; /* unused */
    3743             : 
    3744       39880 :         nwrap_gr_global.idx = 0;
    3745       39880 : }
    3746             : 
    3747     1003324 : static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
    3748             : {
    3749             :         struct group *gr;
    3750             : 
    3751             :         (void) b; /* unused */
    3752             : 
    3753     1003324 :         if (nwrap_gr_global.idx == 0) {
    3754             :                 bool ok;
    3755             : 
    3756       39880 :                 ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
    3757       39880 :                 if (!ok) {
    3758           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
    3759           0 :                         return NULL;
    3760             :                 }
    3761             :         }
    3762             : 
    3763     1003324 :         if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
    3764       39880 :                 errno = ENOENT;
    3765       39880 :                 return NULL;
    3766             :         }
    3767             : 
    3768      963444 :         gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
    3769             : 
    3770      963444 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3771             :                   "return group[%s] gid[%u]",
    3772             :                   gr->gr_name, gr->gr_gid);
    3773             : 
    3774      963444 :         return gr;
    3775             : }
    3776             : 
    3777         720 : static int nwrap_files_getgrent_r(struct nwrap_backend *b,
    3778             :                                   struct group *grdst, char *buf,
    3779             :                                   size_t buflen, struct group **grdstp)
    3780             : {
    3781             :         struct group *gr;
    3782             : 
    3783         720 :         gr = nwrap_files_getgrent(b);
    3784         720 :         if (!gr) {
    3785          12 :                 if (errno == 0) {
    3786           0 :                         return ENOENT;
    3787             :                 }
    3788          12 :                 return errno;
    3789             :         }
    3790             : 
    3791         708 :         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
    3792             : }
    3793             : 
    3794       39880 : static void nwrap_files_endgrent(struct nwrap_backend *b)
    3795             : {
    3796             :         (void) b; /* unused */
    3797             : 
    3798       39880 :         nwrap_gr_global.idx = 0;
    3799       39880 : }
    3800             : 
    3801             : /* hosts functions */
    3802         194 : static int nwrap_files_internal_gethostbyname(const char *name, int af,
    3803             :                                               struct hostent *result,
    3804             :                                               struct nwrap_vector *addr_list)
    3805             : {
    3806             :         struct nwrap_entlist *el;
    3807             :         struct hostent *he;
    3808             :         char *h_name_lower;
    3809             :         ENTRY e;
    3810             :         ENTRY *e_p;
    3811         194 :         char canon_name[DNS_NAME_MAX] = { 0 };
    3812             :         size_t name_len;
    3813         194 :         bool he_found = false;
    3814             :         bool ok;
    3815             : 
    3816             :         /*
    3817             :          * We need to make sure we have zeroed return pointer for consumers
    3818             :          * which don't check return values, e.g. OpenLDAP.
    3819             :          */
    3820         194 :         ZERO_STRUCTP(result);
    3821             : 
    3822         194 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    3823         194 :         if (!ok) {
    3824           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    3825           0 :                 goto no_ent;
    3826             :         }
    3827             : 
    3828         194 :         name_len = strlen(name);
    3829         194 :         if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
    3830           0 :                 memcpy(canon_name, name, name_len - 1);
    3831           0 :                 canon_name[name_len] = '\0';
    3832           0 :                 name = canon_name;
    3833             :         }
    3834             : 
    3835         194 :         if (!str_tolower_copy(&h_name_lower, name)) {
    3836           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    3837             :                           "Out of memory while converting to lower case");
    3838           0 :                 goto no_ent;
    3839             :         }
    3840             : 
    3841             :         /* Look at hash table for element */
    3842         194 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
    3843         194 :         e.key = h_name_lower;
    3844         194 :         e.data = NULL;
    3845         194 :         e_p = hsearch(e, FIND);
    3846         194 :         if (e_p == NULL) {
    3847          34 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
    3848          34 :                 SAFE_FREE(h_name_lower);
    3849          34 :                 goto no_ent;
    3850             :         }
    3851         160 :         SAFE_FREE(h_name_lower);
    3852             : 
    3853             :         /* Always cleanup vector and results */
    3854         160 :         if (!nwrap_vector_is_initialized(addr_list)) {
    3855         160 :                 if (!nwrap_vector_init(addr_list)) {
    3856           0 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3857             :                                   "Unable to initialize memory for addr_list vector");
    3858           0 :                         goto no_ent;
    3859             :                 }
    3860             :         } else {
    3861             :                 /* When vector is initialized data are valid no more.
    3862             :                  * Quick way how to free vector is: */
    3863           0 :                 addr_list->count = 0;
    3864             :         }
    3865             : 
    3866             :         /* Iterate through results */
    3867         480 :         for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
    3868             :         {
    3869         320 :                 he = &(el->ed->ht);
    3870             : 
    3871             :                 /* Filter by address familiy if provided */
    3872         320 :                 if (af != AF_UNSPEC && he->h_addrtype != af) {
    3873           0 :                         continue;
    3874             :                 }
    3875             : 
    3876             :                 /*
    3877             :                  * GLIBC HACK?
    3878             :                  * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
    3879             :                  */
    3880         320 :                 if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
    3881         160 :                         continue;
    3882             :                 }
    3883             : 
    3884         160 :                 if (!he_found) {
    3885         160 :                         memcpy(result, he, sizeof(struct hostent));
    3886         160 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3887             :                                   "Name found. Returning record for %s",
    3888             :                                   he->h_name);
    3889         160 :                         he_found = true;
    3890             :                 }
    3891         160 :                 nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
    3892         160 :                 result->h_addr_list = nwrap_vector_head(addr_list);
    3893             :         }
    3894             : 
    3895         160 :         if (he_found) {
    3896         160 :                 return 0;
    3897             :         }
    3898           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    3899             :                   "Name found in database. No records matches type.");
    3900             : 
    3901          34 : no_ent:
    3902          34 :         errno = ENOENT;
    3903          34 :         return -1;
    3904             : }
    3905             : 
    3906         194 : static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b,
    3907             :                                         const char *name, int af,
    3908             :                                         struct hostent *hedst,
    3909             :                                         char *buf, size_t buflen,
    3910             :                                         struct hostent **hedstp)
    3911             : {
    3912         194 :         struct nwrap_vector *addr_list = NULL;
    3913             :         union {
    3914             :                 char *ptr;
    3915             :                 char **list;
    3916             :         } g;
    3917             :         int rc;
    3918             : 
    3919             :         (void) b; /* unused */
    3920             :         (void) af; /* unused */
    3921             : 
    3922         194 :         if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) {
    3923           0 :                 errno = EINVAL;
    3924           0 :                 return -1;
    3925             :         }
    3926         194 :         *hedstp = NULL;
    3927         194 :         buf[0] = '\0';
    3928             : 
    3929         194 :         addr_list = calloc(1, sizeof(struct nwrap_vector));
    3930         194 :         if (addr_list == NULL) {
    3931           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR,
    3932             :                           "Unable to allocate memory for address list");
    3933           0 :                 errno = ENOENT;
    3934           0 :                 return -1;
    3935             :         }
    3936             : 
    3937         194 :         rc = nwrap_files_internal_gethostbyname(name, af, hedst,
    3938             :                                                 addr_list);
    3939         194 :         if (rc == -1) {
    3940          34 :                 SAFE_FREE(addr_list->items);
    3941          34 :                 SAFE_FREE(addr_list);
    3942          34 :                 errno = ENOENT;
    3943          34 :                 return -1;
    3944             :         }
    3945             : 
    3946             :         /* +1 i for ending NULL pointer */
    3947         160 :         if (buflen < ((addr_list->count + 1) * sizeof(void *))) {
    3948           0 :                 SAFE_FREE(addr_list->items);
    3949           0 :                 SAFE_FREE(addr_list);
    3950           0 :                 return ERANGE;
    3951             :         }
    3952             : 
    3953             :         /* Copy all to user provided buffer and change
    3954             :          * pointers in returned structure.
    3955             :          * +1 is for ending NULL pointer. */
    3956         160 :         memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
    3957             : 
    3958         160 :         SAFE_FREE(addr_list->items);
    3959         160 :         SAFE_FREE(addr_list);
    3960             : 
    3961         160 :         g.ptr = buf;
    3962         160 :         hedst->h_addr_list = g.list;
    3963         160 :         *hedstp = hedst;
    3964         160 :         return 0;
    3965             : }
    3966             : 
    3967             : #ifdef HAVE_GETHOSTBYNAME_R
    3968         194 : static int nwrap_gethostbyname_r(const char *name,
    3969             :                                  struct hostent *ret,
    3970             :                                  char *buf, size_t buflen,
    3971             :                                  struct hostent **result, int *h_errnop)
    3972             : {
    3973             :         int rc;
    3974             :         size_t i;
    3975             : 
    3976         248 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    3977         214 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    3978         214 :                 rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret,
    3979             :                                                  buf, buflen, result);
    3980         214 :                 if (rc == 0) {
    3981         160 :                         return 0;
    3982          54 :                 } else if (rc == ERANGE) {
    3983           0 :                         return ERANGE;
    3984             :                 }
    3985             :         }
    3986          34 :         *h_errnop = h_errno;
    3987          34 :         return ENOENT;
    3988             : }
    3989             : 
    3990             : int gethostbyname_r(const char *name,
    3991             :                     struct hostent *ret,
    3992             :                     char *buf, size_t buflen,
    3993             :                     struct hostent **result, int *h_errnop)
    3994             : {
    3995         197 :         if (!nss_wrapper_hosts_enabled()) {
    3996           3 :                 return libc_gethostbyname_r(name,
    3997             :                                             ret,
    3998             :                                             buf,
    3999             :                                             buflen,
    4000             :                                             result,
    4001             :                                             h_errnop);
    4002             :         }
    4003             : 
    4004         194 :         return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
    4005             : }
    4006             : #endif
    4007             : 
    4008             : #ifdef HAVE_GETHOSTBYNAME2_R
    4009           0 : static int nwrap_gethostbyname2_r(const char *name, int af,
    4010             :                                  struct hostent *ret,
    4011             :                                  char *buf, size_t buflen,
    4012             :                                  struct hostent **result, int *h_errnop)
    4013             : {
    4014             :         int rc;
    4015             :         size_t i;
    4016             : 
    4017           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4018           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4019           0 :                 rc = b->ops->nw_gethostbyname2_r(b, name, af, ret,
    4020             :                                                  buf, buflen, result);
    4021           0 :                 if (rc == 0) {
    4022           0 :                         return 0;
    4023           0 :                 } else if (rc == ERANGE) {
    4024           0 :                         return ERANGE;
    4025             :                 }
    4026             :         }
    4027           0 :         *h_errnop = h_errno;
    4028           0 :         return ENOENT;
    4029             : }
    4030             : 
    4031             : int gethostbyname2_r(const char *name, int af,
    4032             :                      struct hostent *ret,
    4033             :                      char *buf, size_t buflen,
    4034             :                      struct hostent **result, int *h_errnop)
    4035             : {
    4036           0 :         if (!nss_wrapper_hosts_enabled()) {
    4037           0 :                 return libc_gethostbyname2_r(name, af, ret, buf, buflen,
    4038             :                                              result, h_errnop);
    4039             :         }
    4040             : 
    4041           0 :         return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result,
    4042             :                                       h_errnop);
    4043             : }
    4044             : #endif
    4045             : 
    4046      923221 : static int nwrap_files_getaddrinfo(const char *name,
    4047             :                                    unsigned short port,
    4048             :                                    const struct addrinfo *hints,
    4049             :                                    struct addrinfo **ai)
    4050             : {
    4051             :         struct nwrap_entlist *el;
    4052             :         struct hostent *he;
    4053      923221 :         struct addrinfo *ai_head = NULL;
    4054      923221 :         struct addrinfo *ai_cur = NULL;
    4055             :         char *h_name_lower;
    4056             :         size_t name_len;
    4057      923221 :         char canon_name[DNS_NAME_MAX] = { 0 };
    4058      923221 :         bool skip_canonname = false;
    4059      923221 :         ENTRY e = {
    4060             :                 .key = NULL,
    4061             :         };
    4062      923221 :         ENTRY *e_p = NULL;
    4063             :         int rc;
    4064             :         bool ok;
    4065             : 
    4066      923221 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4067      923221 :         if (!ok) {
    4068           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    4069           0 :                 return EAI_SYSTEM;
    4070             :         }
    4071             : 
    4072      923221 :         name_len = strlen(name);
    4073      923221 :         if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
    4074         924 :                 memcpy(canon_name, name, name_len - 1);
    4075         924 :                 canon_name[name_len] = '\0';
    4076         924 :                 name = canon_name;
    4077             :         }
    4078             : 
    4079      923221 :         if (!str_tolower_copy(&h_name_lower, name)) {
    4080           0 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    4081             :                           "Out of memory while converting to lower case");
    4082           0 :                 return EAI_MEMORY;
    4083             :         }
    4084             : 
    4085      923221 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
    4086      923221 :         e.key = h_name_lower;
    4087      904819 :         e.data = NULL;
    4088      923221 :         e_p = hsearch(e, FIND);
    4089      923221 :         if (e_p == NULL) {
    4090      674357 :                 NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
    4091      674357 :                 SAFE_FREE(h_name_lower);
    4092      674357 :                 errno = ENOENT;
    4093      674357 :                 return EAI_NONAME;
    4094             :         }
    4095      248864 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
    4096      248864 :         SAFE_FREE(h_name_lower);
    4097             : 
    4098      248864 :         rc = EAI_NONAME;
    4099      519274 :         for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
    4100             :         {
    4101             :                 int rc2;
    4102      270410 :                 struct addrinfo *ai_new = NULL;
    4103             : 
    4104      270410 :                 he = &(el->ed->ht);
    4105             : 
    4106      271160 :                 if (hints->ai_family != AF_UNSPEC &&
    4107         750 :                     he->h_addrtype != hints->ai_family)
    4108             :                 {
    4109          26 :                         NWRAP_LOG(NWRAP_LOG_DEBUG,
    4110             :                                   "Entry found but with wrong AF - "
    4111             :                                   "remembering EAI_ADDRINFO.");
    4112          26 :                         rc = EAI_ADDRFAMILY;
    4113          26 :                         continue;
    4114             :                 }
    4115             : 
    4116             :                 /* Function allocates memory and returns it in ai. */
    4117      270384 :                 rc2 = nwrap_convert_he_ai(he,
    4118             :                                          port,
    4119             :                                          hints,
    4120             :                                          &ai_new,
    4121             :                                          skip_canonname);
    4122      270384 :                 if (rc2 != 0) {
    4123           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
    4124           0 :                         if (ai_head != NULL) {
    4125           0 :                                 freeaddrinfo(ai_head);
    4126             :                         }
    4127           0 :                         return rc2;
    4128             :                 }
    4129      270384 :                 skip_canonname = true;
    4130             : 
    4131      270384 :                 if (ai_head == NULL) {
    4132      248864 :                         ai_head = ai_new;
    4133             :                 }
    4134      270384 :                 if (ai_cur != NULL) {
    4135       21520 :                         ai_cur->ai_next = ai_new;
    4136             :                 }
    4137      270384 :                 ai_cur = ai_new;
    4138             :         }
    4139             : 
    4140      248864 :         if (ai_head != NULL) {
    4141      248864 :                 rc = 0;
    4142             :         }
    4143             : 
    4144      248864 :         *ai = ai_head;
    4145             : 
    4146      248864 :         return rc;
    4147             : }
    4148             : 
    4149         105 : static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b,
    4150             :                                                  const void *addr,
    4151             :                                                  socklen_t len, int type)
    4152             : {
    4153             :         struct hostent *he;
    4154         105 :         char ip[NWRAP_INET_ADDRSTRLEN] = {0};
    4155             :         struct nwrap_entdata *ed;
    4156             :         const char *a;
    4157             :         size_t i;
    4158             :         bool ok;
    4159             : 
    4160             :         (void) b; /* unused */
    4161             :         (void) len; /* unused */
    4162             : 
    4163         105 :         ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4164         105 :         if (!ok) {
    4165           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
    4166           0 :                 return NULL;
    4167             :         }
    4168             : 
    4169         105 :         a = inet_ntop(type, addr, ip, sizeof(ip));
    4170         105 :         if (a == NULL) {
    4171           0 :                 errno = EINVAL;
    4172           0 :                 return NULL;
    4173             :         }
    4174             : 
    4175         401 :         nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
    4176             :         {
    4177         401 :                 he = &(ed->ht);
    4178         401 :                 if (he->h_addrtype != type) {
    4179         148 :                         continue;
    4180             :                 }
    4181             : 
    4182         253 :                 if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
    4183         105 :                         return he;
    4184             :                 }
    4185             :         }
    4186             : 
    4187           0 :         errno = ENOENT;
    4188           0 :         return NULL;
    4189             : }
    4190             : 
    4191             : #ifdef HAVE_GETHOSTBYADDR_R
    4192           6 : static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
    4193             :                                  struct hostent *ret,
    4194             :                                  char *buf, size_t buflen,
    4195             :                                  struct hostent **result, int *h_errnop)
    4196             : {
    4197             :         size_t i;
    4198           6 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4199           6 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4200           6 :                 *result = b->ops->nw_gethostbyaddr(b, addr, len, type);
    4201           6 :                 if (*result != NULL) {
    4202           6 :                         break;
    4203             :                 }
    4204             :         }
    4205             : 
    4206           6 :         if (*result != NULL) {
    4207           6 :                 memset(buf, '\0', buflen);
    4208           6 :                 *ret = **result;
    4209           6 :                 return 0;
    4210             :         }
    4211             : 
    4212           0 :         *h_errnop = h_errno;
    4213           0 :         return -1;
    4214             : }
    4215             : 
    4216             : int gethostbyaddr_r(const void *addr, socklen_t len, int type,
    4217             :                     struct hostent *ret,
    4218             :                     char *buf, size_t buflen,
    4219             :                     struct hostent **result, int *h_errnop)
    4220             : {
    4221           6 :         if (!nss_wrapper_hosts_enabled()) {
    4222           0 :                 return libc_gethostbyaddr_r(addr,
    4223             :                                             len,
    4224             :                                             type,
    4225             :                                             ret,
    4226             :                                             buf,
    4227             :                                             buflen,
    4228             :                                             result,
    4229             :                                             h_errnop);
    4230             :         }
    4231             : 
    4232           6 :         return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
    4233             : }
    4234             : #endif
    4235             : 
    4236             : /* hosts enum functions */
    4237           0 : static void nwrap_files_sethostent(void)
    4238             : {
    4239           0 :         nwrap_he_global.idx = 0;
    4240           0 : }
    4241             : 
    4242           0 : static struct hostent *nwrap_files_gethostent(void)
    4243             : {
    4244             :         struct hostent *he;
    4245             : 
    4246           0 :         if (nwrap_he_global.idx == 0) {
    4247             :                 bool ok;
    4248             : 
    4249           0 :                 ok = nwrap_files_cache_reload(nwrap_he_global.cache);
    4250           0 :                 if (!ok) {
    4251           0 :                         NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
    4252           0 :                         return NULL;
    4253             :                 }
    4254             :         }
    4255             : 
    4256           0 :         if (nwrap_he_global.idx >= nwrap_he_global.num) {
    4257           0 :                 errno = ENOENT;
    4258           0 :                 return NULL;
    4259             :         }
    4260             : 
    4261           0 :         he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
    4262             : 
    4263           0 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
    4264             : 
    4265           0 :         return he;
    4266             : }
    4267             : 
    4268           0 : static void nwrap_files_endhostent(void)
    4269             : {
    4270           0 :         nwrap_he_global.idx = 0;
    4271           0 : }
    4272             : 
    4273             : /*
    4274             :  * module backend
    4275             :  */
    4276             : 
    4277             : 
    4278       16367 : static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
    4279             :                                             const char *name)
    4280             : {
    4281             :         static struct passwd pwd;
    4282             :         static char buf[1000];
    4283             :         NSS_STATUS status;
    4284             : 
    4285       16367 :         if (b->symbols->_nss_getpwnam_r.f == NULL) {
    4286           0 :                 return NULL;
    4287             :         }
    4288             : 
    4289       16367 :         status = b->symbols->_nss_getpwnam_r.f(name,
    4290             :                                                &pwd,
    4291             :                                                buf,
    4292             :                                                sizeof(buf),
    4293             :                                                &errno);
    4294       16367 :         if (status == NSS_STATUS_NOTFOUND) {
    4295        4241 :                 return NULL;
    4296             :         }
    4297       12120 :         if (status != NSS_STATUS_SUCCESS) {
    4298        1004 :                 return NULL;
    4299             :         }
    4300             : 
    4301       11110 :         return &pwd;
    4302             : }
    4303             : 
    4304         937 : static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
    4305             :                                    const char *name, struct passwd *pwdst,
    4306             :                                    char *buf, size_t buflen, struct passwd **pwdstp)
    4307             : {
    4308             :         int ret;
    4309             : 
    4310         937 :         *pwdstp = NULL;
    4311             : 
    4312         937 :         if (b->symbols->_nss_getpwnam_r.f == NULL) {
    4313           0 :                 return NSS_STATUS_NOTFOUND;
    4314             :         }
    4315             : 
    4316         937 :         ret = b->symbols->_nss_getpwnam_r.f(name, pwdst, buf, buflen, &errno);
    4317         937 :         switch (ret) {
    4318         937 :         case NSS_STATUS_SUCCESS:
    4319         937 :                 *pwdstp = pwdst;
    4320         937 :                 return 0;
    4321           0 :         case NSS_STATUS_NOTFOUND:
    4322           0 :                 if (errno != 0) {
    4323           0 :                         return errno;
    4324             :                 }
    4325           0 :                 return ENOENT;
    4326           0 :         case NSS_STATUS_TRYAGAIN:
    4327           0 :                 if (errno != 0) {
    4328           0 :                         return errno;
    4329             :                 }
    4330           0 :                 return ERANGE;
    4331           0 :         default:
    4332           0 :                 if (errno != 0) {
    4333           0 :                         return errno;
    4334             :                 }
    4335           0 :                 return ret;
    4336             :         }
    4337             : }
    4338             : 
    4339        2674 : static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b,
    4340             :                                             uid_t uid)
    4341             : {
    4342             :         static struct passwd pwd;
    4343             :         static char buf[1000];
    4344             :         NSS_STATUS status;
    4345             : 
    4346        2674 :         if (b->symbols->_nss_getpwuid_r.f == NULL) {
    4347           0 :                 return NULL;
    4348             :         }
    4349             : 
    4350        2674 :         status = b->symbols->_nss_getpwuid_r.f(uid,
    4351             :                                                &pwd,
    4352             :                                                buf,
    4353             :                                                sizeof(buf),
    4354             :                                                &errno);
    4355        2674 :         if (status == NSS_STATUS_NOTFOUND) {
    4356        1342 :                 return NULL;
    4357             :         }
    4358        1332 :         if (status != NSS_STATUS_SUCCESS) {
    4359          36 :                 return NULL;
    4360             :         }
    4361        1296 :         return &pwd;
    4362             : }
    4363             : 
    4364         692 : static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
    4365             :                                    uid_t uid, struct passwd *pwdst,
    4366             :                                    char *buf, size_t buflen, struct passwd **pwdstp)
    4367             : {
    4368             :         int ret;
    4369             : 
    4370         692 :         *pwdstp = NULL;
    4371             : 
    4372         692 :         if (b->symbols->_nss_getpwuid_r.f == NULL) {
    4373           0 :                 return ENOENT;
    4374             :         }
    4375             : 
    4376         692 :         ret = b->symbols->_nss_getpwuid_r.f(uid, pwdst, buf, buflen, &errno);
    4377         692 :         switch (ret) {
    4378         688 :         case NSS_STATUS_SUCCESS:
    4379         688 :                 *pwdstp = pwdst;
    4380         688 :                 return 0;
    4381           0 :         case NSS_STATUS_NOTFOUND:
    4382           0 :                 if (errno != 0) {
    4383           0 :                         return errno;
    4384             :                 }
    4385           0 :                 return ENOENT;
    4386           0 :         case NSS_STATUS_TRYAGAIN:
    4387           0 :                 if (errno != 0) {
    4388           0 :                         return errno;
    4389             :                 }
    4390           0 :                 return ERANGE;
    4391           4 :         default:
    4392           4 :                 if (errno != 0) {
    4393           4 :                         return errno;
    4394             :                 }
    4395           0 :                 return ret;
    4396             :         }
    4397             : }
    4398             : 
    4399          64 : static void nwrap_module_setpwent(struct nwrap_backend *b)
    4400             : {
    4401          64 :         if (b->symbols->_nss_setpwent.f == NULL) {
    4402           0 :                 return;
    4403             :         }
    4404             : 
    4405          64 :         b->symbols->_nss_setpwent.f();
    4406             : }
    4407             : 
    4408        2052 : static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b)
    4409             : {
    4410             :         static struct passwd pwd;
    4411             :         static char buf[1000];
    4412             :         NSS_STATUS status;
    4413             : 
    4414        2052 :         if (b->symbols->_nss_getpwent_r.f == NULL) {
    4415           0 :                 return NULL;
    4416             :         }
    4417             : 
    4418        2052 :         status = b->symbols->_nss_getpwent_r.f(&pwd, buf, sizeof(buf), &errno);
    4419        2052 :         if (status == NSS_STATUS_NOTFOUND) {
    4420          42 :                 return NULL;
    4421             :         }
    4422        2010 :         if (status != NSS_STATUS_SUCCESS) {
    4423           6 :                 return NULL;
    4424             :         }
    4425        2004 :         return &pwd;
    4426             : }
    4427             : 
    4428        1352 : static int nwrap_module_getpwent_r(struct nwrap_backend *b,
    4429             :                                    struct passwd *pwdst, char *buf,
    4430             :                                    size_t buflen, struct passwd **pwdstp)
    4431             : {
    4432             :         int ret;
    4433             : 
    4434        1352 :         *pwdstp = NULL;
    4435             : 
    4436        1352 :         if (b->symbols->_nss_getpwent_r.f == NULL) {
    4437           0 :                 return ENOENT;
    4438             :         }
    4439             : 
    4440        1352 :         ret = b->symbols->_nss_getpwent_r.f(pwdst, buf, buflen, &errno);
    4441        1352 :         switch (ret) {
    4442        1336 :         case NSS_STATUS_SUCCESS:
    4443        1336 :                 *pwdstp = pwdst;
    4444        1336 :                 return 0;
    4445          16 :         case NSS_STATUS_NOTFOUND:
    4446          16 :                 if (errno != 0) {
    4447          16 :                         return errno;
    4448             :                 }
    4449           0 :                 return ENOENT;
    4450           0 :         case NSS_STATUS_TRYAGAIN:
    4451           0 :                 if (errno != 0) {
    4452           0 :                         return errno;
    4453             :                 }
    4454           0 :                 return ERANGE;
    4455           0 :         default:
    4456           0 :                 if (errno != 0) {
    4457           0 :                         return errno;
    4458             :                 }
    4459           0 :                 return ret;
    4460             :         }
    4461             : }
    4462             : 
    4463        2639 : static void nwrap_module_endpwent(struct nwrap_backend *b)
    4464             : {
    4465        2639 :         if (b->symbols->_nss_endpwent.f) {
    4466        2639 :                 return;
    4467             :         }
    4468             : 
    4469           0 :         b->symbols->_nss_endpwent.f();
    4470             : }
    4471             : 
    4472           0 : static int nwrap_module_initgroups(struct nwrap_backend *b,
    4473             :                                    const char *user, gid_t group)
    4474             : {
    4475             :         gid_t *groups;
    4476             :         long int start;
    4477             :         long int size;
    4478             : 
    4479           0 :         if (b->symbols->_nss_initgroups.f == NULL) {
    4480           0 :                 return NSS_STATUS_UNAVAIL;
    4481             :         }
    4482             : 
    4483           0 :         return b->symbols->_nss_initgroups.f(user,
    4484             :                                              group,
    4485             :                                              &start,
    4486             :                                              &size,
    4487             :                                              &groups,
    4488             :                                              0,
    4489             :                                              &errno);
    4490             : }
    4491             : 
    4492         543 : static struct group *nwrap_module_getgrnam(struct nwrap_backend *b,
    4493             :                                            const char *name)
    4494             : {
    4495             :         static struct group grp;
    4496             :         static char *buf;
    4497             :         static int buflen = 1000;
    4498             :         NSS_STATUS status;
    4499             : 
    4500         543 :         if (b->symbols->_nss_getgrnam_r.f == NULL) {
    4501           0 :                 return NULL;
    4502             :         }
    4503             : 
    4504         543 :         if (!buf) {
    4505         519 :                 buf = (char *)malloc(buflen);
    4506             :         }
    4507         567 : again:
    4508         543 :         status = b->symbols->_nss_getgrnam_r.f(name, &grp, buf, buflen, &errno);
    4509         543 :         if (status == NSS_STATUS_TRYAGAIN) {
    4510           0 :                 buflen *= 2;
    4511           0 :                 buf = (char *)realloc(buf, buflen);
    4512           0 :                 if (!buf) {
    4513           0 :                         return NULL;
    4514             :                 }
    4515           0 :                 goto again;
    4516             :         }
    4517         543 :         if (status == NSS_STATUS_NOTFOUND) {
    4518         503 :                 SAFE_FREE(buf);
    4519         503 :                 return NULL;
    4520             :         }
    4521          40 :         if (status != NSS_STATUS_SUCCESS) {
    4522           0 :                 SAFE_FREE(buf);
    4523           0 :                 return NULL;
    4524             :         }
    4525          40 :         return &grp;
    4526             : }
    4527             : 
    4528           0 : static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
    4529             :                                    const char *name, struct group *grdst,
    4530             :                                    char *buf, size_t buflen, struct group **grdstp)
    4531             : {
    4532             :         int ret;
    4533             : 
    4534           0 :         *grdstp = NULL;
    4535             : 
    4536           0 :         if (b->symbols->_nss_getgrnam_r.f == NULL) {
    4537           0 :                 return ENOENT;
    4538             :         }
    4539             : 
    4540           0 :         ret = b->symbols->_nss_getgrnam_r.f(name, grdst, buf, buflen, &errno);
    4541           0 :         switch (ret) {
    4542           0 :         case NSS_STATUS_SUCCESS:
    4543           0 :                 *grdstp = grdst;
    4544           0 :                 return 0;
    4545           0 :         case NSS_STATUS_NOTFOUND:
    4546           0 :                 if (errno != 0) {
    4547           0 :                         return errno;
    4548             :                 }
    4549           0 :                 return ENOENT;
    4550           0 :         case NSS_STATUS_TRYAGAIN:
    4551           0 :                 if (errno != 0) {
    4552           0 :                         return errno;
    4553             :                 }
    4554           0 :                 return ERANGE;
    4555           0 :         default:
    4556           0 :                 if (errno != 0) {
    4557           0 :                         return errno;
    4558             :                 }
    4559           0 :                 return ret;
    4560             :         }
    4561             : }
    4562             : 
    4563         594 : static struct group *nwrap_module_getgrgid(struct nwrap_backend *b,
    4564             :                                            gid_t gid)
    4565             : {
    4566             :         static struct group grp;
    4567             :         static char *buf;
    4568             :         static int buflen = 1000;
    4569             :         NSS_STATUS status;
    4570             : 
    4571         594 :         if (b->symbols->_nss_getgrgid_r.f == NULL) {
    4572           0 :                 return NULL;
    4573             :         }
    4574             : 
    4575         594 :         if (!buf) {
    4576          50 :                 buf = (char *)malloc(buflen);
    4577             :         }
    4578             : 
    4579        1138 : again:
    4580         594 :         status = b->symbols->_nss_getgrgid_r.f(gid, &grp, buf, buflen, &errno);
    4581         594 :         if (status == NSS_STATUS_TRYAGAIN) {
    4582           0 :                 buflen *= 2;
    4583           0 :                 buf = (char *)realloc(buf, buflen);
    4584           0 :                 if (!buf) {
    4585           0 :                         return NULL;
    4586             :                 }
    4587           0 :                 goto again;
    4588             :         }
    4589         594 :         if (status == NSS_STATUS_NOTFOUND) {
    4590          10 :                 SAFE_FREE(buf);
    4591          10 :                 return NULL;
    4592             :         }
    4593         584 :         if (status != NSS_STATUS_SUCCESS) {
    4594           0 :                 SAFE_FREE(buf);
    4595           0 :                 return NULL;
    4596             :         }
    4597         584 :         return &grp;
    4598             : }
    4599             : 
    4600           4 : static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
    4601             :                                    gid_t gid, struct group *grdst,
    4602             :                                    char *buf, size_t buflen, struct group **grdstp)
    4603             : {
    4604             :         int ret;
    4605             : 
    4606           4 :         *grdstp = NULL;
    4607             : 
    4608           4 :         if (b->symbols->_nss_getgrgid_r.f == NULL) {
    4609           0 :                 return ENOENT;
    4610             :         }
    4611             : 
    4612           4 :         ret = b->symbols->_nss_getgrgid_r.f(gid, grdst, buf, buflen, &errno);
    4613           4 :         switch (ret) {
    4614           0 :         case NSS_STATUS_SUCCESS:
    4615           0 :                 *grdstp = grdst;
    4616           0 :                 return 0;
    4617           0 :         case NSS_STATUS_NOTFOUND:
    4618           0 :                 if (errno != 0) {
    4619           0 :                         return errno;
    4620             :                 }
    4621           0 :                 return ENOENT;
    4622           0 :         case NSS_STATUS_TRYAGAIN:
    4623           0 :                 if (errno != 0) {
    4624           0 :                         return errno;
    4625             :                 }
    4626           0 :                 return ERANGE;
    4627           4 :         default:
    4628           4 :                 if (errno != 0) {
    4629           4 :                         return errno;
    4630             :                 }
    4631           0 :                 return ret;
    4632             :         }
    4633             : }
    4634             : 
    4635       39872 : static void nwrap_module_setgrent(struct nwrap_backend *b)
    4636             : {
    4637       39872 :         if (b->symbols->_nss_setgrent.f) {
    4638       39864 :                 return;
    4639             :         }
    4640             : 
    4641           0 :         b->symbols->_nss_setgrent.f();
    4642             : }
    4643             : 
    4644       39860 : static struct group *nwrap_module_getgrent(struct nwrap_backend *b)
    4645             : {
    4646             :         static struct group grp;
    4647             :         static char *buf;
    4648             :         static int buflen = 1024;
    4649             :         NSS_STATUS status;
    4650             : 
    4651       39860 :         if (b->symbols->_nss_getgrent_r.f == NULL) {
    4652           0 :                 return NULL;
    4653             :         }
    4654             : 
    4655       39860 :         if (!buf) {
    4656       39860 :                 buf = (char *)malloc(buflen);
    4657             :         }
    4658             : 
    4659       39852 : again:
    4660       39860 :         status = b->symbols->_nss_getgrent_r.f(&grp, buf, buflen, &errno);
    4661       39860 :         if (status == NSS_STATUS_TRYAGAIN) {
    4662           0 :                 buflen *= 2;
    4663           0 :                 buf = (char *)realloc(buf, buflen);
    4664           0 :                 if (!buf) {
    4665           0 :                         return NULL;
    4666             :                 }
    4667           0 :                 goto again;
    4668             :         }
    4669       39860 :         if (status == NSS_STATUS_NOTFOUND) {
    4670       39860 :                 SAFE_FREE(buf);
    4671       39852 :                 return NULL;
    4672             :         }
    4673           0 :         if (status != NSS_STATUS_SUCCESS) {
    4674           0 :                 SAFE_FREE(buf);
    4675           0 :                 return NULL;
    4676             :         }
    4677           0 :         return &grp;
    4678             : }
    4679             : 
    4680          12 : static int nwrap_module_getgrent_r(struct nwrap_backend *b,
    4681             :                                    struct group *grdst, char *buf,
    4682             :                                    size_t buflen, struct group **grdstp)
    4683             : {
    4684             :         int ret;
    4685             : 
    4686          12 :         *grdstp = NULL;
    4687             : 
    4688          12 :         if (b->symbols->_nss_getgrent_r.f == NULL) {
    4689           0 :                 return ENOENT;
    4690             :         }
    4691             : 
    4692          12 :         ret = b->symbols->_nss_getgrent_r.f(grdst, buf, buflen, &errno);
    4693          12 :         switch (ret) {
    4694           0 :         case NSS_STATUS_SUCCESS:
    4695           0 :                 *grdstp = grdst;
    4696           0 :                 return 0;
    4697          12 :         case NSS_STATUS_NOTFOUND:
    4698          12 :                 if (errno != 0) {
    4699          12 :                         return errno;
    4700             :                 }
    4701           0 :                 return ENOENT;
    4702           0 :         case NSS_STATUS_TRYAGAIN:
    4703           0 :                 if (errno != 0) {
    4704           0 :                         return errno;
    4705             :                 }
    4706           0 :                 return ERANGE;
    4707           0 :         default:
    4708           0 :                 if (errno != 0) {
    4709           0 :                         return errno;
    4710             :                 }
    4711           0 :                 return ret;
    4712             :         }
    4713             : }
    4714             : 
    4715       39872 : static void nwrap_module_endgrent(struct nwrap_backend *b)
    4716             : {
    4717       39872 :         if (b->symbols->_nss_endgrent.f == NULL) {
    4718           0 :                 return;
    4719             :         }
    4720             : 
    4721       39872 :         b->symbols->_nss_endgrent.f();
    4722             : }
    4723             : 
    4724           0 : static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b,
    4725             :                                                   const void *addr,
    4726             :                                                   socklen_t len, int type)
    4727             : {
    4728             :         static struct hostent he;
    4729             :         static char *buf = NULL;
    4730             :         static size_t buflen = 1000;
    4731             :         NSS_STATUS status;
    4732             : 
    4733           0 :         if (b->symbols->_nss_gethostbyaddr_r.f == NULL) {
    4734           0 :                 return NULL;
    4735             :         }
    4736             : 
    4737           0 :         if (buf == NULL) {
    4738           0 :                 buf = (char *)malloc(buflen);
    4739           0 :                 if (buf == NULL) {
    4740           0 :                         return NULL;
    4741             :                 }
    4742             :         }
    4743           0 : again:
    4744           0 :         status = b->symbols->_nss_gethostbyaddr_r.f(addr,
    4745             :                                                     len,
    4746             :                                                     type,
    4747             :                                                     &he,
    4748             :                                                     buf,
    4749             :                                                     buflen,
    4750             :                                                     &errno,
    4751             :                                                     &h_errno);
    4752           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4753           0 :                 char *p = NULL;
    4754             : 
    4755           0 :                 buflen *= 2;
    4756           0 :                 p = (char *)realloc(buf, buflen);
    4757           0 :                 if (p == NULL) {
    4758           0 :                         SAFE_FREE(buf);
    4759           0 :                         return NULL;
    4760             :                 }
    4761           0 :                 buf = p;
    4762           0 :                 goto again;
    4763             :         }
    4764           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4765           0 :                 SAFE_FREE(buf);
    4766           0 :                 return NULL;
    4767             :         }
    4768           0 :         if (status != NSS_STATUS_SUCCESS) {
    4769           0 :                 SAFE_FREE(buf);
    4770           0 :                 return NULL;
    4771             :         }
    4772             : 
    4773           0 :         return &he;
    4774             : }
    4775             : 
    4776          20 : static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b,
    4777             :                                          const char *name, int af,
    4778             :                                          struct hostent *hedst,
    4779             :                                          char *buf, size_t buflen,
    4780             :                                          struct hostent **hedstp)
    4781             : {
    4782             :         NSS_STATUS status;
    4783             : 
    4784          20 :         *hedstp = NULL;
    4785             : 
    4786          20 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4787          20 :                 return ENOENT;
    4788             :         }
    4789             : 
    4790           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4791             :                                                      af,
    4792             :                                                      hedst,
    4793             :                                                      buf,
    4794             :                                                      buflen,
    4795             :                                                      &errno,
    4796             :                                                      &h_errno);
    4797           0 :         switch (status) {
    4798           0 :         case NSS_STATUS_SUCCESS:
    4799           0 :                 *hedstp = hedst;
    4800           0 :                 return 0;
    4801           0 :         case NSS_STATUS_NOTFOUND:
    4802           0 :                 if (errno != 0) {
    4803           0 :                         return errno;
    4804             :                 }
    4805           0 :                 return ENOENT;
    4806           0 :         case NSS_STATUS_TRYAGAIN:
    4807           0 :                 if (errno != 0) {
    4808           0 :                         return errno;
    4809             :                 }
    4810           0 :                 return ERANGE;
    4811           0 :         default:
    4812           0 :                 if (errno != 0) {
    4813           0 :                         return errno;
    4814             :                 }
    4815           0 :                 return status;
    4816             :         }
    4817             : }
    4818             : 
    4819           0 : static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b,
    4820             :                                                   const char *name)
    4821             : {
    4822             :         static struct hostent he;
    4823             :         static char *buf = NULL;
    4824             :         static size_t buflen = 1000;
    4825             :         NSS_STATUS status;
    4826             : 
    4827           0 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4828           0 :                 return NULL;
    4829             :         }
    4830             : 
    4831           0 :         if (buf == NULL) {
    4832           0 :                 buf = (char *)malloc(buflen);
    4833           0 :                 if (buf == NULL) {
    4834           0 :                         return NULL;
    4835             :                 }
    4836             :         }
    4837             : 
    4838           0 : again:
    4839           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4840             :                                                      AF_UNSPEC,
    4841             :                                                      &he,
    4842             :                                                      buf,
    4843             :                                                      buflen,
    4844             :                                                      &errno,
    4845             :                                                      &h_errno);
    4846           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4847           0 :                 char *p = NULL;
    4848             : 
    4849           0 :                 buflen *= 2;
    4850           0 :                 p = (char *)realloc(buf, buflen);
    4851           0 :                 if (p == NULL) {
    4852           0 :                         SAFE_FREE(buf);
    4853           0 :                         return NULL;
    4854             :                 }
    4855           0 :                 buf = p;
    4856           0 :                 goto again;
    4857             :         }
    4858           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4859           0 :                 SAFE_FREE(buf);
    4860           0 :                 return NULL;
    4861             :         }
    4862           0 :         if (status != NSS_STATUS_SUCCESS) {
    4863           0 :                 SAFE_FREE(buf);
    4864           0 :                 return NULL;
    4865             :         }
    4866             : 
    4867           0 :         return &he;
    4868             : }
    4869             : 
    4870           0 : static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b,
    4871             :                                                    const char *name, int af)
    4872             : {
    4873             :         static struct hostent he;
    4874             :         static char *buf = NULL;
    4875             :         static size_t buflen = 1000;
    4876             :         NSS_STATUS status;
    4877             : 
    4878           0 :         if (b->symbols->_nss_gethostbyname2_r.f == NULL) {
    4879           0 :                 return NULL;
    4880             :         }
    4881             : 
    4882           0 :         if (buf == NULL) {
    4883           0 :                 buf = (char *)malloc(buflen);
    4884           0 :                 if (buf == NULL) {
    4885           0 :                         return NULL;
    4886             :                 }
    4887             :         }
    4888             : 
    4889           0 : again:
    4890           0 :         status = b->symbols->_nss_gethostbyname2_r.f(name,
    4891             :                                                      af,
    4892             :                                                      &he,
    4893             :                                                      buf,
    4894             :                                                      buflen,
    4895             :                                                      &errno,
    4896             :                                                      &h_errno);
    4897           0 :         if (status == NSS_STATUS_TRYAGAIN) {
    4898           0 :                 char *p = NULL;
    4899             : 
    4900           0 :                 buflen *= 2;
    4901           0 :                 p = (char *)realloc(buf, buflen);
    4902           0 :                 if (p == NULL) {
    4903           0 :                         SAFE_FREE(buf);
    4904           0 :                         return NULL;
    4905             :                 }
    4906           0 :                 buf = p;
    4907           0 :                 goto again;
    4908             :         }
    4909           0 :         if (status == NSS_STATUS_NOTFOUND) {
    4910           0 :                 SAFE_FREE(buf);
    4911           0 :                 return NULL;
    4912             :         }
    4913           0 :         if (status != NSS_STATUS_SUCCESS) {
    4914           0 :                 SAFE_FREE(buf);
    4915           0 :                 return NULL;
    4916             :         }
    4917             : 
    4918           0 :         return &he;
    4919             : }
    4920             : 
    4921             : /****************************************************************************
    4922             :  *   GETPWNAM
    4923             :  ***************************************************************************/
    4924             : 
    4925       44518 : static struct passwd *nwrap_getpwnam(const char *name)
    4926             : {
    4927             :         size_t i;
    4928             :         struct passwd *pwd;
    4929             : 
    4930       74314 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4931       60885 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4932       60885 :                 pwd = b->ops->nw_getpwnam(b, name);
    4933       60885 :                 if (pwd) {
    4934       30555 :                         return pwd;
    4935             :                 }
    4936             :         }
    4937             : 
    4938       13081 :         return NULL;
    4939             : }
    4940             : 
    4941             : struct passwd *getpwnam(const char *name)
    4942             : {
    4943       45624 :         if (!nss_wrapper_enabled()) {
    4944        1106 :                 return libc_getpwnam(name);
    4945             :         }
    4946             : 
    4947       44518 :         return nwrap_getpwnam(name);
    4948             : }
    4949             : 
    4950             : /****************************************************************************
    4951             :  *   GETPWNAM_R
    4952             :  ***************************************************************************/
    4953             : 
    4954        1741 : static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
    4955             :                             char *buf, size_t buflen, struct passwd **pwdstp)
    4956             : {
    4957             :         size_t i;
    4958             :         int ret;
    4959             : 
    4960        5356 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4961        2678 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    4962        2678 :                 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
    4963        2678 :                 if (ret == ENOENT) {
    4964         937 :                         continue;
    4965             :                 }
    4966        1741 :                 return ret;
    4967             :         }
    4968             : 
    4969           0 :         return ENOENT;
    4970             : }
    4971             : 
    4972             : #ifdef HAVE_GETPWNAM_R
    4973             : # ifdef HAVE_SOLARIS_GETPWNAM_R
    4974             : int getpwnam_r(const char *name, struct passwd *pwdst,
    4975             :                char *buf, int buflen, struct passwd **pwdstp)
    4976             : # else /* HAVE_SOLARIS_GETPWNAM_R */
    4977             : int getpwnam_r(const char *name, struct passwd *pwdst,
    4978             :                char *buf, size_t buflen, struct passwd **pwdstp)
    4979             : # endif /* HAVE_SOLARIS_GETPWNAM_R */
    4980             : {
    4981        1741 :         if (!nss_wrapper_enabled()) {
    4982           0 :                 return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
    4983             :         }
    4984             : 
    4985        1741 :         return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
    4986             : }
    4987             : #endif
    4988             : 
    4989             : /****************************************************************************
    4990             :  *   GETPWUID
    4991             :  ***************************************************************************/
    4992             : 
    4993       36126 : static struct passwd *nwrap_getpwuid(uid_t uid)
    4994             : {
    4995             :         size_t i;
    4996             :         struct passwd *pwd;
    4997             : 
    4998       40178 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    4999       38800 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5000       38800 :                 pwd = b->ops->nw_getpwuid(b, uid);
    5001       38800 :                 if (pwd) {
    5002       34287 :                         return pwd;
    5003             :                 }
    5004             :         }
    5005             : 
    5006        1378 :         return NULL;
    5007             : }
    5008             : 
    5009             : struct passwd *getpwuid(uid_t uid)
    5010             : {
    5011       36543 :         if (!nss_wrapper_enabled()) {
    5012         417 :                 return libc_getpwuid(uid);
    5013             :         }
    5014             : 
    5015       36126 :         return nwrap_getpwuid(uid);
    5016             : }
    5017             : 
    5018             : /****************************************************************************
    5019             :  *   GETPWUID_R
    5020             :  ***************************************************************************/
    5021             : 
    5022        1500 : static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
    5023             :                             char *buf, size_t buflen, struct passwd **pwdstp)
    5024             : {
    5025             :         size_t i;
    5026             :         int ret;
    5027             : 
    5028        4392 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5029        2192 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5030        2192 :                 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
    5031        2192 :                 if (ret == ENOENT) {
    5032         696 :                         continue;
    5033             :                 }
    5034        1496 :                 return ret;
    5035             :         }
    5036             : 
    5037           4 :         return ENOENT;
    5038             : }
    5039             : 
    5040             : #ifdef HAVE_SOLARIS_GETPWUID_R
    5041             : int getpwuid_r(uid_t uid, struct passwd *pwdst,
    5042             :                char *buf, int buflen, struct passwd **pwdstp)
    5043             : #else
    5044             : int getpwuid_r(uid_t uid, struct passwd *pwdst,
    5045             :                char *buf, size_t buflen, struct passwd **pwdstp)
    5046             : #endif
    5047             : {
    5048        1503 :         if (!nss_wrapper_enabled()) {
    5049           3 :                 return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
    5050             :         }
    5051             : 
    5052        1500 :         return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
    5053             : }
    5054             : 
    5055             : /****************************************************************************
    5056             :  *   SETPWENT
    5057             :  ***************************************************************************/
    5058             : 
    5059          64 : static void nwrap_setpwent(void)
    5060             : {
    5061             :         size_t i;
    5062             : 
    5063         192 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5064         128 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5065         128 :                 b->ops->nw_setpwent(b);
    5066             :         }
    5067          64 : }
    5068             : 
    5069             : void setpwent(void)
    5070             : {
    5071          64 :         if (!nss_wrapper_enabled()) {
    5072           0 :                 libc_setpwent();
    5073           0 :                 return;
    5074             :         }
    5075             : 
    5076          64 :         nwrap_setpwent();
    5077             : }
    5078             : 
    5079             : /****************************************************************************
    5080             :  *   GETPWENT
    5081             :  ***************************************************************************/
    5082             : 
    5083        3630 : static struct passwd *nwrap_getpwent(void)
    5084             : {
    5085             :         size_t i;
    5086             :         struct passwd *pwd;
    5087             : 
    5088        5730 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5089        5682 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5090        5682 :                 pwd = b->ops->nw_getpwent(b);
    5091        5682 :                 if (pwd) {
    5092        3582 :                         return pwd;
    5093             :                 }
    5094             :         }
    5095             : 
    5096          48 :         return NULL;
    5097             : }
    5098             : 
    5099             : struct passwd *getpwent(void)
    5100             : {
    5101        3630 :         if (!nss_wrapper_enabled()) {
    5102           0 :                 return libc_getpwent();
    5103             :         }
    5104             : 
    5105        3630 :         return nwrap_getpwent();
    5106             : }
    5107             : 
    5108             : /****************************************************************************
    5109             :  *   GETPWENT_R
    5110             :  ***************************************************************************/
    5111             : 
    5112             : #ifdef HAVE_GETPWENT_R
    5113        2156 : static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
    5114             :                             size_t buflen, struct passwd **pwdstp)
    5115             : {
    5116             :         size_t i;
    5117             :         int ret;
    5118             : 
    5119        7048 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5120        3508 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5121        3508 :                 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
    5122        3508 :                 if (ret == ENOENT) {
    5123        1368 :                         continue;
    5124             :                 }
    5125        2140 :                 return ret;
    5126             :         }
    5127             : 
    5128          16 :         return ENOENT;
    5129             : }
    5130             : 
    5131             : #  ifdef HAVE_SOLARIS_GETPWENT_R
    5132             : struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
    5133             : {
    5134             :         struct passwd *pwdstp = NULL;
    5135             :         int rc;
    5136             : 
    5137             :         if (!nss_wrapper_enabled()) {
    5138             :                 return libc_getpwent_r(pwdst, buf, buflen);
    5139             :         }
    5140             :         rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
    5141             :         if (rc < 0) {
    5142             :                 return NULL;
    5143             :         }
    5144             : 
    5145             :         return pwdstp;
    5146             : }
    5147             : #  else /* HAVE_SOLARIS_GETPWENT_R */
    5148             : int getpwent_r(struct passwd *pwdst, char *buf,
    5149             :                size_t buflen, struct passwd **pwdstp)
    5150             : {
    5151        2156 :         if (!nss_wrapper_enabled()) {
    5152           0 :                 return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
    5153             :         }
    5154             : 
    5155        2156 :         return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
    5156             : }
    5157             : #  endif /* HAVE_SOLARIS_GETPWENT_R */
    5158             : #endif /* HAVE_GETPWENT_R */
    5159             : 
    5160             : /****************************************************************************
    5161             :  *   ENDPWENT
    5162             :  ***************************************************************************/
    5163             : 
    5164        2639 : static void nwrap_endpwent(void)
    5165             : {
    5166             :         size_t i;
    5167             : 
    5168        7917 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5169        5278 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5170        5278 :                 b->ops->nw_endpwent(b);
    5171             :         }
    5172        2639 : }
    5173             : 
    5174             : void endpwent(void)
    5175             : {
    5176        2731 :         if (!nss_wrapper_enabled()) {
    5177          92 :                 libc_endpwent();
    5178          92 :                 return;
    5179             :         }
    5180             : 
    5181        2639 :         nwrap_endpwent();
    5182             : }
    5183             : 
    5184             : /****************************************************************************
    5185             :  *   INITGROUPS
    5186             :  ***************************************************************************/
    5187             : 
    5188           0 : static int nwrap_initgroups(const char *user, gid_t group)
    5189             : {
    5190             :         size_t i;
    5191             : 
    5192           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5193           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5194             :                 int rc;
    5195             : 
    5196           0 :                 rc = b->ops->nw_initgroups(b, user, group);
    5197           0 :                 if (rc == 0) {
    5198           0 :                         return 0;
    5199             :                 }
    5200             :         }
    5201             : 
    5202           0 :         errno = ENOENT;
    5203           0 :         return -1;
    5204             : }
    5205             : 
    5206             : int initgroups(const char *user, gid_t group)
    5207             : {
    5208           0 :         if (!nss_wrapper_enabled()) {
    5209           0 :                 return libc_initgroups(user, group);
    5210             :         }
    5211             : 
    5212           0 :         return nwrap_initgroups(user, group);
    5213             : }
    5214             : 
    5215             : /****************************************************************************
    5216             :  *   GETGRNAM
    5217             :  ***************************************************************************/
    5218             : 
    5219        2108 : static struct group *nwrap_getgrnam(const char *name)
    5220             : {
    5221             :         size_t i;
    5222             :         struct group *grp;
    5223             : 
    5224        3262 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5225        2651 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5226        2651 :                 grp = b->ops->nw_getgrnam(b, name);
    5227        2651 :                 if (grp) {
    5228        1495 :                         return grp;
    5229             :                 }
    5230             :         }
    5231             : 
    5232         607 :         return NULL;
    5233             : }
    5234             : 
    5235             : struct group *getgrnam(const char *name)
    5236             : {
    5237        2301 :         if (!nss_wrapper_enabled()) {
    5238         193 :                 return libc_getgrnam(name);
    5239             :         }
    5240             : 
    5241        2108 :         return nwrap_getgrnam(name);
    5242             : }
    5243             : 
    5244             : /****************************************************************************
    5245             :  *   GETGRNAM_R
    5246             :  ***************************************************************************/
    5247             : 
    5248         708 : static int nwrap_getgrnam_r(const char *name, struct group *grdst,
    5249             :                             char *buf, size_t buflen, struct group **grdstp)
    5250             : {
    5251             :         size_t i;
    5252             :         int ret;
    5253             : 
    5254        1416 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5255         708 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5256         708 :                 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
    5257         708 :                 if (ret == ENOENT) {
    5258           0 :                         continue;
    5259             :                 }
    5260         708 :                 return ret;
    5261             :         }
    5262             : 
    5263           0 :         return ENOENT;
    5264             : }
    5265             : 
    5266             : #ifdef HAVE_GETGRNAM_R
    5267             : # ifdef HAVE_SOLARIS_GETGRNAM_R
    5268             : int getgrnam_r(const char *name, struct group *grp,
    5269             :                 char *buf, int buflen, struct group **pgrp)
    5270             : # else /* HAVE_SOLARIS_GETGRNAM_R */
    5271             : int getgrnam_r(const char *name, struct group *grp,
    5272             :                char *buf, size_t buflen, struct group **pgrp)
    5273             : # endif /* HAVE_SOLARIS_GETGRNAM_R */
    5274             : {
    5275         708 :         if (!nss_wrapper_enabled()) {
    5276           0 :                 return libc_getgrnam_r(name,
    5277             :                                        grp,
    5278             :                                        buf,
    5279             :                                        buflen,
    5280             :                                        pgrp);
    5281             :         }
    5282             : 
    5283         708 :         return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
    5284             : }
    5285             : #endif /* HAVE_GETGRNAM_R */
    5286             : 
    5287             : /****************************************************************************
    5288             :  *   GETGRGID
    5289             :  ***************************************************************************/
    5290             : 
    5291        5209 : static struct group *nwrap_getgrgid(gid_t gid)
    5292             : {
    5293             :         size_t i;
    5294             :         struct group *grp;
    5295             : 
    5296        5813 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5297        5803 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5298        5803 :                 grp = b->ops->nw_getgrgid(b, gid);
    5299        5803 :                 if (grp) {
    5300        5199 :                         return grp;
    5301             :                 }
    5302             :         }
    5303             : 
    5304          10 :         return NULL;
    5305             : }
    5306             : 
    5307             : struct group *getgrgid(gid_t gid)
    5308             : {
    5309        5448 :         if (!nss_wrapper_enabled()) {
    5310         239 :                 return libc_getgrgid(gid);
    5311             :         }
    5312             : 
    5313        5209 :         return nwrap_getgrgid(gid);
    5314             : }
    5315             : 
    5316             : /****************************************************************************
    5317             :  *   GETGRGID_R
    5318             :  ***************************************************************************/
    5319             : 
    5320         712 : static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
    5321             :                             char *buf, size_t buflen, struct group **grdstp)
    5322             : {
    5323             :         size_t i;
    5324             :         int ret;
    5325             : 
    5326        1440 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5327         716 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5328         716 :                 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
    5329         716 :                 if (ret == ENOENT) {
    5330           8 :                         continue;
    5331             :                 }
    5332         708 :                 return ret;
    5333             :         }
    5334             : 
    5335           4 :         return ENOENT;
    5336             : }
    5337             : 
    5338             : #ifdef HAVE_GETGRGID_R
    5339             : # ifdef HAVE_SOLARIS_GETGRGID_R
    5340             : int getgrgid_r(gid_t gid, struct group *grdst,
    5341             :                char *buf, int buflen, struct group **grdstp)
    5342             : # else /* HAVE_SOLARIS_GETGRGID_R */
    5343             : int getgrgid_r(gid_t gid, struct group *grdst,
    5344             :                char *buf, size_t buflen, struct group **grdstp)
    5345             : # endif /* HAVE_SOLARIS_GETGRGID_R */
    5346             : {
    5347         712 :         if (!nss_wrapper_enabled()) {
    5348           0 :                 return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
    5349             :         }
    5350             : 
    5351         712 :         return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
    5352             : }
    5353             : #endif
    5354             : 
    5355             : /****************************************************************************
    5356             :  *   SETGRENT
    5357             :  ***************************************************************************/
    5358             : 
    5359       39872 : static void nwrap_setgrent(void)
    5360             : {
    5361             :         size_t i;
    5362             : 
    5363      119632 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5364       79752 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5365       79752 :                 b->ops->nw_setgrent(b);
    5366             :         }
    5367       39872 : }
    5368             : 
    5369             : #ifdef HAVE_BSD_SETGRENT
    5370             : int setgrent(void)
    5371             : #else
    5372             : void setgrent(void)
    5373             : #endif
    5374             : {
    5375          34 :         if (!nss_wrapper_enabled()) {
    5376           0 :                 libc_setgrent();
    5377           0 :                 goto out;
    5378             :         }
    5379             : 
    5380          34 :         nwrap_setgrent();
    5381             : 
    5382          34 : out:
    5383             : #ifdef HAVE_BSD_SETGRENT
    5384             :         return 0;
    5385             : #else
    5386          34 :         return;
    5387             : #endif
    5388             : }
    5389             : 
    5390             : /****************************************************************************
    5391             :  *   GETGRENT
    5392             :  ***************************************************************************/
    5393             : 
    5394     1002604 : static struct group *nwrap_getgrent(void)
    5395             : {
    5396             :         size_t i;
    5397             :         struct group *grp;
    5398             : 
    5399     1082332 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5400     1042464 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5401     1042464 :                 grp = b->ops->nw_getgrent(b);
    5402     1042464 :                 if (grp) {
    5403      962688 :                         return grp;
    5404             :                 }
    5405             :         }
    5406             : 
    5407       39860 :         return NULL;
    5408             : }
    5409             : 
    5410             : struct group *getgrent(void)
    5411             : {
    5412        1108 :         if (!nss_wrapper_enabled()) {
    5413           0 :                 return libc_getgrent();
    5414             :         }
    5415             : 
    5416        1108 :         return nwrap_getgrent();
    5417             : }
    5418             : 
    5419             : /****************************************************************************
    5420             :  *   GETGRENT_R
    5421             :  ***************************************************************************/
    5422             : 
    5423             : #ifdef HAVE_GETGRENT_R
    5424         720 : static int nwrap_getgrent_r(struct group *grdst, char *buf,
    5425             :                             size_t buflen, struct group **grdstp)
    5426             : {
    5427             :         size_t i;
    5428             :         int ret;
    5429             : 
    5430        1488 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5431         732 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5432         732 :                 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
    5433         732 :                 if (ret == ENOENT) {
    5434          24 :                         continue;
    5435             :                 }
    5436         708 :                 return ret;
    5437             :         }
    5438             : 
    5439          12 :         return ENOENT;
    5440             : }
    5441             : 
    5442             : #  ifdef HAVE_SOLARIS_GETGRENT_R
    5443             : struct group *getgrent_r(struct group *src, char *buf, int buflen)
    5444             : {
    5445             :         struct group *grdstp = NULL;
    5446             :         int rc;
    5447             : 
    5448             :         if (!nss_wrapper_enabled()) {
    5449             :                 return libc_getgrent_r(src, buf, buflen);
    5450             :         }
    5451             : 
    5452             :         rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
    5453             :         if (rc < 0) {
    5454             :                 return NULL;
    5455             :         }
    5456             : 
    5457             :         return grdstp;
    5458             : }
    5459             : #  else /* HAVE_SOLARIS_GETGRENT_R */
    5460             : int getgrent_r(struct group *src, char *buf,
    5461             :                size_t buflen, struct group **grdstp)
    5462             : {
    5463         720 :         if (!nss_wrapper_enabled()) {
    5464           0 :                 return libc_getgrent_r(src, buf, buflen, grdstp);
    5465             :         }
    5466             : 
    5467         720 :         return nwrap_getgrent_r(src, buf, buflen, grdstp);
    5468             : }
    5469             : #  endif /* HAVE_SOLARIS_GETGRENT_R */
    5470             : #endif /* HAVE_GETGRENT_R */
    5471             : 
    5472             : /****************************************************************************
    5473             :  *   ENDGRENT
    5474             :  ***************************************************************************/
    5475             : 
    5476       39872 : static void nwrap_endgrent(void)
    5477             : {
    5478             :         size_t i;
    5479             : 
    5480      119624 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5481       79752 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5482       79752 :                 b->ops->nw_endgrent(b);
    5483             :         }
    5484       39872 : }
    5485             : 
    5486             : void endgrent(void)
    5487             : {
    5488          34 :         if (!nss_wrapper_enabled()) {
    5489           0 :                 libc_endgrent();
    5490           0 :                 return;
    5491             :         }
    5492             : 
    5493          34 :         nwrap_endgrent();
    5494             : }
    5495             : 
    5496             : /****************************************************************************
    5497             :  *   GETGROUPLIST
    5498             :  ***************************************************************************/
    5499             : 
    5500             : #ifdef HAVE_GETGROUPLIST
    5501       39846 : static int nwrap_getgrouplist(const char *user, gid_t group,
    5502             :                               gid_t *groups, int *ngroups)
    5503             : {
    5504             :         struct group *grp;
    5505             :         gid_t *groups_tmp;
    5506       39846 :         int count = 1;
    5507             : 
    5508       39846 :         NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
    5509             : 
    5510       39846 :         groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
    5511       39846 :         if (!groups_tmp) {
    5512           0 :                 NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    5513           0 :                 errno = ENOMEM;
    5514           0 :                 return -1;
    5515             :         }
    5516       39846 :         groups_tmp[0] = group;
    5517             : 
    5518       39838 :         nwrap_setgrent();
    5519     1041334 :         while ((grp = nwrap_getgrent()) != NULL) {
    5520      961650 :                 int i = 0;
    5521             : 
    5522      961650 :                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    5523             :                           "Inspecting %s for group membership",
    5524             :                           grp->gr_name);
    5525             : 
    5526     1039358 :                 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
    5527             : 
    5528      153873 :                         if (group != grp->gr_gid &&
    5529       76165 :                             (strcmp(user, grp->gr_mem[i]) == 0)) {
    5530             : 
    5531       35074 :                                 NWRAP_LOG(NWRAP_LOG_DEBUG,
    5532             :                                           "%s is member of %s",
    5533             :                                           user,
    5534             :                                           grp->gr_name);
    5535             : 
    5536       35074 :                                 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
    5537       35074 :                                 if (!groups_tmp) {
    5538           0 :                                         NWRAP_LOG(NWRAP_LOG_ERROR,
    5539             :                                                   "Out of memory");
    5540           0 :                                         errno = ENOMEM;
    5541           0 :                                         return -1;
    5542             :                                 }
    5543       35074 :                                 groups_tmp[count] = grp->gr_gid;
    5544             : 
    5545       35074 :                                 count++;
    5546             :                         }
    5547             :                 }
    5548             :         }
    5549             : 
    5550       39846 :         nwrap_endgrent();
    5551             : 
    5552       39846 :         NWRAP_LOG(NWRAP_LOG_DEBUG,
    5553             :                   "%s is member of %d groups",
    5554             :                   user, *ngroups);
    5555             : 
    5556       39846 :         if (*ngroups < count) {
    5557        1070 :                 *ngroups = count;
    5558        1070 :                 free(groups_tmp);
    5559        1070 :                 return -1;
    5560             :         }
    5561             : 
    5562       38776 :         *ngroups = count;
    5563       38784 :         memcpy(groups, groups_tmp, count * sizeof(gid_t));
    5564       38776 :         free(groups_tmp);
    5565             : 
    5566       38776 :         return count;
    5567             : }
    5568             : 
    5569             : int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
    5570             : {
    5571       39849 :         if (!nss_wrapper_enabled()) {
    5572           3 :                 return libc_getgrouplist(user, group, groups, ngroups);
    5573             :         }
    5574             : 
    5575       39846 :         return nwrap_getgrouplist(user, group, groups, ngroups);
    5576             : }
    5577             : #endif
    5578             : 
    5579             : /**********************************************************
    5580             :  * SHADOW
    5581             :  **********************************************************/
    5582             : 
    5583             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    5584             : 
    5585             : #ifdef HAVE_SETSPENT
    5586             : static void nwrap_setspent(void)
    5587             : {
    5588             :         nwrap_files_setspent();
    5589             : }
    5590             : 
    5591             : void setspent(void)
    5592             : {
    5593             :         if (!nss_wrapper_shadow_enabled()) {
    5594             :                 return;
    5595             :         }
    5596             : 
    5597             :         nwrap_setspent();
    5598             : }
    5599             : 
    5600             : static struct spwd *nwrap_getspent(void)
    5601             : {
    5602             :         return nwrap_files_getspent();
    5603             : }
    5604             : 
    5605             : struct spwd *getspent(void)
    5606             : {
    5607             :         if (!nss_wrapper_shadow_enabled()) {
    5608             :                 return NULL;
    5609             :         }
    5610             : 
    5611             :         return nwrap_getspent();
    5612             : }
    5613             : 
    5614             : static void nwrap_endspent(void)
    5615             : {
    5616             :         nwrap_files_endspent();
    5617             : }
    5618             : 
    5619             : void endspent(void)
    5620             : {
    5621             :         if (!nss_wrapper_shadow_enabled()) {
    5622             :                 return;
    5623             :         }
    5624             : 
    5625             :         nwrap_endspent();
    5626             : }
    5627             : #endif /* HAVE_SETSPENT */
    5628             : 
    5629           0 : static struct spwd *nwrap_getspnam(const char *name)
    5630             : {
    5631           0 :         return nwrap_files_getspnam(name);
    5632             : }
    5633             : 
    5634             : struct spwd *getspnam(const char *name)
    5635             : {
    5636           0 :         if (!nss_wrapper_shadow_enabled()) {
    5637           0 :                 return NULL;
    5638             :         }
    5639             : 
    5640           0 :         return nwrap_getspnam(name);
    5641             : }
    5642             : 
    5643             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    5644             : 
    5645             : /**********************************************************
    5646             :  * NETDB
    5647             :  **********************************************************/
    5648             : 
    5649           0 : static void nwrap_sethostent(int stayopen) {
    5650             :         (void) stayopen; /* ignored */
    5651             : 
    5652           0 :         nwrap_files_sethostent();
    5653           0 : }
    5654             : 
    5655             : #ifdef HAVE_SOLARIS_SETHOSTENT
    5656             : int sethostent(int stayopen)
    5657             : {
    5658             :         if (!nss_wrapper_hosts_enabled()) {
    5659             :                 libc_sethostent(stayopen);
    5660             :                 return 0;
    5661             :         }
    5662             : 
    5663             :         nwrap_sethostent(stayopen);
    5664             : 
    5665             :         return 0;
    5666             : }
    5667             : #else /* HAVE_SOLARIS_SETHOSTENT */
    5668             : void sethostent(int stayopen)
    5669             : {
    5670           0 :         if (!nss_wrapper_hosts_enabled()) {
    5671           0 :                 libc_sethostent(stayopen);
    5672           0 :                 return;
    5673             :         }
    5674             : 
    5675           0 :         nwrap_sethostent(stayopen);
    5676             : }
    5677             : #endif /* HAVE_SOLARIS_SETHOSTENT */
    5678             : 
    5679           0 : static struct hostent *nwrap_gethostent(void)
    5680             : {
    5681           0 :         return nwrap_files_gethostent();
    5682             : }
    5683             : 
    5684             : struct hostent *gethostent(void) {
    5685           0 :         if (!nss_wrapper_hosts_enabled()) {
    5686           0 :                 return libc_gethostent();
    5687             :         }
    5688             : 
    5689           0 :         return nwrap_gethostent();
    5690             : }
    5691             : 
    5692           0 : static void nwrap_endhostent(void) {
    5693           0 :         nwrap_files_endhostent();
    5694           0 : }
    5695             : 
    5696             : #ifdef HAVE_SOLARIS_ENDHOSTENT
    5697             : int endhostent(void)
    5698             : {
    5699             :         if (!nss_wrapper_hosts_enabled()) {
    5700             :                 libc_endhostent();
    5701             :                 return 0;
    5702             :         }
    5703             : 
    5704             :         nwrap_endhostent();
    5705             : 
    5706             :         return 0;
    5707             : }
    5708             : #else /* HAVE_SOLARIS_ENDHOSTENT */
    5709             : void endhostent(void)
    5710             : {
    5711           0 :         if (!nss_wrapper_hosts_enabled()) {
    5712           0 :                 libc_endhostent();
    5713           0 :                 return;
    5714             :         }
    5715             : 
    5716           0 :         nwrap_endhostent();
    5717             : }
    5718             : #endif /* HAVE_SOLARIS_ENDHOSTENT */
    5719             : 
    5720             : 
    5721             : #ifdef BSD
    5722             : /* BSD implementation stores data in thread local storage but GLIBC does not */
    5723             : static __thread struct hostent user_he;
    5724             : static __thread struct nwrap_vector user_addrlist;
    5725             : #else
    5726             : static struct hostent user_he;
    5727             : static struct nwrap_vector user_addrlist;
    5728             : #endif /* BSD */
    5729             : 
    5730           0 : static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b,
    5731             :                                                  const char *name)
    5732             : {
    5733             :         int ret;
    5734             : 
    5735             :         (void) b; /* unused */
    5736             : 
    5737           0 :         ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he,
    5738             :                                                  &user_addrlist);
    5739           0 :         if (ret == 0) {
    5740           0 :                 return &user_he;
    5741             :         }
    5742             : 
    5743           0 :         return NULL;
    5744             : }
    5745             : 
    5746           0 : static struct hostent *nwrap_gethostbyname(const char *name)
    5747             : {
    5748             :         size_t i;
    5749           0 :         struct hostent *he = NULL;
    5750             : 
    5751           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5752           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5753           0 :                 he = b->ops->nw_gethostbyname(b, name);
    5754           0 :                 if (he != NULL) {
    5755           0 :                         return he;
    5756             :                 }
    5757             :         }
    5758             : 
    5759           0 :         return NULL;
    5760             : }
    5761             : 
    5762             : struct hostent *gethostbyname(const char *name)
    5763             : {
    5764           0 :         if (!nss_wrapper_hosts_enabled()) {
    5765           0 :                 return libc_gethostbyname(name);
    5766             :         }
    5767             : 
    5768           0 :         return nwrap_gethostbyname(name);
    5769             : }
    5770             : 
    5771             : /* This is a GNU extension - Also can be found on BSD systems */
    5772             : #ifdef HAVE_GETHOSTBYNAME2
    5773             : #ifdef BSD
    5774             : /* BSD implementation stores data in  thread local storage but GLIBC not */
    5775             : static __thread struct hostent user_he2;
    5776             : static __thread struct nwrap_vector user_addrlist2;
    5777             : #else
    5778             : static struct hostent user_he2;
    5779             : static struct nwrap_vector user_addrlist2;
    5780             : #endif /* BSD */
    5781             : 
    5782           0 : static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b,
    5783             :                                                   const char *name, int af)
    5784             : {
    5785             :         int ret;
    5786             : 
    5787             :         (void) b; /* unused */
    5788             : 
    5789           0 :         ret = nwrap_files_internal_gethostbyname(name, af, &user_he2,
    5790             :                                                  &user_addrlist2);
    5791           0 :         if (ret == 0) {
    5792           0 :                 return &user_he2;
    5793             :         }
    5794             : 
    5795           0 :         return NULL;
    5796             : }
    5797             : 
    5798           0 : static struct hostent *nwrap_gethostbyname2(const char *name, int af)
    5799             : {
    5800             :         size_t i;
    5801           0 :         struct hostent *he = NULL;
    5802             : 
    5803           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5804           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5805           0 :                 he = b->ops->nw_gethostbyname2(b, name, af);
    5806           0 :                 if (he != NULL) {
    5807           0 :                         return he;
    5808             :                 }
    5809             :         }
    5810             : 
    5811           0 :         return NULL;
    5812             : }
    5813             : 
    5814             : struct hostent *gethostbyname2(const char *name, int af)
    5815             : {
    5816           0 :         if (!nss_wrapper_hosts_enabled()) {
    5817           0 :                 return libc_gethostbyname2(name, af);
    5818             :         }
    5819             : 
    5820           0 :         return nwrap_gethostbyname2(name, af);
    5821             : }
    5822             : #endif
    5823             : 
    5824           0 : static struct hostent *nwrap_gethostbyaddr(const void *addr,
    5825             :                                            socklen_t len, int type)
    5826             : {
    5827             :         size_t i;
    5828           0 :         struct hostent *he = NULL;
    5829             : 
    5830           0 :         for (i=0; i < nwrap_main_global->num_backends; i++) {
    5831           0 :                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    5832           0 :                 he = b->ops->nw_gethostbyaddr(b, addr, len, type);
    5833           0 :                 if (he != NULL) {
    5834           0 :                         return he;
    5835             :                 }
    5836             :         }
    5837             : 
    5838           0 :         return NULL;
    5839             : }
    5840             : 
    5841             : struct hostent *gethostbyaddr(const void *addr,
    5842             :                               socklen_t len, int type)
    5843             : {
    5844           0 :         if (!nss_wrapper_hosts_enabled()) {
    5845           0 :                 return libc_gethostbyaddr(addr, len, type);
    5846             :         }
    5847             : 
    5848           0 :         return nwrap_gethostbyaddr(addr, len, type);
    5849             : }
    5850             : 
    5851             : static const struct addrinfo default_hints =
    5852             : {
    5853             :         .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
    5854             :         .ai_family = AF_UNSPEC,
    5855             :         .ai_socktype = 0,
    5856             :         .ai_protocol = 0,
    5857             :         .ai_addrlen = 0,
    5858             :         .ai_addr = NULL,
    5859             :         .ai_canonname = NULL,
    5860             :         .ai_next = NULL
    5861             : };
    5862             : 
    5863      270384 : static int nwrap_convert_he_ai(const struct hostent *he,
    5864             :                                unsigned short port,
    5865             :                                const struct addrinfo *hints,
    5866             :                                struct addrinfo **pai,
    5867             :                                bool skip_canonname)
    5868             : {
    5869             :         struct addrinfo *ai;
    5870             :         socklen_t socklen;
    5871             : 
    5872      270384 :         if (he == NULL) {
    5873           0 :                 return EAI_MEMORY;
    5874             :         }
    5875             : 
    5876      270384 :         switch (he->h_addrtype) {
    5877      192357 :                 case AF_INET:
    5878      192357 :                         socklen = sizeof(struct sockaddr_in);
    5879      192357 :                         break;
    5880             : #ifdef HAVE_IPV6
    5881       74939 :                 case AF_INET6:
    5882       74939 :                         socklen = sizeof(struct sockaddr_in6);
    5883       74939 :                         break;
    5884             : #endif
    5885           0 :                 default:
    5886           0 :                         return EAI_FAMILY;
    5887             :         }
    5888             : 
    5889      270384 :         ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
    5890      270384 :         if (ai == NULL) {
    5891           0 :                 return EAI_MEMORY;
    5892             :         }
    5893             : 
    5894      270384 :         ai->ai_flags = hints->ai_flags;
    5895      270384 :         ai->ai_family = he->h_addrtype;
    5896      270384 :         ai->ai_socktype = hints->ai_socktype;
    5897      270384 :         ai->ai_protocol = hints->ai_protocol;
    5898      270384 :         ai->ai_canonname = NULL;
    5899             : 
    5900      270384 :         if (ai->ai_socktype == 0) {
    5901         224 :                 ai->ai_socktype = SOCK_DGRAM;
    5902             :         }
    5903      270384 :         if (ai->ai_protocol == 0) {
    5904      264612 :                 if (ai->ai_socktype == SOCK_DGRAM) {
    5905       26988 :                         ai->ai_protocol = IPPROTO_UDP;
    5906      237624 :                 } else if (ai->ai_socktype == SOCK_STREAM) {
    5907      237624 :                         ai->ai_protocol = IPPROTO_TCP;
    5908             :                 }
    5909             :         }
    5910             : 
    5911      270384 :         ai->ai_addrlen = socklen;
    5912      270384 :         ai->ai_addr = (void *)(ai + 1);
    5913             : 
    5914             : #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
    5915             :         ai->ai_addr->sa_len = socklen;
    5916             : #endif
    5917      270384 :         ai->ai_addr->sa_family = he->h_addrtype;
    5918             : 
    5919      270384 :         switch (he->h_addrtype) {
    5920      195445 :                 case AF_INET:
    5921      195445 :                 {
    5922             :                         union {
    5923             :                                 struct sockaddr *sa;
    5924             :                                 struct sockaddr_in *in;
    5925             :                         } addr;
    5926             : 
    5927      195445 :                         addr.sa = ai->ai_addr;
    5928             : 
    5929      198533 :                         memset(addr.in, 0, sizeof(struct sockaddr_in));
    5930             : 
    5931      195445 :                         addr.in->sin_port = htons(port);
    5932      195445 :                         addr.in->sin_family = AF_INET;
    5933             : 
    5934      198533 :                         memset(addr.in->sin_zero,
    5935             :                                '\0',
    5936             :                                sizeof (addr.in->sin_zero));
    5937      393978 :                         memcpy(&(addr.in->sin_addr),
    5938      195445 :                                he->h_addr_list[0],
    5939      195445 :                                he->h_length);
    5940             : 
    5941             :                 }
    5942      195445 :                 break;
    5943             : #ifdef HAVE_IPV6
    5944       74939 :                 case AF_INET6:
    5945       74939 :                 {
    5946             :                         union {
    5947             :                                 struct sockaddr *sa;
    5948             :                                 struct sockaddr_in6 *in6;
    5949             :                         } addr;
    5950             : 
    5951       74939 :                         addr.sa = ai->ai_addr;
    5952             : 
    5953       75053 :                         memset(addr.in6, 0, sizeof(struct sockaddr_in6));
    5954             : 
    5955       74939 :                         addr.in6->sin6_port = htons(port);
    5956       74939 :                         addr.in6->sin6_family = AF_INET6;
    5957             : 
    5958      149992 :                         memcpy(&addr.in6->sin6_addr,
    5959       74939 :                                he->h_addr_list[0],
    5960       74939 :                                he->h_length);
    5961             :                 }
    5962       74939 :                 break;
    5963             : #endif
    5964             :         }
    5965             : 
    5966      270384 :         ai->ai_next = NULL;
    5967             : 
    5968      270384 :         if (he->h_name && !skip_canonname) {
    5969      248864 :                 ai->ai_canonname = strdup(he->h_name);
    5970      248864 :                 if (ai->ai_canonname == NULL) {
    5971           0 :                         freeaddrinfo(ai);
    5972           0 :                         return EAI_MEMORY;
    5973             :                 }
    5974             :         }
    5975             : 
    5976      270384 :         *pai = ai;
    5977      270384 :         return 0;
    5978             : }
    5979             : 
    5980      947283 : static int nwrap_getaddrinfo(const char *node,
    5981             :                              const char *service,
    5982             :                              const struct addrinfo *hints,
    5983             :                              struct addrinfo **res)
    5984             : {
    5985      947283 :         struct addrinfo *ai = NULL;
    5986      947283 :         unsigned short port = 0;
    5987             :         struct {
    5988             :                 int family;
    5989             :                 union {
    5990             :                         struct in_addr v4;
    5991             : #ifdef HAVE_IPV6
    5992             :                         struct in6_addr v6;
    5993             :                 } in;
    5994             : #endif
    5995      947283 :         } addr = {
    5996             :                 .family = AF_UNSPEC,
    5997             :         };
    5998             :         int rc;
    5999             : 
    6000      947283 :         if (node == NULL && service == NULL) {
    6001           0 :                 return EAI_NONAME;
    6002             :         }
    6003             : 
    6004      947283 :         if (hints == NULL) {
    6005           0 :                 hints = &default_hints;
    6006             :         }
    6007             : 
    6008             :         /* EAI_BADFLAGS
    6009             :               hints.ai_flags   contains   invalid  flags;  or,  hints.ai_flags
    6010             :               included AI_CANONNAME and name was NULL.
    6011             :         */
    6012      947283 :         if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
    6013           0 :                 return EAI_BADFLAGS;
    6014             :         }
    6015             : 
    6016             :         /* If no node has been specified, let glibc deal with it */
    6017      947283 :         if (node == NULL) {
    6018             :                 int ret;
    6019           0 :                 struct addrinfo *p = NULL;
    6020             : 
    6021           0 :                 ret = libc_getaddrinfo(node, service, hints, &p);
    6022             : 
    6023           0 :                 if (ret == 0) {
    6024           0 :                         *res = p;
    6025             :                 }
    6026           0 :                 return ret;
    6027             :         }
    6028             : 
    6029      947283 :         if (service != NULL && service[0] != '\0') {
    6030      163254 :                 const char *proto = NULL;
    6031             :                 struct servent *s;
    6032             :                 char *end_ptr;
    6033             :                 long sl;
    6034             : 
    6035      163254 :                 errno = 0;
    6036      163254 :                 sl = strtol(service, &end_ptr, 10);
    6037             : 
    6038      163254 :                 if (*end_ptr == '\0') {
    6039      163254 :                         port = sl;
    6040      163254 :                         goto valid_port;
    6041           0 :                 } else if (hints->ai_flags & AI_NUMERICSERV) {
    6042           0 :                         return EAI_NONAME;
    6043             :                 }
    6044             : 
    6045           0 :                 if (hints->ai_protocol != 0) {
    6046             :                         struct protoent *pent;
    6047             : 
    6048           0 :                         pent = getprotobynumber(hints->ai_protocol);
    6049           0 :                         if (pent != NULL) {
    6050           0 :                                 proto = pent->p_name;
    6051             :                         }
    6052             :                 }
    6053             : 
    6054           0 :                 s = getservbyname(service, proto);
    6055           0 :                 if (s == NULL) {
    6056           0 :                         return EAI_NONAME;
    6057             :                 }
    6058           0 :                 port = ntohs(s->s_port);
    6059             :         }
    6060             : 
    6061      784029 : valid_port:
    6062             : 
    6063      947283 :         rc = inet_pton(AF_INET, node, &addr.in.v4);
    6064      947283 :         if (rc == 1) {
    6065      719487 :                 addr.family = AF_INET;
    6066             :         }
    6067             : #ifdef HAVE_IPV6
    6068      947283 :         if (addr.family == AF_UNSPEC) {
    6069      227796 :                 rc = inet_pton(AF_INET6, node, &addr.in.v6);
    6070      227796 :                 if (rc == 1) {
    6071      175606 :                         addr.family = AF_INET6;
    6072             :                 }
    6073             :         }
    6074             : #endif
    6075             : 
    6076      947283 :         if (addr.family == AF_UNSPEC) {
    6077       52190 :                if (hints->ai_flags & AI_NUMERICHOST) {
    6078       24062 :                         return EAI_NONAME;
    6079             :                 }
    6080      909245 :         } else if ((hints->ai_family != AF_UNSPEC) &&
    6081       14152 :                    (hints->ai_family != addr.family))
    6082             :         {
    6083           0 :                 return EAI_ADDRFAMILY;
    6084             :         }
    6085             : 
    6086      923221 :         rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
    6087      923221 :         if (rc != 0) {
    6088             :                 int ret;
    6089      674357 :                 struct addrinfo *p = NULL;
    6090             : 
    6091      674357 :                 ret = libc_getaddrinfo(node, service, hints, &p);
    6092             : 
    6093      674357 :                 if (ret == 0) {
    6094             :                         /*
    6095             :                          * nwrap_files_getaddrinfo failed, but libc was
    6096             :                          * successful -- use the result from libc.
    6097             :                          */
    6098      667775 :                         *res = p;
    6099      667775 :                         return 0;
    6100             :                 }
    6101             : 
    6102        6582 :                 return rc;
    6103             :         }
    6104             : 
    6105             :         /*
    6106             :          * If the socktype was not specified, duplicate
    6107             :          * each ai returned, so that we have variants for
    6108             :          * both UDP and TCP.
    6109             :          */
    6110      248864 :         if (hints->ai_socktype == 0) {
    6111             :                 struct addrinfo *ai_cur;
    6112             : 
    6113             :                 /* freeaddrinfo() frees ai_canonname and ai so allocate them */
    6114         349 :                 for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
    6115             :                         struct addrinfo *ai_new;
    6116             : 
    6117             :                         /* duplicate the current entry */
    6118             : 
    6119         224 :                         ai_new = malloc(sizeof(struct addrinfo));
    6120         224 :                         if (ai_new == NULL) {
    6121           0 :                                 freeaddrinfo(ai);
    6122           0 :                                 return EAI_MEMORY;
    6123             :                         }
    6124             : 
    6125         224 :                         memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
    6126         224 :                         ai_new->ai_next = NULL;
    6127             : 
    6128             :                         /* We need a deep copy or freeaddrinfo() will blow up */
    6129         224 :                         if (ai_cur->ai_canonname != NULL) {
    6130         125 :                                 ai_new->ai_canonname =
    6131         125 :                                         strdup(ai_cur->ai_canonname);
    6132             :                         }
    6133             : 
    6134         224 :                         if (ai_cur->ai_socktype == SOCK_DGRAM) {
    6135         224 :                                 ai_new->ai_socktype = SOCK_STREAM;
    6136           0 :                         } else if (ai_cur->ai_socktype == SOCK_STREAM) {
    6137           0 :                                 ai_new->ai_socktype = SOCK_DGRAM;
    6138             :                         }
    6139         224 :                         if (ai_cur->ai_protocol == IPPROTO_TCP) {
    6140           0 :                                 ai_new->ai_protocol = IPPROTO_UDP;
    6141         224 :                         } else if (ai_cur->ai_protocol == IPPROTO_UDP) {
    6142         224 :                                 ai_new->ai_protocol = IPPROTO_TCP;
    6143             :                         }
    6144             : 
    6145             :                         /* now insert the new entry */
    6146             : 
    6147         224 :                         ai_new->ai_next = ai_cur->ai_next;
    6148         224 :                         ai_cur->ai_next = ai_new;
    6149             : 
    6150             :                         /* and move on (don't duplicate the new entry) */
    6151             : 
    6152         224 :                         ai_cur = ai_new;
    6153             :                 }
    6154             :         }
    6155             : 
    6156      248864 :         *res = ai;
    6157             : 
    6158      248864 :         return 0;
    6159             : }
    6160             : 
    6161             : int getaddrinfo(const char *node, const char *service,
    6162             :                 const struct addrinfo *hints,
    6163             :                 struct addrinfo **res)
    6164             : {
    6165     1081963 :         if (!nss_wrapper_hosts_enabled()) {
    6166      134680 :                 return libc_getaddrinfo(node, service, hints, res);
    6167             :         }
    6168             : 
    6169      947283 :         return nwrap_getaddrinfo(node, service, hints, res);
    6170             : }
    6171             : 
    6172     1732416 : static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6173             :                              char *host, size_t hostlen,
    6174             :                              char *serv, size_t servlen,
    6175             :                              int flags)
    6176             : {
    6177             :         struct hostent *he;
    6178             :         struct servent *service;
    6179             :         const char *proto;
    6180             :         const void *addr;
    6181             :         socklen_t addrlen;
    6182             :         uint16_t port;
    6183             :         sa_family_t type;
    6184             :         size_t i;
    6185             : 
    6186     1732416 :         if (sa == NULL || salen < sizeof(sa_family_t)) {
    6187           0 :                 return EAI_FAMILY;
    6188             :         }
    6189             : 
    6190     1732416 :         if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
    6191           0 :                 return EAI_NONAME;
    6192             :         }
    6193             : 
    6194     1732416 :         type = sa->sa_family;
    6195     1732416 :         switch (type) {
    6196     1389504 :         case AF_INET: {
    6197             :                 union {
    6198             :                         const struct sockaddr *sa;
    6199             :                         const struct sockaddr_in *in;
    6200             :                 } a;
    6201             : 
    6202     1389504 :                 if (salen < sizeof(struct sockaddr_in)) {
    6203           0 :                         return EAI_FAMILY;
    6204             :                 }
    6205             : 
    6206     1389504 :                 a.sa = sa;
    6207             : 
    6208     1389504 :                 addr = &(a.in->sin_addr);
    6209     1389504 :                 addrlen = sizeof(a.in->sin_addr);
    6210     1389504 :                 port = ntohs(a.in->sin_port);
    6211     1353110 :                 break;
    6212             :         }
    6213             : #ifdef HAVE_IPV6
    6214      342066 :         case AF_INET6: {
    6215             :                 union {
    6216             :                         const struct sockaddr *sa;
    6217             :                         const struct sockaddr_in6 *in6;
    6218             :                 } a;
    6219             : 
    6220      342066 :                 if (salen < sizeof(struct sockaddr_in6)) {
    6221           0 :                         return EAI_FAMILY;
    6222             :                 }
    6223             : 
    6224      342066 :                 a.sa = sa;
    6225             : 
    6226      342066 :                 addr = &(a.in6->sin6_addr);
    6227      342066 :                 addrlen = sizeof(a.in6->sin6_addr);
    6228      342066 :                 port = ntohs(a.in6->sin6_port);
    6229      335740 :                 break;
    6230             :         }
    6231             : #endif
    6232         846 :         default:
    6233         846 :                 return EAI_FAMILY;
    6234             :         }
    6235             : 
    6236     1731570 :         if (host != NULL) {
    6237     1731570 :                 he = NULL;
    6238     1731570 :                 if ((flags & NI_NUMERICHOST) == 0) {
    6239          99 :                         for (i=0; i < nwrap_main_global->num_backends; i++) {
    6240          99 :                                 struct nwrap_backend *b = &nwrap_main_global->backends[i];
    6241          99 :                                 he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type);
    6242          99 :                                 if (he != NULL) {
    6243          99 :                                         break;
    6244             :                                 }
    6245             :                         }
    6246          99 :                         if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
    6247           0 :                                 return EAI_NONAME;
    6248             :                 }
    6249     1688850 :                 if (he != NULL && he->h_name != NULL) {
    6250          99 :                         if (strlen(he->h_name) >= hostlen)
    6251           0 :                                 return EAI_OVERFLOW;
    6252          99 :                         snprintf(host, hostlen, "%s", he->h_name);
    6253         198 :                         if (flags & NI_NOFQDN)
    6254           0 :                                 host[strcspn(host, ".")] = '\0';
    6255             :                 } else {
    6256     1731471 :                         if (inet_ntop(type, addr, host, hostlen) == NULL)
    6257           0 :                                 return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
    6258             :                 }
    6259             :         }
    6260             : 
    6261     1731570 :         if (serv != NULL) {
    6262       12360 :                 service = NULL;
    6263       12360 :                 if ((flags & NI_NUMERICSERV) == 0) {
    6264           0 :                         proto = (flags & NI_DGRAM) ? "udp" : "tcp";
    6265           0 :                         service = getservbyport(htons(port), proto);
    6266             :                 }
    6267       12360 :                 if (service != NULL) {
    6268           0 :                         if (strlen(service->s_name) >= servlen)
    6269           0 :                                 return EAI_OVERFLOW;
    6270           0 :                         snprintf(serv, servlen, "%s", service->s_name);
    6271             :                 } else {
    6272       12360 :                         if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
    6273           0 :                                 return EAI_OVERFLOW;
    6274             :                 }
    6275             :         }
    6276             : 
    6277     1688850 :         return 0;
    6278             : }
    6279             : 
    6280             : #ifdef HAVE_LINUX_GETNAMEINFO
    6281             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6282             :                 char *host, socklen_t hostlen,
    6283             :                 char *serv, socklen_t servlen,
    6284             :                 int flags)
    6285             : #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
    6286             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6287             :                 char *host, socklen_t hostlen,
    6288             :                 char *serv, socklen_t servlen,
    6289             :                 unsigned int flags)
    6290             : #else
    6291             : int getnameinfo(const struct sockaddr *sa, socklen_t salen,
    6292             :                 char *host, size_t hostlen,
    6293             :                 char *serv, size_t servlen,
    6294             :                 int flags)
    6295             : #endif
    6296             : {
    6297     1931522 :         if (!nss_wrapper_hosts_enabled()) {
    6298      199106 :                 return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
    6299             :         }
    6300             : 
    6301     1732416 :         return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
    6302             : }
    6303             : 
    6304       55209 : static int nwrap_gethostname(char *name, size_t len)
    6305             : {
    6306       55209 :         const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
    6307             : 
    6308       55209 :         if (strlen(hostname) >= len) {
    6309           0 :                 errno = ENAMETOOLONG;
    6310           0 :                 return -1;
    6311             :         }
    6312       55209 :         snprintf(name, len, "%s", hostname);
    6313             : 
    6314       55209 :         return 0;
    6315             : }
    6316             : 
    6317             : #ifdef HAVE_SOLARIS_GETHOSTNAME
    6318             : int gethostname(char *name, int len)
    6319             : #else /* HAVE_SOLARIS_GETHOSTNAME */
    6320             : int gethostname(char *name, size_t len)
    6321             : #endif /* HAVE_SOLARIS_GETHOSTNAME */
    6322             : {
    6323       62373 :         if (!nwrap_hostname_enabled()) {
    6324        8007 :                 return libc_gethostname(name, len);
    6325             :         }
    6326             : 
    6327       55209 :         return nwrap_gethostname(name, len);
    6328             : }
    6329             : 
    6330             : /****************************
    6331             :  * CONSTRUCTOR
    6332             :  ***************************/
    6333      126400 : void nwrap_constructor(void)
    6334             : {
    6335             :         /*
    6336             :          * If we hold a lock and the application forks, then the child
    6337             :          * is not able to unlock the mutex and we are in a deadlock.
    6338             :          *
    6339             :          * Setting these handlers should prevent such deadlocks.
    6340             :          */
    6341      126400 :         pthread_atfork(&nwrap_thread_prepare,
    6342             :                        &nwrap_thread_parent,
    6343             :                        &nwrap_thread_child);
    6344             : 
    6345             :         /* Do not call nwrap_init() here. */
    6346      126400 : }
    6347             : 
    6348             : /****************************
    6349             :  * DESTRUCTOR
    6350             :  ***************************/
    6351             : 
    6352             : /*
    6353             :  * This function is called when the library is unloaded and makes sure that
    6354             :  * sockets get closed and the unix file for the socket are unlinked.
    6355             :  */
    6356      166976 : void nwrap_destructor(void)
    6357             : {
    6358             :         size_t i;
    6359             : 
    6360      166976 :         NWRAP_LOCK_ALL;
    6361      166976 :         if (nwrap_main_global != NULL) {
    6362       77364 :                 struct nwrap_main *m = nwrap_main_global;
    6363             : 
    6364             :                 /* libc */
    6365       77364 :                 if (m->libc != NULL) {
    6366       77364 :                         if (m->libc->handle != NULL) {
    6367       58798 :                                 dlclose(m->libc->handle);
    6368             :                         }
    6369       77364 :                         if (m->libc->nsl_handle != NULL) {
    6370        7874 :                                 dlclose(m->libc->nsl_handle);
    6371             :                         }
    6372       77364 :                         if (m->libc->sock_handle != NULL) {
    6373           0 :                                 dlclose(m->libc->sock_handle);
    6374             :                         }
    6375       77364 :                         SAFE_FREE(m->libc);
    6376             :                 }
    6377             : 
    6378             :                 /* backends */
    6379       77364 :                 if (m->backends != NULL) {
    6380      222046 :                         for (i = 0; i < m->num_backends; i++) {
    6381      146003 :                                 struct nwrap_backend *b = &(m->backends[i]);
    6382             : 
    6383      146003 :                                 if (b->so_handle != NULL) {
    6384       68639 :                                         dlclose(b->so_handle);
    6385             :                                 }
    6386      146003 :                                 SAFE_FREE(b->symbols);
    6387             :                         }
    6388       77364 :                         SAFE_FREE(m->backends);
    6389             :                 }
    6390             :         }
    6391             : 
    6392      166976 :         if (nwrap_pw_global.cache != NULL) {
    6393       77364 :                 struct nwrap_cache *c = nwrap_pw_global.cache;
    6394             : 
    6395       77364 :                 nwrap_files_cache_unload(c);
    6396       77364 :                 if (c->fd >= 0) {
    6397       32149 :                         fclose(c->fp);
    6398       32149 :                         c->fd = -1;
    6399             :                 }
    6400             : 
    6401       77364 :                 SAFE_FREE(nwrap_pw_global.list);
    6402       77364 :                 nwrap_pw_global.num = 0;
    6403             :         }
    6404             : 
    6405      166976 :         if (nwrap_gr_global.cache != NULL) {
    6406       77364 :                 struct nwrap_cache *c = nwrap_gr_global.cache;
    6407             : 
    6408       77364 :                 nwrap_files_cache_unload(c);
    6409       77364 :                 if (c->fd >= 0) {
    6410       28084 :                         fclose(c->fp);
    6411       28084 :                         c->fd = -1;
    6412             :                 }
    6413             : 
    6414       77364 :                 SAFE_FREE(nwrap_gr_global.list);
    6415       77364 :                 nwrap_pw_global.num = 0;
    6416             :         }
    6417             : 
    6418             : #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
    6419      166976 :         if (nwrap_sp_global.cache != NULL) {
    6420       77364 :                 struct nwrap_cache *c = nwrap_sp_global.cache;
    6421             : 
    6422       77364 :                 nwrap_files_cache_unload(c);
    6423       77364 :                 if (c->fd >= 0) {
    6424           0 :                         fclose(c->fp);
    6425           0 :                         c->fd = -1;
    6426             :                 }
    6427             : 
    6428       77364 :                 nwrap_sp_global.num = 0;
    6429             :         }
    6430             : #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    6431             : 
    6432      166976 :         if (nwrap_he_global.cache != NULL) {
    6433       77364 :                 struct nwrap_cache *c = nwrap_he_global.cache;
    6434             : 
    6435       77364 :                 nwrap_files_cache_unload(c);
    6436       77364 :                 if (c->fd >= 0) {
    6437       60950 :                         fclose(c->fp);
    6438       60950 :                         c->fd = -1;
    6439             :                 }
    6440             : 
    6441       77364 :                 nwrap_he_global.num = 0;
    6442             :         }
    6443             : 
    6444      166976 :         free(user_addrlist.items);
    6445             : #ifdef HAVE_GETHOSTBYNAME2
    6446      166976 :         free(user_addrlist2.items);
    6447             : #endif
    6448             : 
    6449      166976 :         hdestroy();
    6450      166976 :         NWRAP_UNLOCK_ALL;
    6451      166976 : }

Generated by: LCOV version 1.13