LCOV - code coverage report
Current view: top level - third_party/nss_wrapper - nss_wrapper.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 1414 2413 58.6 %
Date: 2024-02-14 10:14:15 Functions: 112 160 70.0 %

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

Generated by: LCOV version 1.14