Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/lib/nss_wrapper
Files:
4 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/nss_wrapper/nss_wrapper.c

    r740 r988  
    22 * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
    33 * Copyright (C) Guenther Deschner 2009 <gd@samba.org>
     4 * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
    45 *
    56 * All rights reserved.
     
    3334 */
    3435
    35 #ifdef _SAMBA_BUILD_
    36 
    37 /* defining this gives us the posix getpwnam_r() calls on solaris
    38    Thanks to heimdal for this */
     36#include "config.h"
     37
     38#include <pthread.h>
     39
     40#include <sys/types.h>
     41#include <sys/stat.h>
     42#include <sys/socket.h>
     43#include <errno.h>
     44#include <fcntl.h>
     45#include <stdarg.h>
     46#include <stdbool.h>
     47#include <stddef.h>
     48#include <stdio.h>
     49#include <stdint.h>
     50#include <stdlib.h>
     51#include <string.h>
     52#include <unistd.h>
     53#include <ctype.h>
     54
     55#include <netinet/in.h>
     56
     57#include <search.h>
     58#include <assert.h>
     59
     60/*
     61 * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h  gives us
     62 * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
     63 * Solaris
     64 */
     65#ifndef _POSIX_PTHREAD_SEMANTICS
    3966#define _POSIX_PTHREAD_SEMANTICS
    40 
    41 #define NSS_WRAPPER_NOT_REPLACE
    42 #include "../replace/replace.h"
    43 #include "system/passwd.h"
    44 #include "system/filesys.h"
    45 #include "../nsswitch/nsstest.h"
    46 
    47 #else /* _SAMBA_BUILD_ */
    48 
    49 #error nss_wrapper_only_supported_in_samba_yet
    50 
     67#endif
     68
     69#include <pwd.h>
     70#include <grp.h>
     71#ifdef HAVE_SHADOW_H
     72#include <shadow.h>
     73#endif /* HAVE_SHADOW_H */
     74
     75#include <netdb.h>
     76#include <arpa/inet.h>
     77#include <netinet/in.h>
     78
     79#include <dlfcn.h>
     80
     81#if defined(HAVE_NSS_H)
     82/* Linux and BSD */
     83#include <nss.h>
     84
     85typedef enum nss_status NSS_STATUS;
     86#elif defined(HAVE_NSS_COMMON_H)
     87/* Solaris */
     88#include <nss_common.h>
     89#include <nss_dbdefs.h>
     90#include <nsswitch.h>
     91
     92typedef nss_status_t NSS_STATUS;
     93
     94# define NSS_STATUS_SUCCESS     NSS_SUCCESS
     95# define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
     96# define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
     97# define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
     98#else
     99# error "No nsswitch support detected"
     100#endif
     101
     102#ifndef PTR_DIFF
     103#define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
    51104#endif
    52105
     
    55108#endif
    56109
    57 /* not all systems have _r functions... */
    58 #ifndef HAVE_GETPWNAM_R
    59 #define getpwnam_r(name, pwdst, buf, buflen, pwdstp)    ENOSYS
     110#ifndef EAI_NODATA
     111#define EAI_NODATA EAI_NONAME
    60112#endif
    61 #ifndef HAVE_GETPWUID_R
    62 #define getpwuid_r(uid, pwdst, buf, buflen, pwdstp)     ENOSYS
     113
     114#ifndef EAI_ADDRFAMILY
     115#define EAI_ADDRFAMILY EAI_FAMILY
    63116#endif
    64 #ifndef HAVE_GETPWENT_R
    65 #define getpwent_r(pwdst, buf, buflen, pwdstp)          ENOSYS
     117
     118#ifndef __STRING
     119#define __STRING(x)    #x
    66120#endif
    67 #ifndef HAVE_GETGRNAM_R
    68 #define getgrnam_r(name, grdst, buf, buflen, grdstp)    ENOSYS
     121
     122#ifndef __STRINGSTRING
     123#define __STRINGSTRING(x) __STRING(x)
    69124#endif
    70 #ifndef HAVE_GETGRGID_R
    71 #define getgrgid_r(gid, grdst, buf, buflen, grdstp)     ENOSYS
     125
     126#ifndef __LINESTR__
     127#define __LINESTR__ __STRINGSTRING(__LINE__)
    72128#endif
    73 #ifndef HAVE_GETGRENT_R
    74 #define getgrent_r(grdst, buf, buflen, grdstp)          ENOSYS
     129
     130#ifndef __location__
     131#define __location__ __FILE__ ":" __LINESTR__
    75132#endif
    76133
    77 /* not all systems have getgrouplist */
    78 #ifndef HAVE_GETGROUPLIST
    79 #define getgrouplist(user, group, groups, ngroups)      0
     134#ifndef DNS_NAME_MAX
     135#define DNS_NAME_MAX 255
    80136#endif
    81137
    82 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
    83  * for now */
    84 #define REWRITE_CALLS
    85 
    86 #ifdef REWRITE_CALLS
    87 
    88 #define real_getpwnam           getpwnam
    89 #define real_getpwnam_r         getpwnam_r
    90 #define real_getpwuid           getpwuid
    91 #define real_getpwuid_r         getpwuid_r
    92 
    93 #define real_setpwent           setpwent
    94 #define real_getpwent           getpwent
    95 #define real_getpwent_r         getpwent_r
    96 #define real_endpwent           endpwent
    97 
    98 /*
    99 #define real_getgrlst           getgrlst
    100 #define real_getgrlst_r         getgrlst_r
    101 #define real_initgroups_dyn     initgroups_dyn
    102 */
    103 #define real_initgroups         initgroups
    104 #define real_getgrouplist       getgrouplist
    105 
    106 #define real_getgrnam           getgrnam
    107 #define real_getgrnam_r         getgrnam_r
    108 #define real_getgrgid           getgrgid
    109 #define real_getgrgid_r         getgrgid_r
    110 
    111 #define real_setgrent           setgrent
    112 #define real_getgrent           getgrent
    113 #define real_getgrent_r         getgrent_r
    114 #define real_endgrent           endgrent
    115 
     138/* GCC have printf type attribute check. */
     139#ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
     140#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
     141#else
     142#define PRINTF_ATTRIBUTE(a,b)
     143#endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
     144
     145#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
     146#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
     147#else
     148#define DESTRUCTOR_ATTRIBUTE
     149#endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
     150
     151#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
     152
     153#ifndef SAFE_FREE
     154#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
    116155#endif
    117156
    118 #if 0
    119 # ifdef DEBUG
    120 # define NWRAP_ERROR(args)      DEBUG(0, args)
    121 # else
    122 # define NWRAP_ERROR(args)      printf args
    123 # endif
     157#ifdef HAVE_IPV6
     158#define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
    124159#else
    125 #define NWRAP_ERROR(args)
     160#define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
    126161#endif
    127162
    128 #if 0
    129 # ifdef DEBUG
    130 # define NWRAP_DEBUG(args)      DEBUG(0, args)
    131 # else
    132 # define NWRAP_DEBUG(args)      printf args
    133 # endif
     163#define NWRAP_LOCK(m) do { \
     164        pthread_mutex_lock(&( m ## _mutex)); \
     165} while(0)
     166
     167#define NWRAP_UNLOCK(m) do { \
     168        pthread_mutex_unlock(&( m ## _mutex)); \
     169} while(0)
     170
     171
     172static bool nwrap_initialized = false;
     173static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
     174
     175/* The mutex or accessing the id */
     176static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     177static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     178static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     179static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     180static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
     181
     182/* Add new global locks here please */
     183/* Also don't forget to add locks to
     184 * nwrap_init() function.
     185 */
     186# define NWRAP_LOCK_ALL do { \
     187        NWRAP_LOCK(nwrap_initialized); \
     188        NWRAP_LOCK(nwrap_global); \
     189        NWRAP_LOCK(nwrap_gr_global); \
     190        NWRAP_LOCK(nwrap_he_global); \
     191        NWRAP_LOCK(nwrap_pw_global); \
     192        NWRAP_LOCK(nwrap_sp_global); \
     193} while (0);
     194
     195# define NWRAP_UNLOCK_ALL do {\
     196        NWRAP_UNLOCK(nwrap_sp_global); \
     197        NWRAP_UNLOCK(nwrap_pw_global); \
     198        NWRAP_UNLOCK(nwrap_he_global); \
     199        NWRAP_UNLOCK(nwrap_gr_global); \
     200        NWRAP_UNLOCK(nwrap_global); \
     201        NWRAP_UNLOCK(nwrap_initialized); \
     202} while (0);
     203
     204static void nwrap_thread_prepare(void)
     205{
     206        NWRAP_LOCK_ALL;
     207}
     208
     209static void nwrap_thread_parent(void)
     210{
     211        NWRAP_UNLOCK_ALL;
     212}
     213
     214static void nwrap_thread_child(void)
     215{
     216        NWRAP_UNLOCK_ALL;
     217}
     218
     219enum nwrap_dbglvl_e {
     220        NWRAP_LOG_ERROR = 0,
     221        NWRAP_LOG_WARN,
     222        NWRAP_LOG_DEBUG,
     223        NWRAP_LOG_TRACE
     224};
     225
     226#ifdef NDEBUG
     227# define NWRAP_LOG(...)
    134228#else
    135 #define NWRAP_DEBUG(args)
     229
     230static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
     231# define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
     232
     233static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
     234                      const char *func,
     235                      const char *format, ...)
     236{
     237        char buffer[1024];
     238        va_list va;
     239        const char *d;
     240        unsigned int lvl = 0;
     241        int pid = getpid();
     242
     243        d = getenv("NSS_WRAPPER_DEBUGLEVEL");
     244        if (d != NULL) {
     245                lvl = atoi(d);
     246        }
     247
     248        va_start(va, format);
     249        vsnprintf(buffer, sizeof(buffer), format, va);
     250        va_end(va);
     251
     252        if (lvl >= dbglvl) {
     253                switch (dbglvl) {
     254                        case NWRAP_LOG_ERROR:
     255                                fprintf(stderr,
     256                                        "NWRAP_ERROR(%d) - %s: %s\n",
     257                                        pid, func, buffer);
     258                                break;
     259                        case NWRAP_LOG_WARN:
     260                                fprintf(stderr,
     261                                        "NWRAP_WARN(%d) - %s: %s\n",
     262                                        pid, func, buffer);
     263                                break;
     264                        case NWRAP_LOG_DEBUG:
     265                                fprintf(stderr,
     266                                        "NWRAP_DEBUG(%d) - %s: %s\n",
     267                                        pid, func, buffer);
     268                                break;
     269                        case NWRAP_LOG_TRACE:
     270                                fprintf(stderr,
     271                                        "NWRAP_TRACE(%d) - %s: %s\n",
     272                                        pid, func, buffer);
     273                                break;
     274                }
     275        }
     276}
     277#endif /* NDEBUG NWRAP_LOG */
     278
     279struct nwrap_libc_fns {
     280        struct passwd *(*_libc_getpwnam)(const char *name);
     281        int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
     282                       char *buf, size_t buflen, struct passwd **result);
     283        struct passwd *(*_libc_getpwuid)(uid_t uid);
     284        int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
     285        void (*_libc_setpwent)(void);
     286        struct passwd *(*_libc_getpwent)(void);
     287#ifdef HAVE_SOLARIS_GETPWENT_R
     288        struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
     289#else
     290        int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
    136291#endif
    137 
    138 #if 0
    139 # ifdef DEBUG
    140 # define NWRAP_VERBOSE(args)    DEBUG(0, args)
    141 # else
    142 # define NWRAP_VERBOSE(args)    printf args
    143 # endif
     292        void (*_libc_endpwent)(void);
     293        int (*_libc_initgroups)(const char *user, gid_t gid);
     294        struct group *(*_libc_getgrnam)(const char *name);
     295        int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
     296        struct group *(*_libc_getgrgid)(gid_t gid);
     297        int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
     298        void (*_libc_setgrent)(void);
     299        struct group *(*_libc_getgrent)(void);
     300#ifdef HAVE_SOLARIS_GETGRENT_R
     301        struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
    144302#else
    145 #define NWRAP_VERBOSE(args)
     303        int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
    146304#endif
     305        void (*_libc_endgrent)(void);
     306        int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
     307
     308        void (*_libc_sethostent)(int stayopen);
     309        struct hostent *(*_libc_gethostent)(void);
     310        void (*_libc_endhostent)(void);
     311
     312        struct hostent *(*_libc_gethostbyname)(const char *name);
     313#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
     314        struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
     315#endif
     316        struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
     317
     318        int (*_libc_getaddrinfo)(const char *node, const char *service,
     319                                 const struct addrinfo *hints,
     320                                 struct addrinfo **res);
     321        int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
     322                                 char *host, size_t hostlen,
     323                                 char *serv, size_t servlen,
     324                                 int flags);
     325        int (*_libc_gethostname)(char *name, size_t len);
     326#ifdef HAVE_GETHOSTBYNAME_R
     327        int (*_libc_gethostbyname_r)(const char *name,
     328                                     struct hostent *ret,
     329                                     char *buf, size_t buflen,
     330                                     struct hostent **result, int *h_errnop);
     331#endif
     332#ifdef HAVE_GETHOSTBYADDR_R
     333        int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
     334                                     struct hostent *ret,
     335                                     char *buf, size_t buflen,
     336                                     struct hostent **result, int *h_errnop);
     337#endif
     338};
    147339
    148340struct nwrap_module_nss_fns {
     
    212404};
    213405
     406/* Public prototypes */
     407
     408bool nss_wrapper_enabled(void);
     409bool nss_wrapper_shadow_enabled(void);
     410bool nss_wrapper_hosts_enabled(void);
     411
    214412/* prototypes for files backend */
    215413
     
    327525};
    328526
     527struct nwrap_libc {
     528        void *handle;
     529        void *nsl_handle;
     530        void *sock_handle;
     531        struct nwrap_libc_fns *fns;
     532};
     533
    329534struct nwrap_main {
    330         const char *nwrap_switch;
    331535        int num_backends;
    332536        struct nwrap_backend *backends;
     537        struct nwrap_libc *libc;
    333538};
    334539
    335 struct nwrap_main *nwrap_main_global;
    336 struct nwrap_main __nwrap_main_global;
     540static struct nwrap_main *nwrap_main_global;
     541static struct nwrap_main __nwrap_main_global;
     542
     543/*
     544 * PROTOTYPES
     545 */
     546static int nwrap_convert_he_ai(const struct hostent *he,
     547                               unsigned short port,
     548                               const struct addrinfo *hints,
     549                               struct addrinfo **pai,
     550                               bool skip_canonname);
     551
     552/*
     553 * VECTORS
     554 */
     555
     556#define DEFAULT_VECTOR_CAPACITY 16
     557
     558struct nwrap_vector {
     559        void **items;
     560        size_t count;
     561        size_t capacity;
     562};
     563
     564/* Macro returns pointer to first element of vector->items array.
     565 *
     566 * nwrap_vector is used as a memory backend which take care of
     567 * memory allocations and other stuff like memory growing.
     568 * nwrap_vectors should not be considered as some abstract structures.
     569 * On this level, vectors are more handy than direct realloc/malloc
     570 * calls.
     571 *
     572 * nwrap_vector->items is array inside nwrap_vector which can be
     573 * directly pointed by libc structure assembled by cwrap itself.
     574 *
     575 * EXAMPLE:
     576 *
     577 * 1) struct hostent contains char **h_addr_list element.
     578 * 2) nwrap_vector holds array of pointers to addresses.
     579 *    It's easier to use vector to store results of
     580 *    file parsing etc.
     581 *
     582 * Now, pretend that cwrap assembled struct hostent and
     583 * we need to set h_addr_list to point to nwrap_vector.
     584 * Idea behind is to shield users from internal nwrap_vector
     585 * implementation.
     586 * (Yes, not fully - array terminated by NULL is needed because
     587 * it's result expected by libc function caller.)
     588 *
     589 *
     590 * CODE EXAMPLE:
     591 *
     592 * struct hostent he;
     593 * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
     594 * ... don't care about failed allocation now ...
     595 *
     596 * ... fill nwrap vector ...
     597 *
     598 * struct hostent he;
     599 * he.h_addr_list = nwrap_vector_head(vector);
     600 *
     601 */
     602#define nwrap_vector_head(vect) ((void *)((vect)->items))
     603
     604#define nwrap_vector_foreach(item, vect, iter) \
     605        for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
     606             item != NULL; \
     607             (item) = (vect).items[++iter])
     608
     609#define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
     610
     611static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
     612{
     613        if (vector == NULL) {
     614                return false;
     615        }
     616
     617        /* count is initialized by ZERO_STRUCTP */
     618        ZERO_STRUCTP(vector);
     619        vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     620        if (vector->items == NULL) {
     621                return false;
     622        }
     623        vector->capacity = DEFAULT_VECTOR_CAPACITY;
     624        memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
     625
     626        return true;
     627}
     628
     629static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
     630{
     631        assert (vector != NULL);
     632
     633        if (vector->items == NULL) {
     634                nwrap_vector_init(vector);
     635        }
     636
     637        if (vector->count == vector->capacity) {
     638                /* Items array _MUST_ be NULL terminated because it's passed
     639                 * as result to caller which expect NULL terminated array from libc.
     640                 */
     641                void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
     642                if (items == NULL) {
     643                        return false;
     644                }
     645                vector->items = items;
     646
     647                /* Don't count ending NULL to capacity */
     648                vector->capacity *= 2;
     649        }
     650
     651        vector->items[vector->count] = item;
     652
     653        vector->count += 1;
     654        vector->items[vector->count] = NULL;
     655
     656        return true;
     657}
     658
     659static bool nwrap_vector_merge(struct nwrap_vector *dst,
     660                               struct nwrap_vector *src)
     661{
     662        void **dst_items = NULL;
     663        size_t count;
     664
     665        if (src->count == 0) {
     666                return true;
     667        }
     668
     669        count = dst->count + src->count;
     670
     671        /* We don't need reallocation if we have enough capacity. */
     672        if (src->count > (dst->capacity - dst->count)) {
     673                dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
     674                if (dst_items == NULL) {
     675                        return false;
     676                }
     677                dst->items = dst_items;
     678                dst->capacity = count;
     679        }
     680
     681        memcpy((void *)(((long *)dst->items) + dst->count),
     682               src->items,
     683               src->count * sizeof(void *));
     684        dst->count = count;
     685
     686        return true;
     687}
    337688
    338689struct nwrap_cache {
    339690        const char *path;
    340691        int fd;
     692        FILE *fp;
    341693        struct stat st;
    342         uint8_t *buf;
    343694        void *private_data;
     695
     696        struct nwrap_vector lines;
     697
    344698        bool (*parse_line)(struct nwrap_cache *, char *line);
    345699        void (*unload)(struct nwrap_cache *);
    346700};
    347701
     702/* passwd */
    348703struct nwrap_pw {
    349704        struct nwrap_cache *cache;
     
    360715static void nwrap_pw_unload(struct nwrap_cache *nwrap);
    361716
     717/* shadow */
     718#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     719struct nwrap_sp {
     720        struct nwrap_cache *cache;
     721
     722        struct spwd *list;
     723        int num;
     724        int idx;
     725};
     726
     727struct nwrap_cache __nwrap_cache_sp;
     728struct nwrap_sp nwrap_sp_global;
     729
     730static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
     731static void nwrap_sp_unload(struct nwrap_cache *nwrap);
     732#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     733
     734/* group */
    362735struct nwrap_gr {
    363736        struct nwrap_cache *cache;
     
    371744struct nwrap_gr nwrap_gr_global;
    372745
     746/* hosts */
     747static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
     748static void nwrap_he_unload(struct nwrap_cache *nwrap);
     749
     750struct nwrap_addrdata {
     751        unsigned char host_addr[16]; /* IPv4 or IPv6 address */
     752};
     753
     754static size_t max_hostents = 100;
     755
     756struct nwrap_entdata {
     757        struct nwrap_addrdata addr;
     758        struct hostent ht;
     759
     760        struct nwrap_vector nwrap_addrdata;
     761
     762        ssize_t aliases_count;
     763};
     764
     765struct nwrap_entlist {
     766        struct nwrap_entlist *next;
     767        struct nwrap_entdata *ed;
     768};
     769
     770struct nwrap_he {
     771        struct nwrap_cache *cache;
     772
     773        struct nwrap_vector entries;
     774        struct nwrap_vector lists;
     775
     776        int num;
     777        int idx;
     778};
     779
     780static struct nwrap_cache __nwrap_cache_he;
     781static struct nwrap_he nwrap_he_global;
     782
     783
     784/*********************************************************
     785 * NWRAP PROTOTYPES
     786 *********************************************************/
     787
     788static void nwrap_init(void);
    373789static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
    374790static void nwrap_gr_unload(struct nwrap_cache *nwrap);
     791void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
     792
     793/*********************************************************
     794 * NWRAP LIBC LOADER FUNCTIONS
     795 *********************************************************/
     796
     797enum nwrap_lib {
     798    NWRAP_LIBC,
     799    NWRAP_LIBNSL,
     800    NWRAP_LIBSOCKET,
     801};
     802
     803#ifndef NDEBUG
     804static const char *nwrap_str_lib(enum nwrap_lib lib)
     805{
     806        switch (lib) {
     807        case NWRAP_LIBC:
     808                return "libc";
     809        case NWRAP_LIBNSL:
     810                return "libnsl";
     811        case NWRAP_LIBSOCKET:
     812                return "libsocket";
     813        }
     814
     815        /* Compiler would warn us about unhandled enum value if we get here */
     816        return "unknown";
     817}
     818#endif
     819
     820static void *nwrap_load_lib_handle(enum nwrap_lib lib)
     821{
     822        int flags = RTLD_LAZY;
     823        void *handle = NULL;
     824        int i;
     825
     826#ifdef RTLD_DEEPBIND
     827        flags |= RTLD_DEEPBIND;
     828#endif
     829
     830        switch (lib) {
     831        case NWRAP_LIBNSL:
     832#ifdef HAVE_LIBNSL
     833                handle = nwrap_main_global->libc->nsl_handle;
     834                if (handle == NULL) {
     835                        for (i = 10; i >= 0; i--) {
     836                                char soname[256] = {0};
     837
     838                                snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
     839                                handle = dlopen(soname, flags);
     840                                if (handle != NULL) {
     841                                        break;
     842                                }
     843                        }
     844
     845                        nwrap_main_global->libc->nsl_handle = handle;
     846                }
     847                break;
     848#endif
     849                /* FALL TROUGH */
     850        case NWRAP_LIBSOCKET:
     851#ifdef HAVE_LIBSOCKET
     852                handle = nwrap_main_global->libc->sock_handle;
     853                if (handle == NULL) {
     854                        for (i = 10; i >= 0; i--) {
     855                                char soname[256] = {0};
     856
     857                                snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
     858                                handle = dlopen(soname, flags);
     859                                if (handle != NULL) {
     860                                        break;
     861                                }
     862                        }
     863
     864                        nwrap_main_global->libc->sock_handle = handle;
     865                }
     866                break;
     867#endif
     868                /* FALL TROUGH */
     869        case NWRAP_LIBC:
     870                handle = nwrap_main_global->libc->handle;
     871                if (handle == NULL) {
     872                        for (i = 10; i >= 0; i--) {
     873                                char soname[256] = {0};
     874
     875                                snprintf(soname, sizeof(soname), "libc.so.%d", i);
     876                                handle = dlopen(soname, flags);
     877                                if (handle != NULL) {
     878                                        break;
     879                                }
     880                        }
     881
     882                        nwrap_main_global->libc->handle = handle;
     883                }
     884                break;
     885        }
     886
     887        if (handle == NULL) {
     888#ifdef RTLD_NEXT
     889                handle = nwrap_main_global->libc->handle
     890                       = nwrap_main_global->libc->sock_handle
     891                       = nwrap_main_global->libc->nsl_handle
     892                       = RTLD_NEXT;
     893#else
     894                NWRAP_LOG(NWRAP_LOG_ERROR,
     895                          "Failed to dlopen library: %s\n",
     896                          dlerror());
     897                exit(-1);
     898#endif
     899        }
     900
     901        return handle;
     902}
     903
     904static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
     905{
     906        void *handle;
     907        void *func;
     908
     909        nwrap_init();
     910
     911        handle = nwrap_load_lib_handle(lib);
     912
     913        func = dlsym(handle, fn_name);
     914        if (func == NULL) {
     915                NWRAP_LOG(NWRAP_LOG_ERROR,
     916                                "Failed to find %s: %s\n",
     917                                fn_name, dlerror());
     918                exit(-1);
     919        }
     920
     921        NWRAP_LOG(NWRAP_LOG_TRACE,
     922                        "Loaded %s from %s",
     923                        fn_name, nwrap_str_lib(lib));
     924        return func;
     925}
     926
     927#define nwrap_load_lib_function(lib, fn_name) \
     928        if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
     929                *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
     930                        _nwrap_load_lib_function(lib, #fn_name); \
     931        }
     932
     933/* INTERNAL HELPER FUNCTIONS */
     934static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
     935{
     936        size_t p;
     937        void *item;
     938        nwrap_vector_foreach(item, nwrap->lines, p) {
     939                /* Maybe some vectors were merged ... */
     940                SAFE_FREE(item);
     941        }
     942        SAFE_FREE(nwrap->lines.items);
     943        ZERO_STRUCTP(&nwrap->lines);
     944}
     945
     946/*
     947 * IMPORTANT
     948 *
     949 * Functions expeciall from libc need to be loaded individually, you can't load
     950 * all at once or gdb will segfault at startup. The same applies to valgrind and
     951 * has probably something todo with with the linker.
     952 * So we need load each function at the point it is called the first time.
     953 */
     954static struct passwd *libc_getpwnam(const char *name)
     955{
     956        nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
     957
     958        return nwrap_main_global->libc->fns->_libc_getpwnam(name);
     959}
     960
     961#ifdef HAVE_GETPWNAM_R
     962static int libc_getpwnam_r(const char *name,
     963                           struct passwd *pwd,
     964                           char *buf,
     965                           size_t buflen,
     966                           struct passwd **result)
     967{
     968#ifdef HAVE___POSIX_GETPWNAM_R
     969        if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
     970                *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
     971                        _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
     972        }
     973#else
     974        nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
     975#endif
     976
     977        return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
     978                                                              pwd,
     979                                                              buf,
     980                                                              buflen,
     981                                                              result);
     982}
     983#endif
     984
     985static struct passwd *libc_getpwuid(uid_t uid)
     986{
     987        nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
     988
     989        return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
     990}
     991
     992#ifdef HAVE_GETPWUID_R
     993static int libc_getpwuid_r(uid_t uid,
     994                           struct passwd *pwd,
     995                           char *buf,
     996                           size_t buflen,
     997                           struct passwd **result)
     998{
     999#ifdef HAVE___POSIX_GETPWUID_R
     1000        if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
     1001                *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
     1002                        _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
     1003        }
     1004#else
     1005        nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
     1006#endif
     1007
     1008        return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
     1009                                                              pwd,
     1010                                                              buf,
     1011                                                              buflen,
     1012                                                              result);
     1013}
     1014#endif
     1015
     1016static inline void str_tolower(char *dst, char *src)
     1017{
     1018        register char *src_tmp = src;
     1019        register char *dst_tmp = dst;
     1020
     1021        while (*src_tmp != '\0') {
     1022                *dst_tmp = tolower(*src_tmp);
     1023                ++src_tmp;
     1024                ++dst_tmp;
     1025        }
     1026}
     1027
     1028static bool str_tolower_copy(char **dst_name, const char *const src_name)
     1029{
     1030        char *h_name_lower;
     1031
     1032        if ((dst_name == NULL) || (src_name == NULL)) {
     1033                return false;
     1034        }
     1035
     1036        h_name_lower = strdup(src_name);
     1037        if (h_name_lower == NULL) {
     1038                NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
     1039                return false;
     1040        }
     1041
     1042        str_tolower(h_name_lower, h_name_lower);
     1043        *dst_name = h_name_lower;
     1044        return true;
     1045}
     1046
     1047static void libc_setpwent(void)
     1048{
     1049        nwrap_load_lib_function(NWRAP_LIBC, setpwent);
     1050
     1051        nwrap_main_global->libc->fns->_libc_setpwent();
     1052}
     1053
     1054static struct passwd *libc_getpwent(void)
     1055{
     1056        nwrap_load_lib_function(NWRAP_LIBC, getpwent);
     1057
     1058        return nwrap_main_global->libc->fns->_libc_getpwent();
     1059}
     1060
     1061#ifdef HAVE_SOLARIS_GETPWENT_R
     1062static struct passwd *libc_getpwent_r(struct passwd *pwdst,
     1063                                      char *buf,
     1064                                      int buflen)
     1065{
     1066        nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
     1067
     1068        return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
     1069                                                              buf,
     1070                                                              buflen);
     1071}
     1072#else /* HAVE_SOLARIS_GETPWENT_R */
     1073static int libc_getpwent_r(struct passwd *pwdst,
     1074                           char *buf,
     1075                           size_t buflen,
     1076                           struct passwd **pwdstp)
     1077{
     1078        nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
     1079
     1080        return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
     1081                                                              buf,
     1082                                                              buflen,
     1083                                                              pwdstp);
     1084}
     1085#endif /* HAVE_SOLARIS_GETPWENT_R */
     1086
     1087static void libc_endpwent(void)
     1088{
     1089        nwrap_load_lib_function(NWRAP_LIBC, endpwent);
     1090
     1091        nwrap_main_global->libc->fns->_libc_endpwent();
     1092}
     1093
     1094static int libc_initgroups(const char *user, gid_t gid)
     1095{
     1096        nwrap_load_lib_function(NWRAP_LIBC, initgroups);
     1097
     1098        return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
     1099}
     1100
     1101static struct group *libc_getgrnam(const char *name)
     1102{
     1103        nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
     1104
     1105        return nwrap_main_global->libc->fns->_libc_getgrnam(name);
     1106}
     1107
     1108#ifdef HAVE_GETGRNAM_R
     1109static int libc_getgrnam_r(const char *name,
     1110                           struct group *grp,
     1111                           char *buf,
     1112                           size_t buflen,
     1113                           struct group **result)
     1114{
     1115#ifdef HAVE___POSIX_GETGRNAM_R
     1116        if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
     1117                *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
     1118                        _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
     1119        }
     1120#else
     1121        nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
     1122#endif
     1123
     1124        return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
     1125                                                              grp,
     1126                                                              buf,
     1127                                                              buflen,
     1128                                                              result);
     1129}
     1130#endif
     1131
     1132static struct group *libc_getgrgid(gid_t gid)
     1133{
     1134        nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
     1135
     1136        return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
     1137}
     1138
     1139#ifdef HAVE_GETGRGID_R
     1140static int libc_getgrgid_r(gid_t gid,
     1141                           struct group *grp,
     1142                           char *buf,
     1143                           size_t buflen,
     1144                           struct group **result)
     1145{
     1146#ifdef HAVE___POSIX_GETGRGID_R
     1147        if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
     1148                *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
     1149                        _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
     1150        }
     1151#else
     1152        nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
     1153#endif
     1154
     1155        return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
     1156                                                              grp,
     1157                                                              buf,
     1158                                                              buflen,
     1159                                                              result);
     1160}
     1161#endif
     1162
     1163static void libc_setgrent(void)
     1164{
     1165        nwrap_load_lib_function(NWRAP_LIBC, setgrent);
     1166
     1167        nwrap_main_global->libc->fns->_libc_setgrent();
     1168}
     1169
     1170static struct group *libc_getgrent(void)
     1171{
     1172        nwrap_load_lib_function(NWRAP_LIBC, getgrent);
     1173
     1174        return nwrap_main_global->libc->fns->_libc_getgrent();
     1175}
     1176
     1177#ifdef HAVE_GETGRENT_R
     1178#ifdef HAVE_SOLARIS_GETGRENT_R
     1179static struct group *libc_getgrent_r(struct group *group,
     1180                                     char *buf,
     1181                                     size_t buflen)
     1182{
     1183        nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
     1184
     1185        return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
     1186                                                              buf,
     1187                                                              buflen);
     1188}
     1189#else /* !HAVE_SOLARIS_GETGRENT_R */
     1190static int libc_getgrent_r(struct group *group,
     1191                           char *buf,
     1192                           size_t buflen,
     1193                           struct group **result)
     1194{
     1195        nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
     1196
     1197        return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
     1198                                                              buf,
     1199                                                              buflen,
     1200                                                              result);
     1201}
     1202#endif /* HAVE_SOLARIS_GETGRENT_R */
     1203#endif /* HAVE_GETGRENT_R */
     1204
     1205static void libc_endgrent(void)
     1206{
     1207        nwrap_load_lib_function(NWRAP_LIBC, endgrent);
     1208
     1209        nwrap_main_global->libc->fns->_libc_endgrent();
     1210}
     1211
     1212#ifdef HAVE_GETGROUPLIST
     1213static int libc_getgrouplist(const char *user,
     1214                             gid_t group,
     1215                             gid_t *groups,
     1216                             int *ngroups)
     1217{
     1218        nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
     1219
     1220        return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
     1221                                                                group,
     1222                                                                groups,
     1223                                                                ngroups);
     1224}
     1225#endif
     1226
     1227static void libc_sethostent(int stayopen)
     1228{
     1229        nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
     1230
     1231        nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
     1232}
     1233
     1234static struct hostent *libc_gethostent(void)
     1235{
     1236        nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
     1237
     1238        return nwrap_main_global->libc->fns->_libc_gethostent();
     1239}
     1240
     1241static void libc_endhostent(void)
     1242{
     1243        nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
     1244
     1245        nwrap_main_global->libc->fns->_libc_endhostent();
     1246}
     1247
     1248static struct hostent *libc_gethostbyname(const char *name)
     1249{
     1250        nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
     1251
     1252        return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
     1253}
     1254
     1255#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
     1256static struct hostent *libc_gethostbyname2(const char *name, int af)
     1257{
     1258        nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
     1259
     1260        return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
     1261}
     1262#endif
     1263
     1264static struct hostent *libc_gethostbyaddr(const void *addr,
     1265                                          socklen_t len,
     1266                                          int type)
     1267{
     1268        nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
     1269
     1270        return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
     1271                                                                 len,
     1272                                                                 type);
     1273}
     1274
     1275static int libc_gethostname(char *name, size_t len)
     1276{
     1277        nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
     1278
     1279        return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
     1280}
     1281
     1282#ifdef HAVE_GETHOSTBYNAME_R
     1283static int libc_gethostbyname_r(const char *name,
     1284                                struct hostent *ret,
     1285                                char *buf,
     1286                                size_t buflen,
     1287                                struct hostent **result,
     1288                                int *h_errnop)
     1289{
     1290        nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
     1291
     1292        return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
     1293                                                                   ret,
     1294                                                                   buf,
     1295                                                                   buflen,
     1296                                                                   result,
     1297                                                                   h_errnop);
     1298}
     1299#endif
     1300
     1301#ifdef HAVE_GETHOSTBYADDR_R
     1302static int libc_gethostbyaddr_r(const void *addr,
     1303                                socklen_t len,
     1304                                int type,
     1305                                struct hostent *ret,
     1306                                char *buf,
     1307                                size_t buflen,
     1308                                struct hostent **result,
     1309                                int *h_errnop)
     1310{
     1311        nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
     1312
     1313        return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
     1314                                                                   len,
     1315                                                                   type,
     1316                                                                   ret,
     1317                                                                   buf,
     1318                                                                   buflen,
     1319                                                                   result,
     1320                                                                   h_errnop);
     1321}
     1322#endif
     1323
     1324static int libc_getaddrinfo(const char *node,
     1325                            const char *service,
     1326                            const struct addrinfo *hints,
     1327                            struct addrinfo **res)
     1328{
     1329        nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
     1330
     1331        return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
     1332                                                               service,
     1333                                                               hints,
     1334                                                               res);
     1335}
     1336
     1337static int libc_getnameinfo(const struct sockaddr *sa,
     1338                            socklen_t salen,
     1339                            char *host,
     1340                            size_t hostlen,
     1341                            char *serv,
     1342                            size_t servlen,
     1343                            int flags)
     1344{
     1345        nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
     1346
     1347        return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
     1348                                                               salen,
     1349                                                               host,
     1350                                                               hostlen,
     1351                                                               serv,
     1352                                                               servlen,
     1353                                                               flags);
     1354}
     1355
     1356/*********************************************************
     1357 * NWRAP NSS MODULE LOADER FUNCTIONS
     1358 *********************************************************/
    3751359
    3761360static void *nwrap_load_module_fn(struct nwrap_backend *b,
     
    3811365
    3821366        if (!b->so_handle) {
    383                 NWRAP_ERROR(("%s: no handle\n",
    384                              __location__));
     1367                NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
    3851368                return NULL;
    3861369        }
    3871370
    3881371        if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
    389                 NWRAP_ERROR(("%s: out of memory\n",
    390                              __location__));
     1372                NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    3911373                return NULL;
    3921374        }
     
    3941376        res = dlsym(b->so_handle, s);
    3951377        if (!res) {
    396                 NWRAP_ERROR(("%s: cannot find function %s in %s\n",
    397                              __location__, s, b->so_path));
    398         }
    399         free(s);
    400         s = NULL;
     1378                NWRAP_LOG(NWRAP_LOG_ERROR,
     1379                          "Cannot find function %s in %s",
     1380                          s, b->so_path);
     1381        }
     1382        SAFE_FREE(s);
    4011383        return res;
    4021384}
     
    4151397        }
    4161398
    417         fns->_nss_getpwnam_r    = (NSS_STATUS (*)(const char *, struct passwd *, char *, size_t, int *))
    418                                   nwrap_load_module_fn(b, "getpwnam_r");
    419         fns->_nss_getpwuid_r    = (NSS_STATUS (*)(uid_t, struct passwd *, char *, size_t, int *))
    420                                   nwrap_load_module_fn(b, "getpwuid_r");
    421         fns->_nss_setpwent      = (NSS_STATUS(*)(void))
    422                                   nwrap_load_module_fn(b, "setpwent");
    423         fns->_nss_getpwent_r    = (NSS_STATUS (*)(struct passwd *, char *, size_t, int *))
    424                                   nwrap_load_module_fn(b, "getpwent_r");
    425         fns->_nss_endpwent      = (NSS_STATUS(*)(void))
    426                                   nwrap_load_module_fn(b, "endpwent");
    427         fns->_nss_initgroups    = (NSS_STATUS (*)(const char *, gid_t, long int *, long int *, gid_t **, long int, int *))
    428                                   nwrap_load_module_fn(b, "initgroups_dyn");
    429         fns->_nss_getgrnam_r    = (NSS_STATUS (*)(const char *, struct group *, char *, size_t, int *))
    430                                   nwrap_load_module_fn(b, "getgrnam_r");
    431         fns->_nss_getgrgid_r    = (NSS_STATUS (*)(gid_t, struct group *, char *, size_t, int *))
    432                                   nwrap_load_module_fn(b, "getgrgid_r");
    433         fns->_nss_setgrent      = (NSS_STATUS(*)(void))
    434                                   nwrap_load_module_fn(b, "setgrent");
    435         fns->_nss_getgrent_r    = (NSS_STATUS (*)(struct group *, char *, size_t, int *))
    436                                   nwrap_load_module_fn(b, "getgrent_r");
    437         fns->_nss_endgrent      = (NSS_STATUS(*)(void))
    438                                   nwrap_load_module_fn(b, "endgrent");
     1399        *(void **)(&fns->_nss_getpwnam_r) =
     1400                nwrap_load_module_fn(b, "getpwnam_r");
     1401        *(void **)(&fns->_nss_getpwuid_r) =
     1402                nwrap_load_module_fn(b, "getpwuid_r");
     1403        *(void **)(&fns->_nss_setpwent) =
     1404                nwrap_load_module_fn(b, "setpwent");
     1405        *(void **)(&fns->_nss_getpwent_r) =
     1406                nwrap_load_module_fn(b, "getpwent_r");
     1407        *(void **)(&fns->_nss_endpwent) =
     1408                nwrap_load_module_fn(b, "endpwent");
     1409        *(void **)(&fns->_nss_initgroups) =
     1410                nwrap_load_module_fn(b, "initgroups_dyn");
     1411        *(void **)(&fns->_nss_getgrnam_r) =
     1412                nwrap_load_module_fn(b, "getgrnam_r");
     1413        *(void **)(&fns->_nss_getgrgid_r)=
     1414                nwrap_load_module_fn(b, "getgrgid_r");
     1415        *(void **)(&fns->_nss_setgrent) =
     1416                nwrap_load_module_fn(b, "setgrent");
     1417        *(void **)(&fns->_nss_getgrent_r) =
     1418                nwrap_load_module_fn(b, "getgrent_r");
     1419        *(void **)(&fns->_nss_endgrent) =
     1420                nwrap_load_module_fn(b, "endgrent");
    4391421
    4401422        return fns;
     
    4511433        h = dlopen(so_path, RTLD_LAZY);
    4521434        if (!h) {
    453                 NWRAP_ERROR(("%s: cannot open shared library %s\n",
    454                              __location__, so_path));
     1435                NWRAP_LOG(NWRAP_LOG_ERROR,
     1436                          "Cannot open shared library %s",
     1437                          so_path);
    4551438                return NULL;
    4561439        }
     
    4701453                sizeof(struct nwrap_backend) * ((*num_backends) + 1));
    4711454        if (!*backends) {
    472                 NWRAP_ERROR(("%s: out of memory\n",
    473                              __location__));
     1455                NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    4741456                return false;
    4751457        }
     
    4971479}
    4981480
     1481static void nwrap_libc_init(struct nwrap_main *r)
     1482{
     1483        r->libc = malloc(sizeof(struct nwrap_libc));
     1484        if (r->libc == NULL) {
     1485                printf("Failed to allocate memory for libc");
     1486                exit(-1);
     1487        }
     1488        ZERO_STRUCTP(r->libc);
     1489
     1490        r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
     1491        if (r->libc->fns == NULL) {
     1492                printf("Failed to allocate memory for libc functions");
     1493                exit(-1);
     1494        }
     1495        ZERO_STRUCTP(r->libc->fns);
     1496}
     1497
    4991498static void nwrap_backend_init(struct nwrap_main *r)
    5001499{
    501         const char *winbind_so_path = getenv("NSS_WRAPPER_WINBIND_SO_PATH");
     1500        const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
     1501        const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
    5021502
    5031503        r->num_backends = 0;
     
    5071507                               &r->num_backends,
    5081508                               &r->backends)) {
    509                 NWRAP_ERROR(("%s: failed to initialize 'files' backend\n",
    510                              __location__));
     1509                NWRAP_LOG(NWRAP_LOG_ERROR,
     1510                          "Failed to initialize 'files' backend");
    5111511                return;
    5121512        }
    5131513
    514         if (winbind_so_path && strlen(winbind_so_path)) {
    515                 if (!nwrap_module_init("winbind", &nwrap_module_ops, winbind_so_path,
     1514        if (module_so_path != NULL &&
     1515            module_so_path[0] != '\0' &&
     1516            module_fn_name != NULL &&
     1517            module_fn_name[0] != '\0') {
     1518                if (!nwrap_module_init(module_fn_name,
     1519                                       &nwrap_module_ops,
     1520                                       module_so_path,
    5161521                                       &r->num_backends,
    5171522                                       &r->backends)) {
    518                         NWRAP_ERROR(("%s: failed to initialize 'winbind' backend\n",
    519                                      __location__));
     1523                        NWRAP_LOG(NWRAP_LOG_ERROR,
     1524                                  "Failed to initialize '%s' backend",
     1525                                  module_fn_name);
    5201526                        return;
    5211527                }
     
    5251531static void nwrap_init(void)
    5261532{
    527         static bool initialized;
    528 
    529         if (initialized) return;
    530         initialized = true;
     1533        const char *env;
     1534        char *endptr;
     1535        size_t max_hostents_tmp;
     1536
     1537        NWRAP_LOCK(nwrap_initialized);
     1538        if (nwrap_initialized) {
     1539                NWRAP_UNLOCK(nwrap_initialized);
     1540                return;
     1541        }
     1542
     1543        /*
     1544         * Still holding nwrap_initialized lock here.
     1545         * We don't use NWRAP_(UN)LOCK_ALL macros here because we
     1546         * want to avoid overhead when other threads do their job.
     1547         */
     1548        NWRAP_LOCK(nwrap_global);
     1549        NWRAP_LOCK(nwrap_gr_global);
     1550        NWRAP_LOCK(nwrap_he_global);
     1551        NWRAP_LOCK(nwrap_pw_global);
     1552        NWRAP_LOCK(nwrap_sp_global);
     1553
     1554        nwrap_initialized = true;
     1555
     1556        /* Initialize pthread_atfork handlers */
     1557        pthread_atfork(&nwrap_thread_prepare, &nwrap_thread_parent,
     1558                       &nwrap_thread_child);
     1559
     1560        env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
     1561        if (env != NULL) {
     1562                max_hostents_tmp = (size_t)strtol(env, &endptr, 10);
     1563                if (((env != '\0') && (endptr == '\0')) ||
     1564                    (max_hostents_tmp == 0)) {
     1565                        NWRAP_LOG(NWRAP_LOG_DEBUG,
     1566                                  "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
     1567                                  "value or value is too small. "
     1568                                  "Using default value: %lu.",
     1569                                  (unsigned long)max_hostents);
     1570                } else {
     1571                        max_hostents = max_hostents_tmp;
     1572                }
     1573        }
     1574        /* Initialize hash table */
     1575        NWRAP_LOG(NWRAP_LOG_DEBUG,
     1576                  "Initializing hash table of size %lu items.",
     1577                  (unsigned long)max_hostents);
     1578        if (hcreate(max_hostents) == 0) {
     1579                NWRAP_LOG(NWRAP_LOG_ERROR,
     1580                          "Failed to initialize hash table");
     1581                goto done;
     1582        }
    5311583
    5321584        nwrap_main_global = &__nwrap_main_global;
    5331585
     1586        nwrap_libc_init(nwrap_main_global);
     1587
    5341588        nwrap_backend_init(nwrap_main_global);
    5351589
     1590        /* passwd */
    5361591        nwrap_pw_global.cache = &__nwrap_cache_pw;
    5371592
    5381593        nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
     1594        nwrap_pw_global.cache->fp = NULL;
    5391595        nwrap_pw_global.cache->fd = -1;
    5401596        nwrap_pw_global.cache->private_data = &nwrap_pw_global;
     
    5421598        nwrap_pw_global.cache->unload = nwrap_pw_unload;
    5431599
     1600        /* shadow */
     1601#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     1602        nwrap_sp_global.cache = &__nwrap_cache_sp;
     1603
     1604        nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
     1605        nwrap_sp_global.cache->fp = NULL;
     1606        nwrap_sp_global.cache->fd = -1;
     1607        nwrap_sp_global.cache->private_data = &nwrap_sp_global;
     1608        nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
     1609        nwrap_sp_global.cache->unload = nwrap_sp_unload;
     1610#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     1611
     1612        /* group */
    5441613        nwrap_gr_global.cache = &__nwrap_cache_gr;
    5451614
    5461615        nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
     1616        nwrap_gr_global.cache->fp = NULL;
    5471617        nwrap_gr_global.cache->fd = -1;
    5481618        nwrap_gr_global.cache->private_data = &nwrap_gr_global;
    5491619        nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
    5501620        nwrap_gr_global.cache->unload = nwrap_gr_unload;
    551 }
    552 
    553 static bool nwrap_enabled(void)
     1621
     1622        /* hosts */
     1623        nwrap_he_global.cache = &__nwrap_cache_he;
     1624
     1625        nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
     1626        nwrap_he_global.cache->fp = NULL;
     1627        nwrap_he_global.cache->fd = -1;
     1628        nwrap_he_global.cache->private_data = &nwrap_he_global;
     1629        nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
     1630        nwrap_he_global.cache->unload = nwrap_he_unload;
     1631
     1632done:
     1633        /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
     1634        NWRAP_UNLOCK_ALL;
     1635}
     1636
     1637bool nss_wrapper_enabled(void)
    5541638{
    5551639        nwrap_init();
    5561640
    557         if (!nwrap_pw_global.cache->path) {
     1641        if (nwrap_pw_global.cache->path == NULL ||
     1642            nwrap_pw_global.cache->path[0] == '\0') {
    5581643                return false;
    5591644        }
    560         if (nwrap_pw_global.cache->path[0] == '\0') {
     1645        if (nwrap_gr_global.cache->path == NULL ||
     1646            nwrap_gr_global.cache->path[0] == '\0') {
    5611647                return false;
    5621648        }
    563         if (!nwrap_gr_global.cache->path) {
     1649
     1650        return true;
     1651}
     1652
     1653#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     1654bool nss_wrapper_shadow_enabled(void)
     1655{
     1656        nwrap_init();
     1657
     1658        if (nwrap_sp_global.cache->path == NULL ||
     1659            nwrap_sp_global.cache->path[0] == '\0') {
    5641660                return false;
    5651661        }
    566         if (nwrap_gr_global.cache->path[0] == '\0') {
     1662
     1663        return true;
     1664}
     1665#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     1666
     1667bool nss_wrapper_hosts_enabled(void)
     1668{
     1669        nwrap_init();
     1670
     1671        if (nwrap_he_global.cache->path == NULL ||
     1672            nwrap_he_global.cache->path[0] == '\0') {
    5671673                return false;
    5681674        }
     
    5711677}
    5721678
     1679static bool nwrap_hostname_enabled(void)
     1680{
     1681        nwrap_init();
     1682
     1683        if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
     1684                return false;
     1685        }
     1686
     1687        return true;
     1688}
     1689
    5731690static bool nwrap_parse_file(struct nwrap_cache *nwrap)
    5741691{
    575         int ret;
    576         uint8_t *buf = NULL;
    577         char *nline;
     1692        char *line = NULL;
     1693        ssize_t n;
     1694        /* Unused but getline needs it */
     1695        size_t len;
     1696        bool ok;
    5781697
    5791698        if (nwrap->st.st_size == 0) {
    580                 NWRAP_DEBUG(("%s: size == 0\n",
    581                              __location__));
    582                 goto done;
    583         }
    584 
     1699                NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
     1700                return true;
     1701        }
     1702
     1703        /* Support for 32-bit system I guess */
    5851704        if (nwrap->st.st_size > INT32_MAX) {
    586                 NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n",
    587                              __location__, (unsigned)nwrap->st.st_size));
    588                 goto failed;
    589         }
    590 
    591         ret = lseek(nwrap->fd, 0, SEEK_SET);
    592         if (ret != 0) {
    593                 NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret));
    594                 goto failed;
    595         }
    596 
    597         buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
    598         if (!buf) {
    599                 NWRAP_ERROR(("%s: malloc failed\n",__location__));
    600                 goto failed;
    601         }
    602 
    603         ret = read(nwrap->fd, buf, nwrap->st.st_size);
    604         if (ret != nwrap->st.st_size) {
    605                 NWRAP_ERROR(("%s: read(%u) gave %d\n",
    606                              __location__, (unsigned)nwrap->st.st_size, ret));
    607                 goto failed;
    608         }
    609 
    610         buf[nwrap->st.st_size] = '\0';
    611 
    612         nline = (char *)buf;
    613         while (nline && nline[0]) {
    614                 char *line;
    615                 char *e;
    616                 bool ok;
    617 
    618                 line = nline;
    619                 nline = NULL;
    620 
    621                 e = strchr(line, '\n');
    622                 if (e) {
    623                         e[0] = '\0';
    624                         e++;
    625                         if (e[0] == '\r') {
    626                                 e[0] = '\0';
    627                                 e++;
     1705                NWRAP_LOG(NWRAP_LOG_ERROR,
     1706                          "Size[%u] larger than INT32_MAX",
     1707                          (unsigned)nwrap->st.st_size);
     1708                return false;
     1709        }
     1710
     1711        rewind(nwrap->fp);
     1712
     1713        do {
     1714                n = getline(&line, &len, nwrap->fp);
     1715                if (n < 0) {
     1716                        SAFE_FREE(line);
     1717                        if (feof(nwrap->fp)) {
     1718                                break;
    6281719                        }
    629                         nline = e;
    630                 }
    631 
    632                 NWRAP_VERBOSE(("%s:'%s'\n",__location__, line));
    633 
    634                 if (strlen(line) == 0) {
     1720
     1721                        NWRAP_LOG(NWRAP_LOG_ERROR,
     1722                                  "Unable to read line from file: %s",
     1723                                  nwrap->path);
     1724                        return false;
     1725                }
     1726
     1727                if (line[n - 1] == '\n') {
     1728                        line[n - 1] = '\0';
     1729                }
     1730
     1731                if (line[0] == '\0') {
     1732                        SAFE_FREE(line);
    6351733                        continue;
    6361734                }
     
    6381736                ok = nwrap->parse_line(nwrap, line);
    6391737                if (!ok) {
    640                         goto failed;
    641                 }
    642         }
    643 
    644 done:
    645         nwrap->buf = buf;
     1738                        NWRAP_LOG(NWRAP_LOG_ERROR,
     1739                                  "Unable to parse line file: %s",
     1740                                  line);
     1741                        SAFE_FREE(line);
     1742                        return false;
     1743                }
     1744
     1745                /* Line is parsed without issues so add it to list */
     1746                ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
     1747                if (!ok) {
     1748                        NWRAP_LOG(NWRAP_LOG_ERROR,
     1749                                  "Unable to add line to vector");
     1750                        return false;
     1751                }
     1752
     1753                /* This forces getline to allocate new memory for line. */
     1754                line = NULL;
     1755        } while (!feof(nwrap->fp));
     1756
    6461757        return true;
    647 
    648 failed:
    649         if (buf) free(buf);
    650         return false;
    6511758}
    6521759
     
    6551762        nwrap->unload(nwrap);
    6561763
    657         if (nwrap->buf) free(nwrap->buf);
    658 
    659         nwrap->buf = NULL;
    660 }
    661 
    662 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
     1764        nwrap_lines_unload(nwrap);
     1765}
     1766
     1767static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
    6631768{
    6641769        struct stat st;
     
    6671772        bool retried = false;
    6681773
     1774        assert(nwrap != NULL);
     1775
    6691776reopen:
    6701777        if (nwrap->fd < 0) {
    671                 nwrap->fd = open(nwrap->path, O_RDONLY);
    672                 if (nwrap->fd < 0) {
    673                         NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n",
    674                                      __location__,
    675                                      nwrap->path, nwrap->fd,
    676                                      strerror(errno)));
    677                         return;
    678                 }
    679                 NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path));
     1778                nwrap->fp = fopen(nwrap->path, "re");
     1779                if (nwrap->fp == NULL) {
     1780                        nwrap->fd = -1;
     1781                        NWRAP_LOG(NWRAP_LOG_ERROR,
     1782                                  "Unable to open '%s' readonly %d:%s",
     1783                                  nwrap->path, nwrap->fd,
     1784                                  strerror(errno));
     1785                        return false;
     1786
     1787                }
     1788                nwrap->fd = fileno(nwrap->fp);
     1789                NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
    6801790        }
    6811791
    6821792        ret = fstat(nwrap->fd, &st);
    6831793        if (ret != 0) {
    684                 NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n",
    685                              __location__,
    686                              nwrap->path,
    687                              ret, strerror(errno)));
    688                 return;
     1794                NWRAP_LOG(NWRAP_LOG_ERROR,
     1795                          "fstat(%s) - %d:%s",
     1796                          nwrap->path,
     1797                          ret,
     1798                          strerror(errno));
     1799                fclose(nwrap->fp);
     1800                nwrap->fp = NULL;
     1801                nwrap->fd = -1;
     1802                return false;
    6891803        }
    6901804
    6911805        if (retried == false && st.st_nlink == 0) {
    6921806                /* maybe someone has replaced the file... */
    693                 NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n",
    694                              __location__, nwrap->path));
     1807                NWRAP_LOG(NWRAP_LOG_TRACE,
     1808                          "st_nlink == 0, reopen %s",
     1809                          nwrap->path);
    6951810                retried = true;
    6961811                memset(&nwrap->st, 0, sizeof(nwrap->st));
    697                 close(nwrap->fd);
     1812                fclose(nwrap->fp);
     1813                nwrap->fp = NULL;
    6981814                nwrap->fd = -1;
    6991815                goto reopen;
     
    7011817
    7021818        if (st.st_mtime == nwrap->st.st_mtime) {
    703                 NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n",
    704                                __location__, (unsigned)st.st_mtime));
    705                 return;
    706         }
    707         NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n",
    708                      __location__, (unsigned)st.st_mtime,
    709                      (unsigned)nwrap->st.st_mtime));
     1819                NWRAP_LOG(NWRAP_LOG_TRACE,
     1820                          "st_mtime[%u] hasn't changed, skip reload",
     1821                          (unsigned)st.st_mtime);
     1822                return true;
     1823        }
     1824
     1825        NWRAP_LOG(NWRAP_LOG_TRACE,
     1826                  "st_mtime has changed [%u] => [%u], start reload",
     1827                  (unsigned)st.st_mtime,
     1828                  (unsigned)nwrap->st.st_mtime);
    7101829
    7111830        nwrap->st = st;
     
    7151834        ok = nwrap_parse_file(nwrap);
    7161835        if (!ok) {
    717                 NWRAP_ERROR(("%s: failed to reload %s\n",
    718                              __location__, nwrap->path));
     1836                NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
    7191837                nwrap_files_cache_unload(nwrap);
    720         }
    721         NWRAP_DEBUG(("%s: reloaded %s\n",
    722                      __location__, nwrap->path));
     1838                return false;
     1839        }
     1840
     1841        NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
     1842        return true;
    7231843}
    7241844
     
    7401860        pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
    7411861        if (!pw) {
    742                 NWRAP_ERROR(("%s:realloc(%u) failed\n",
    743                              __location__, list_size));
     1862                NWRAP_LOG(NWRAP_LOG_ERROR,
     1863                          "realloc(%u) failed",
     1864                          (unsigned)list_size);
    7441865                return false;
    7451866        }
     
    7531874        p = strchr(c, ':');
    7541875        if (!p) {
    755                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    756                              __location__, line, c));
     1876                NWRAP_LOG(NWRAP_LOG_ERROR,
     1877                          "Invalid line[%s]: '%s'",
     1878                          line,
     1879                          c);
    7571880                return false;
    7581881        }
     
    7621885        c = p;
    7631886
    764         NWRAP_VERBOSE(("name[%s]\n", pw->pw_name));
     1887        NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
    7651888
    7661889        /* password */
    7671890        p = strchr(c, ':');
    7681891        if (!p) {
    769                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    770                              __location__, line, c));
     1892                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    7711893                return false;
    7721894        }
     
    7761898        c = p;
    7771899
    778         NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd));
     1900        NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
    7791901
    7801902        /* uid */
    7811903        p = strchr(c, ':');
    7821904        if (!p) {
    783                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    784                              __location__, line, c));
     1905                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    7851906                return false;
    7861907        }
     
    7901911        pw->pw_uid = (uid_t)strtoul(c, &e, 10);
    7911912        if (c == e) {
    792                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    793                              __location__, line, c, strerror(errno)));
     1913                NWRAP_LOG(NWRAP_LOG_ERROR,
     1914                          "Invalid line[%s]: '%s' - %s",
     1915                          line, c, strerror(errno));
    7941916                return false;
    7951917        }
    7961918        if (e == NULL) {
    797                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    798                              __location__, line, c, strerror(errno)));
     1919                NWRAP_LOG(NWRAP_LOG_ERROR,
     1920                          "Invalid line[%s]: '%s' - %s",
     1921                          line, c, strerror(errno));
    7991922                return false;
    8001923        }
    8011924        if (e[0] != '\0') {
    802                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    803                              __location__, line, c, strerror(errno)));
     1925                NWRAP_LOG(NWRAP_LOG_ERROR,
     1926                          "Invalid line[%s]: '%s' - %s",
     1927                          line, c, strerror(errno));
    8041928                return false;
    8051929        }
    8061930        c = p;
    8071931
    808         NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid));
     1932        NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
    8091933
    8101934        /* gid */
    8111935        p = strchr(c, ':');
    8121936        if (!p) {
    813                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    814                              __location__, line, c));
     1937                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    8151938                return false;
    8161939        }
     
    8201943        pw->pw_gid = (gid_t)strtoul(c, &e, 10);
    8211944        if (c == e) {
    822                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    823                              __location__, line, c, strerror(errno)));
     1945                NWRAP_LOG(NWRAP_LOG_ERROR,
     1946                          "Invalid line[%s]: '%s' - %s",
     1947                          line, c, strerror(errno));
    8241948                return false;
    8251949        }
    8261950        if (e == NULL) {
    827                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    828                              __location__, line, c, strerror(errno)));
     1951                NWRAP_LOG(NWRAP_LOG_ERROR,
     1952                          "Invalid line[%s]: '%s' - %s",
     1953                          line, c, strerror(errno));
    8291954                return false;
    8301955        }
    8311956        if (e[0] != '\0') {
    832                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    833                              __location__, line, c, strerror(errno)));
     1957                NWRAP_LOG(NWRAP_LOG_ERROR,
     1958                          "Invalid line[%s]: '%s' - %s",
     1959                          line, c, strerror(errno));
    8341960                return false;
    8351961        }
    8361962        c = p;
    8371963
    838         NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid));
     1964        NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
    8391965
    8401966        /* gecos */
    8411967        p = strchr(c, ':');
    8421968        if (!p) {
    843                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    844                              __location__, line, c));
     1969                NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
    8451970                return false;
    8461971        }
     
    8501975        c = p;
    8511976
    852         NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos));
     1977        NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
    8531978
    8541979        /* dir */
    8551980        p = strchr(c, ':');
    8561981        if (!p) {
    857                 NWRAP_ERROR(("%s:'%s'\n",__location__,c));
     1982                NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
    8581983                return false;
    8591984        }
     
    8631988        c = p;
    8641989
    865         NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir));
     1990        NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
    8661991
    8671992        /* shell */
    8681993        pw->pw_shell = c;
    869         NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell));
    870 
    871         NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n",
    872                      pw->pw_name, pw->pw_passwd,
    873                      pw->pw_uid, pw->pw_gid,
    874                      pw->pw_gecos, pw->pw_dir, pw->pw_shell));
     1994        NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
     1995
     1996        NWRAP_LOG(NWRAP_LOG_DEBUG,
     1997                  "Added user[%s:%s:%u:%u:%s:%s:%s]",
     1998                  pw->pw_name, pw->pw_passwd,
     1999                  pw->pw_uid, pw->pw_gid,
     2000                  pw->pw_gecos, pw->pw_dir, pw->pw_shell);
    8752001
    8762002        nwrap_pw->num++;
     
    8832009        nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
    8842010
    885         if (nwrap_pw->list) free(nwrap_pw->list);
    886 
    887         nwrap_pw->list = NULL;
     2011        SAFE_FREE(nwrap_pw->list);
    8882012        nwrap_pw->num = 0;
    8892013        nwrap_pw->idx = 0;
     
    9042028        ofs = PTR_DIFF(last + 1, first);
    9052029
    906         if (ofs > buflen) {
     2030        if (ofs > (off_t) buflen) {
    9072031                return ERANGE;
    9082032        }
     
    9302054}
    9312055
     2056#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     2057static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
     2058{
     2059        struct nwrap_sp *nwrap_sp;
     2060        struct spwd *sp;
     2061        size_t list_size;
     2062        char *c;
     2063        char *e;
     2064        char *p;
     2065
     2066        nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
     2067
     2068        list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
     2069        sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
     2070        if (sp == NULL) {
     2071                NWRAP_LOG(NWRAP_LOG_ERROR,
     2072                          "realloc(%u) failed",
     2073                          (unsigned)list_size);
     2074                return false;
     2075        }
     2076        nwrap_sp->list = sp;
     2077
     2078        sp = &nwrap_sp->list[nwrap_sp->num];
     2079
     2080        c = line;
     2081
     2082        /* name */
     2083        p = strchr(c, ':');
     2084        if (p == NULL) {
     2085                NWRAP_LOG(NWRAP_LOG_ERROR,
     2086                          "name -- Invalid line[%s]: '%s'",
     2087                          line,
     2088                          c);
     2089                return false;
     2090        }
     2091        *p = '\0';
     2092        p++;
     2093        sp->sp_namp = c;
     2094        c = p;
     2095
     2096        NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
     2097
     2098        /* pwd */
     2099        p = strchr(c, ':');
     2100        if (p == NULL) {
     2101                NWRAP_LOG(NWRAP_LOG_ERROR,
     2102                          "pwd -- Invalid line[%s]: '%s'",
     2103                          line,
     2104                          c);
     2105                return false;
     2106        }
     2107        *p = '\0';
     2108        p++;
     2109        sp->sp_pwdp = c;
     2110        c = p;
     2111
     2112        /* lstchg (long) */
     2113        if (c[0] == ':') {
     2114                sp->sp_lstchg = -1;
     2115                p++;
     2116        } else {
     2117                p = strchr(c, ':');
     2118                if (p == NULL) {
     2119                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2120                                  "lstchg -- Invalid line[%s]: '%s'",
     2121                                  line,
     2122                                  c);
     2123                        return false;
     2124                }
     2125                *p = '\0';
     2126                p++;
     2127                sp->sp_lstchg = strtol(c, &e, 10);
     2128                if (c == e) {
     2129                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2130                                  "lstchg -- Invalid line[%s]: '%s' - %s",
     2131                                  line, c, strerror(errno));
     2132                        return false;
     2133                }
     2134                if (e == NULL) {
     2135                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2136                                  "lstchg -- Invalid line[%s]: '%s' - %s",
     2137                                  line, c, strerror(errno));
     2138                        return false;
     2139                }
     2140                if (e[0] != '\0') {
     2141                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2142                                  "lstchg -- Invalid line[%s]: '%s' - %s",
     2143                                  line, c, strerror(errno));
     2144                        return false;
     2145                }
     2146        }
     2147        c = p;
     2148
     2149        /* min (long) */
     2150        if (c[0] == ':') {
     2151                sp->sp_min = -1;
     2152                p++;
     2153        } else {
     2154                p = strchr(c, ':');
     2155                if (p == NULL) {
     2156                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2157                                  "min -- Invalid line[%s]: '%s'",
     2158                                  line,
     2159                                  c);
     2160                        return false;
     2161                }
     2162                *p = '\0';
     2163                p++;
     2164                sp->sp_min = strtol(c, &e, 10);
     2165                if (c == e) {
     2166                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2167                                  "min -- Invalid line[%s]: '%s' - %s",
     2168                                  line, c, strerror(errno));
     2169                        return false;
     2170                }
     2171                if (e == NULL) {
     2172                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2173                                  "min -- Invalid line[%s]: '%s' - %s",
     2174                                  line, c, strerror(errno));
     2175                        return false;
     2176                }
     2177                if (e[0] != '\0') {
     2178                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2179                                  "min -- Invalid line[%s]: '%s' - %s",
     2180                                  line, c, strerror(errno));
     2181                        return false;
     2182                }
     2183        }
     2184        c = p;
     2185
     2186        /* max (long) */
     2187        if (c[0] == ':') {
     2188                sp->sp_max = -1;
     2189                p++;
     2190        } else {
     2191                p = strchr(c, ':');
     2192                if (p == NULL) {
     2193                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2194                                  "max -- Invalid line[%s]: '%s'",
     2195                                  line,
     2196                                  c);
     2197                        return false;
     2198                }
     2199                *p = '\0';
     2200                p++;
     2201                sp->sp_max = strtol(c, &e, 10);
     2202                if (c == e) {
     2203                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2204                                  "max -- Invalid line[%s]: '%s' - %s",
     2205                                  line, c, strerror(errno));
     2206                        return false;
     2207                }
     2208                if (e == NULL) {
     2209                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2210                                  "max -- Invalid line[%s]: '%s' - %s",
     2211                                  line, c, strerror(errno));
     2212                        return false;
     2213                }
     2214                if (e[0] != '\0') {
     2215                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2216                                  "max -- Invalid line[%s]: '%s' - %s",
     2217                                  line, c, strerror(errno));
     2218                        return false;
     2219                }
     2220        }
     2221        c = p;
     2222
     2223        /* warn (long) */
     2224        if (c[0] == ':') {
     2225                sp->sp_warn = -1;
     2226                p++;
     2227        } else {
     2228                p = strchr(c, ':');
     2229                if (p == NULL) {
     2230                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2231                                  "warn -- Invalid line[%s]: '%s'",
     2232                                  line,
     2233                                  c);
     2234                        return false;
     2235                }
     2236                *p = '\0';
     2237                p++;
     2238                sp->sp_warn = strtol(c, &e, 10);
     2239                if (c == e) {
     2240                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2241                                  "warn -- Invalid line[%s]: '%s' - %s",
     2242                                  line, c, strerror(errno));
     2243                        return false;
     2244                }
     2245                if (e == NULL) {
     2246                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2247                                  "warn -- Invalid line[%s]: '%s' - %s",
     2248                                  line, c, strerror(errno));
     2249                        return false;
     2250                }
     2251                if (e[0] != '\0') {
     2252                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2253                                  "warn -- Invalid line[%s]: '%s' - %s",
     2254                                  line, c, strerror(errno));
     2255                        return false;
     2256                }
     2257        }
     2258        c = p;
     2259
     2260        /* inact (long) */
     2261        if (c[0] == ':') {
     2262                sp->sp_inact = -1;
     2263                p++;
     2264        } else {
     2265                p = strchr(c, ':');
     2266                if (p == NULL) {
     2267                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2268                                  "inact -- Invalid line[%s]: '%s'",
     2269                                  line,
     2270                                  c);
     2271                        return false;
     2272                }
     2273                *p = '\0';
     2274                p++;
     2275                sp->sp_inact = strtol(c, &e, 10);
     2276                if (c == e) {
     2277                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2278                                  "inact -- Invalid line[%s]: '%s' - %s",
     2279                                  line, c, strerror(errno));
     2280                        return false;
     2281                }
     2282                if (e == NULL) {
     2283                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2284                                  "inact -- Invalid line[%s]: '%s' - %s",
     2285                                  line, c, strerror(errno));
     2286                        return false;
     2287                }
     2288                if (e[0] != '\0') {
     2289                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2290                                  "inact -- Invalid line[%s]: '%s' - %s",
     2291                                  line, c, strerror(errno));
     2292                        return false;
     2293                }
     2294        }
     2295        c = p;
     2296
     2297        /* expire (long) */
     2298        if (c[0] == ':') {
     2299                sp->sp_expire = -1;
     2300                p++;
     2301        } else {
     2302                p = strchr(c, ':');
     2303                if (p == NULL) {
     2304                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2305                                  "expire -- Invalid line[%s]: '%s'",
     2306                                  line,
     2307                                  c);
     2308                        return false;
     2309                }
     2310                *p = '\0';
     2311                p++;
     2312                sp->sp_expire = strtol(c, &e, 10);
     2313                if (c == e) {
     2314                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2315                                  "expire -- Invalid line[%s]: '%s' - %s",
     2316                                  line, c, strerror(errno));
     2317                        return false;
     2318                }
     2319                if (e == NULL) {
     2320                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2321                                  "expire -- Invalid line[%s]: '%s' - %s",
     2322                                  line, c, strerror(errno));
     2323                        return false;
     2324                }
     2325                if (e[0] != '\0') {
     2326                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2327                                  "expire -- Invalid line[%s]: '%s' - %s",
     2328                                  line, c, strerror(errno));
     2329                        return false;
     2330                }
     2331        }
     2332        c = p;
     2333
     2334        nwrap_sp->num++;
     2335        return true;
     2336}
     2337
     2338static void nwrap_sp_unload(struct nwrap_cache *nwrap)
     2339{
     2340        struct nwrap_sp *nwrap_sp;
     2341        nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
     2342
     2343        SAFE_FREE(nwrap_sp->list);
     2344        nwrap_sp->num = 0;
     2345        nwrap_sp->idx = 0;
     2346}
     2347#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     2348
    9322349/*
    9332350 * the caller has to call nwrap_unload() on failure
     
    9482365        gr = (struct group *)realloc(nwrap_gr->list, list_size);
    9492366        if (!gr) {
    950                 NWRAP_ERROR(("%s:realloc failed\n",__location__));
     2367                NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
    9512368                return false;
    9522369        }
     
    9602377        p = strchr(c, ':');
    9612378        if (!p) {
    962                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    963                              __location__, line, c));
     2379                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    9642380                return false;
    9652381        }
     
    9692385        c = p;
    9702386
    971         NWRAP_VERBOSE(("name[%s]\n", gr->gr_name));
     2387        NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
    9722388
    9732389        /* password */
    9742390        p = strchr(c, ':');
    9752391        if (!p) {
    976                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    977                              __location__, line, c));
     2392                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    9782393                return false;
    9792394        }
     
    9832398        c = p;
    9842399
    985         NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd));
     2400        NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
    9862401
    9872402        /* gid */
    9882403        p = strchr(c, ':');
    9892404        if (!p) {
    990                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
    991                              __location__, line, c));
     2405                NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
    9922406                return false;
    9932407        }
     
    9972411        gr->gr_gid = (gid_t)strtoul(c, &e, 10);
    9982412        if (c == e) {
    999                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    1000                              __location__, line, c, strerror(errno)));
     2413                NWRAP_LOG(NWRAP_LOG_ERROR,
     2414                          "Invalid line[%s]: '%s' - %s",
     2415                          line, c, strerror(errno));
    10012416                return false;
    10022417        }
    10032418        if (e == NULL) {
    1004                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    1005                              __location__, line, c, strerror(errno)));
     2419                NWRAP_LOG(NWRAP_LOG_ERROR,
     2420                          "Invalid line[%s]: '%s' - %s",
     2421                          line, c, strerror(errno));
    10062422                return false;
    10072423        }
    10082424        if (e[0] != '\0') {
    1009                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
    1010                              __location__, line, c, strerror(errno)));
     2425                NWRAP_LOG(NWRAP_LOG_ERROR,
     2426                          "Invalid line[%s]: '%s' - %s",
     2427                          line, c, strerror(errno));
    10112428                return false;
    10122429        }
    10132430        c = p;
    10142431
    1015         NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid));
     2432        NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
    10162433
    10172434        /* members */
    10182435        gr->gr_mem = (char **)malloc(sizeof(char *));
    10192436        if (!gr->gr_mem) {
    1020                 NWRAP_ERROR(("%s:calloc failed\n",__location__));
     2437                NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    10212438                return false;
    10222439        }
     
    10402457                m = (char **)realloc(gr->gr_mem, m_size);
    10412458                if (!m) {
    1042                         NWRAP_ERROR(("%s:realloc(%u) failed\n",
    1043                                       __location__, m_size));
     2459                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2460                                  "realloc(%zd) failed",
     2461                                  m_size);
    10442462                        return false;
    10452463                }
     
    10482466                gr->gr_mem[nummem+1] = NULL;
    10492467
    1050                 NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem]));
    1051         }
    1052 
    1053         NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n",
    1054                      gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem));
     2468                NWRAP_LOG(NWRAP_LOG_TRACE,
     2469                          "member[%u]: '%s'",
     2470                          nummem, gr->gr_mem[nummem]);
     2471        }
     2472
     2473        NWRAP_LOG(NWRAP_LOG_DEBUG,
     2474                  "Added group[%s:%s:%u:] with %u members",
     2475                  gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
    10552476
    10562477        nwrap_gr->num++;
     
    10662487        if (nwrap_gr->list) {
    10672488                for (i=0; i < nwrap_gr->num; i++) {
    1068                         if (nwrap_gr->list[i].gr_mem) {
    1069                                 free(nwrap_gr->list[i].gr_mem);
    1070                         }
    1071                 }
    1072                 free(nwrap_gr->list);
    1073         }
    1074 
    1075         nwrap_gr->list = NULL;
     2489                        SAFE_FREE(nwrap_gr->list[i].gr_mem);
     2490                }
     2491                SAFE_FREE(nwrap_gr->list);
     2492        }
     2493
    10762494        nwrap_gr->num = 0;
    10772495        nwrap_gr->idx = 0;
     
    11052523        ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
    11062524
    1107         if ((ofsb + ofsm) > buflen) {
     2525        if ((ofsb + ofsm) > (off_t) buflen) {
    11082526                return ERANGE;
    11092527        }
     
    11312549}
    11322550
     2551static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
     2552{
     2553        struct nwrap_entlist *el;
     2554
     2555        if (ed == NULL) {
     2556                NWRAP_LOG(NWRAP_LOG_ERROR,
     2557                          "entry is NULL, can't create list item");
     2558                return NULL;
     2559        }
     2560
     2561        el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
     2562        if (el == NULL) {
     2563                NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
     2564                return NULL;
     2565        }
     2566
     2567        el->next = NULL;
     2568        el->ed = ed;
     2569
     2570        return el;
     2571}
     2572
     2573static bool nwrap_ed_inventarize_add_new(char *const h_name,
     2574                                         struct nwrap_entdata *const ed)
     2575{
     2576        ENTRY e;
     2577        ENTRY *p;
     2578        struct nwrap_entlist *el;
     2579        bool ok;
     2580
     2581        if (h_name == NULL) {
     2582                NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
     2583                return false;
     2584        }
     2585
     2586        el = nwrap_entlist_init(ed);
     2587        if (el == NULL) {
     2588                return false;
     2589        }
     2590
     2591        e.key = h_name;
     2592        e.data = (void *)el;
     2593
     2594        p = hsearch(e, ENTER);
     2595        if (p == NULL) {
     2596                NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full!");
     2597                return false;
     2598        }
     2599
     2600        ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
     2601        if (!ok) {
     2602                NWRAP_LOG(NWRAP_LOG_ERROR,
     2603                          "Failed to add list entry to vector.");
     2604                return false;
     2605        }
     2606
     2607        return true;
     2608}
     2609
     2610static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
     2611                                                 struct nwrap_entlist *const el)
     2612{
     2613        struct nwrap_entlist *cursor;
     2614        struct nwrap_entlist *el_new;
     2615
     2616        if (el == NULL) {
     2617                NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
     2618                return false;
     2619        }
     2620
     2621
     2622        for (cursor = el; cursor->next != NULL; cursor = cursor->next)
     2623        {
     2624                if (cursor->ed == ed) {
     2625                        /* The entry already exists in this list. */
     2626                        return true;
     2627                }
     2628        }
     2629
     2630        if (cursor->ed == ed) {
     2631                /* The entry already exists in this list. */
     2632                return true;
     2633        }
     2634
     2635        el_new = nwrap_entlist_init(ed);
     2636        if (el_new == NULL) {
     2637                return false;
     2638        }
     2639
     2640        cursor->next = el_new;
     2641        return true;
     2642}
     2643
     2644static bool nwrap_ed_inventarize(char *const name,
     2645                                 struct nwrap_entdata *const ed)
     2646{
     2647        ENTRY e;
     2648        ENTRY *p;
     2649        bool ok;
     2650
     2651        e.key = name;
     2652        e.data = NULL;
     2653
     2654        NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
     2655
     2656        p = hsearch(e, FIND);
     2657        if (p == NULL) {
     2658                NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
     2659                ok = nwrap_ed_inventarize_add_new(name, ed);
     2660        } else {
     2661                struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
     2662
     2663                NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
     2664                ok = nwrap_ed_inventarize_add_to_existing(ed, el);
     2665        }
     2666
     2667        return ok;
     2668}
     2669
     2670static bool nwrap_add_hname(struct nwrap_entdata *const ed)
     2671{
     2672        char *const h_name = (char *const)(ed->ht.h_name);
     2673        unsigned i;
     2674        bool ok;
     2675
     2676        ok = nwrap_ed_inventarize(h_name, ed);
     2677        if (!ok) {
     2678                return false;
     2679        }
     2680
     2681        if (ed->ht.h_aliases == NULL) {
     2682                return true;
     2683        }
     2684
     2685        /* Itemize aliases */
     2686        for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
     2687                char *h_name_alias;
     2688
     2689                h_name_alias = ed->ht.h_aliases[i];
     2690
     2691                NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
     2692
     2693                if (!nwrap_ed_inventarize(h_name_alias, ed)) {
     2694                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2695                                  "Unable to add alias: %s", h_name_alias);
     2696                        return false;
     2697                }
     2698        }
     2699
     2700        return true;
     2701}
     2702
     2703static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
     2704{
     2705        struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
     2706        bool do_aliases = true;
     2707        ssize_t aliases_count = 0;
     2708        char *p;
     2709        char *i;
     2710        char *n;
     2711
     2712        char *ip;
     2713        bool ok;
     2714
     2715        struct nwrap_entdata *ed = (struct nwrap_entdata *)
     2716                                   malloc(sizeof(struct nwrap_entdata));
     2717        if (ed == NULL) {
     2718                NWRAP_LOG(NWRAP_LOG_ERROR,
     2719                          "Unable to allocate memory for nwrap_entdata");
     2720                return false;
     2721        }
     2722        ZERO_STRUCTP(ed);
     2723
     2724        i = line;
     2725
     2726        /*
     2727         * IP
     2728         */
     2729
     2730        /* Walk to first char */
     2731        for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
     2732                if (*p == '\0') {
     2733                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2734                                  "Invalid line[%s]: '%s'",
     2735                                  line, i);
     2736                        free(ed);
     2737                        return false;
     2738                }
     2739        }
     2740
     2741        for (i = p; !isspace((int)*p); p++) {
     2742                if (*p == '\0') {
     2743                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2744                                  "Invalid line[%s]: '%s'",
     2745                                  line, i);
     2746                        free(ed);
     2747                        return false;
     2748                }
     2749        }
     2750
     2751        *p = '\0';
     2752
     2753        if (inet_pton(AF_INET, i, ed->addr.host_addr)) {
     2754                ed->ht.h_addrtype = AF_INET;
     2755                ed->ht.h_length = 4;
     2756#ifdef HAVE_IPV6
     2757        } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
     2758                ed->ht.h_addrtype = AF_INET6;
     2759                ed->ht.h_length = 16;
     2760#endif
     2761        } else {
     2762                NWRAP_LOG(NWRAP_LOG_ERROR,
     2763                          "Invalid line[%s]: '%s'",
     2764                          line, i);
     2765
     2766                free(ed);
     2767                return false;
     2768        }
     2769        ip = i;
     2770
     2771        ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
     2772                                   (void *const)ed->addr.host_addr);
     2773        if (!ok) {
     2774                NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
     2775                free(ed);
     2776                return false;
     2777        }
     2778        ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
     2779
     2780        p++;
     2781
     2782        /*
     2783         * FQDN
     2784         */
     2785
     2786        /* Walk to first char */
     2787        for (n = p; *p != '_' && !isalnum((int) *p); p++) {
     2788                if (*p == '\0') {
     2789                        NWRAP_LOG(NWRAP_LOG_ERROR,
     2790                                  "Invalid line[%s]: '%s'",
     2791                                  line, n);
     2792
     2793                        free(ed);
     2794                        return false;
     2795                }
     2796        }
     2797
     2798        for (n = p; !isspace((int)*p); p++) {
     2799                if (*p == '\0') {
     2800                        do_aliases = false;
     2801                        break;
     2802                }
     2803        }
     2804
     2805        *p = '\0';
     2806
     2807        /* Convert to lowercase. This operate on same memory region */
     2808        str_tolower(n, n);
     2809        ed->ht.h_name = n;
     2810
     2811        /* glib's getent always dereferences he->h_aliases */
     2812        ed->ht.h_aliases = malloc(sizeof(char *));
     2813        if (ed->ht.h_aliases == NULL) {
     2814                free(ed);
     2815                return false;
     2816        }
     2817        ed->ht.h_aliases[0] = NULL;
     2818
     2819        /*
     2820         * Aliases
     2821         */
     2822        while (do_aliases) {
     2823                char **aliases;
     2824                char *a;
     2825
     2826                p++;
     2827
     2828                /* Walk to first char */
     2829                for (a = p; *p != '_' && !isalnum((int) *p); p++) {
     2830                        if (*p == '\0') {
     2831                                do_aliases = false;
     2832                                break;
     2833                        }
     2834                }
     2835                /* Only trailing spaces are left */
     2836                if (!do_aliases) {
     2837                        break;
     2838                }
     2839
     2840                for (a = p; !isspace((int)*p); p++) {
     2841                        if (*p == '\0') {
     2842                                do_aliases = false;
     2843                                break;
     2844                        }
     2845                }
     2846
     2847                *p = '\0';
     2848
     2849                aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
     2850                if (aliases == NULL) {
     2851                        free(ed);
     2852                        return false;
     2853                }
     2854                ed->ht.h_aliases = aliases;
     2855
     2856                str_tolower(a, a);
     2857                aliases[aliases_count] = a;
     2858                aliases[aliases_count + 1] = NULL;
     2859
     2860                aliases_count += 1;
     2861        }
     2862
     2863        ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
     2864        if (!ok) {
     2865                NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
     2866                free(ed);
     2867                return false;
     2868        }
     2869
     2870        ed->aliases_count = aliases_count;
     2871        /* Inventarize item */
     2872        ok = nwrap_add_hname(ed);
     2873        if (!ok) {
     2874                return false;
     2875        }
     2876
     2877        ok = nwrap_ed_inventarize(ip, ed);
     2878        if (!ok) {
     2879                return false;
     2880        }
     2881
     2882        nwrap_he->num++;
     2883        return true;
     2884}
     2885
     2886static void nwrap_he_unload(struct nwrap_cache *nwrap)
     2887{
     2888        struct nwrap_he *nwrap_he =
     2889                (struct nwrap_he *)nwrap->private_data;
     2890        struct nwrap_entdata *ed;
     2891        struct nwrap_entlist *el;
     2892        size_t i;
     2893        int rc;
     2894
     2895        nwrap_vector_foreach (ed, nwrap_he->entries, i)
     2896        {
     2897                SAFE_FREE(ed->nwrap_addrdata.items);
     2898                SAFE_FREE(ed->ht.h_aliases);
     2899                SAFE_FREE(ed);
     2900        }
     2901        SAFE_FREE(nwrap_he->entries.items);
     2902        nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
     2903
     2904        nwrap_vector_foreach(el, nwrap_he->lists, i)
     2905        {
     2906                while (el != NULL) {
     2907                        struct nwrap_entlist *el_next;
     2908
     2909                        el_next = el->next;
     2910                        SAFE_FREE(el);
     2911                        el = el_next;
     2912                }
     2913        }
     2914        SAFE_FREE(nwrap_he->lists.items);
     2915        nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
     2916
     2917        nwrap_he->num = 0;
     2918        nwrap_he->idx = 0;
     2919
     2920        /*
     2921         * If we unload the file, the pointers in the hash table point to
     2922         * invalid memory. So we need to destroy the hash table and recreate
     2923         * it.
     2924         */
     2925        hdestroy();
     2926        rc = hcreate(max_hostents);
     2927        if (rc == 0) {
     2928                NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
     2929                exit(-1);
     2930        }
     2931}
     2932
     2933
    11332934/* user functions */
    11342935static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
     
    11362937{
    11372938        int i;
    1138 
    1139         nwrap_files_cache_reload(nwrap_pw_global.cache);
     2939        bool ok;
     2940
     2941        (void) b; /* unused */
     2942
     2943        NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
     2944
     2945        ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
     2946        if (!ok) {
     2947                NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
     2948                return NULL;
     2949        }
    11402950
    11412951        for (i=0; i<nwrap_pw_global.num; i++) {
    11422952                if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
    1143                         NWRAP_DEBUG(("%s: user[%s] found\n",
    1144                                      __location__, name));
     2953                        NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
    11452954                        return &nwrap_pw_global.list[i];
    11462955                }
    1147                 NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n",
    1148                                __location__, name,
    1149                                nwrap_pw_global.list[i].pw_name));
    1150         }
    1151 
    1152         NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name));
     2956                NWRAP_LOG(NWRAP_LOG_DEBUG,
     2957                          "user[%s] does not match [%s]",
     2958                          name,
     2959                          nwrap_pw_global.list[i].pw_name);
     2960        }
     2961
     2962        NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
    11532963
    11542964        errno = ENOENT;
     
    11772987{
    11782988        int i;
    1179 
    1180         nwrap_files_cache_reload(nwrap_pw_global.cache);
     2989        bool ok;
     2990
     2991        (void) b; /* unused */
     2992
     2993        ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
     2994        if (!ok) {
     2995                NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
     2996                return NULL;
     2997        }
    11812998
    11822999        for (i=0; i<nwrap_pw_global.num; i++) {
    11833000                if (nwrap_pw_global.list[i].pw_uid == uid) {
    1184                         NWRAP_DEBUG(("%s: uid[%u] found\n",
    1185                                      __location__, uid));
     3001                        NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
    11863002                        return &nwrap_pw_global.list[i];
    11873003                }
    1188                 NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n",
    1189                                __location__, uid,
    1190                                nwrap_pw_global.list[i].pw_uid));
    1191         }
    1192 
    1193         NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid));
     3004                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3005                          "uid[%u] does not match [%u]",
     3006                          uid,
     3007                          nwrap_pw_global.list[i].pw_uid);
     3008        }
     3009
     3010        NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
    11943011
    11953012        errno = ENOENT;
     
    12173034static void nwrap_files_setpwent(struct nwrap_backend *b)
    12183035{
     3036        (void) b; /* unused */
     3037
    12193038        nwrap_pw_global.idx = 0;
    12203039}
     
    12243043        struct passwd *pw;
    12253044
     3045        (void) b; /* unused */
     3046
    12263047        if (nwrap_pw_global.idx == 0) {
    1227                 nwrap_files_cache_reload(nwrap_pw_global.cache);
     3048                bool ok;
     3049                ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
     3050                if (!ok) {
     3051                        NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
     3052                        return NULL;
     3053                }
    12283054        }
    12293055
     
    12353061        pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
    12363062
    1237         NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n",
    1238                        __location__, pw->pw_name, pw->pw_uid));
     3063        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3064                  "return user[%s] uid[%u]",
     3065                  pw->pw_name, pw->pw_uid);
    12393066
    12403067        return pw;
     
    12603087static void nwrap_files_endpwent(struct nwrap_backend *b)
    12613088{
     3089        (void) b; /* unused */
     3090
    12623091        nwrap_pw_global.idx = 0;
    12633092}
     3093
     3094/* shadow */
     3095
     3096#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     3097
     3098#ifdef HAVE_SETSPENT
     3099static void nwrap_files_setspent(void)
     3100{
     3101        nwrap_sp_global.idx = 0;
     3102}
     3103
     3104static struct spwd *nwrap_files_getspent(void)
     3105{
     3106        struct spwd *sp;
     3107
     3108        if (nwrap_sp_global.idx == 0) {
     3109                bool ok;
     3110
     3111                ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
     3112                if (!ok) {
     3113                        NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
     3114                        return NULL;
     3115                }
     3116        }
     3117
     3118        if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
     3119                errno = ENOENT;
     3120                return NULL;
     3121        }
     3122
     3123        sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
     3124
     3125        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3126                  "return user[%s]",
     3127                  sp->sp_namp);
     3128
     3129        return sp;
     3130}
     3131
     3132static void nwrap_files_endspent(void)
     3133{
     3134        nwrap_sp_global.idx = 0;
     3135}
     3136#endif /* HAVE_SETSPENT */
     3137
     3138static struct spwd *nwrap_files_getspnam(const char *name)
     3139{
     3140        int i;
     3141        bool ok;
     3142
     3143        NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
     3144
     3145        ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
     3146        if (!ok) {
     3147                NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
     3148                return NULL;
     3149        }
     3150
     3151        for (i=0; i<nwrap_sp_global.num; i++) {
     3152                if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
     3153                        NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
     3154                        return &nwrap_sp_global.list[i];
     3155                }
     3156                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3157                          "user[%s] does not match [%s]",
     3158                          name,
     3159                          nwrap_sp_global.list[i].sp_namp);
     3160        }
     3161
     3162        NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
     3163
     3164        errno = ENOENT;
     3165        return NULL;
     3166}
     3167#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
    12643168
    12653169/* misc functions */
    12663170static int nwrap_files_initgroups(struct nwrap_backend *b,
    1267                                   const char *user, gid_t group)
    1268 {
    1269         /* TODO: maybe we should also fake this... */
    1270         return EPERM;
     3171                                  const char *user,
     3172                                  gid_t group)
     3173{
     3174        struct group *grp;
     3175        gid_t *groups;
     3176        int size = 1;
     3177        int rc;
     3178
     3179        groups = (gid_t *)malloc(size * sizeof(gid_t));
     3180        if (groups == NULL) {
     3181                NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
     3182                errno = ENOMEM;
     3183                return -1;
     3184        }
     3185        groups[0] = group;
     3186
     3187        nwrap_files_setgrent(b);
     3188        while ((grp = nwrap_files_getgrent(b)) != NULL) {
     3189                int i = 0;
     3190
     3191                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3192                          "Inspecting %s for group membership",
     3193                          grp->gr_name);
     3194
     3195                for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
     3196                        if (group != grp->gr_gid &&
     3197                            (strcmp(user, grp->gr_mem[i]) == 0)) {
     3198                                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3199                                          "%s is member of %s",
     3200                                          user,
     3201                                          grp->gr_name);
     3202
     3203                                groups = (gid_t *)realloc(groups,
     3204                                                          (size + 1) * sizeof(gid_t));
     3205                                if (groups == NULL) {
     3206                                        NWRAP_LOG(NWRAP_LOG_ERROR,
     3207                                                  "Out of memory");
     3208                                        errno = ENOMEM;
     3209                                        return -1;
     3210                                }
     3211
     3212                                groups[size] = grp->gr_gid;
     3213                                size++;
     3214                        }
     3215                }
     3216        }
     3217
     3218        nwrap_files_endgrent(b);
     3219
     3220        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3221                  "%s is member of %d groups",
     3222                  user, size);
     3223
     3224        /* This really only works if uid_wrapper is loaded */
     3225        rc = setgroups(size, groups);
     3226
     3227        free(groups);
     3228
     3229        return rc;
    12713230}
    12723231
     
    12763235{
    12773236        int i;
    1278 
    1279         nwrap_files_cache_reload(nwrap_gr_global.cache);
     3237        bool ok;
     3238
     3239        (void) b; /* unused */
     3240
     3241        ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
     3242        if (!ok) {
     3243                NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
     3244                return NULL;
     3245        }
    12803246
    12813247        for (i=0; i<nwrap_gr_global.num; i++) {
    12823248                if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
    1283                         NWRAP_DEBUG(("%s: group[%s] found\n",
    1284                                      __location__, name));
     3249                        NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
    12853250                        return &nwrap_gr_global.list[i];
    12863251                }
    1287                 NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n",
    1288                                __location__, name,
    1289                                nwrap_gr_global.list[i].gr_name));
    1290         }
    1291 
    1292         NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name));
     3252                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3253                          "group[%s] does not match [%s]",
     3254                          name,
     3255                          nwrap_gr_global.list[i].gr_name);
     3256        }
     3257
     3258        NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
    12933259
    12943260        errno = ENOENT;
     
    13173283{
    13183284        int i;
    1319 
    1320         nwrap_files_cache_reload(nwrap_gr_global.cache);
     3285        bool ok;
     3286
     3287        (void) b; /* unused */
     3288
     3289        ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
     3290        if (!ok) {
     3291                NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
     3292                return NULL;
     3293        }
    13213294
    13223295        for (i=0; i<nwrap_gr_global.num; i++) {
    13233296                if (nwrap_gr_global.list[i].gr_gid == gid) {
    1324                         NWRAP_DEBUG(("%s: gid[%u] found\n",
    1325                                      __location__, gid));
     3297                        NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
    13263298                        return &nwrap_gr_global.list[i];
    13273299                }
    1328                 NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n",
    1329                                __location__, gid,
    1330                                nwrap_gr_global.list[i].gr_gid));
    1331         }
    1332 
    1333         NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid));
     3300                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3301                          "gid[%u] does not match [%u]",
     3302                          gid,
     3303                          nwrap_gr_global.list[i].gr_gid);
     3304        }
     3305
     3306        NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
    13343307
    13353308        errno = ENOENT;
     
    13573330static void nwrap_files_setgrent(struct nwrap_backend *b)
    13583331{
     3332        (void) b; /* unused */
     3333
    13593334        nwrap_gr_global.idx = 0;
    13603335}
     
    13643339        struct group *gr;
    13653340
     3341        (void) b; /* unused */
     3342
    13663343        if (nwrap_gr_global.idx == 0) {
    1367                 nwrap_files_cache_reload(nwrap_gr_global.cache);
     3344                bool ok;
     3345
     3346                ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
     3347                if (!ok) {
     3348                        NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
     3349                        return NULL;
     3350                }
    13683351        }
    13693352
     
    13753358        gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
    13763359
    1377         NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n",
    1378                        __location__, gr->gr_name, gr->gr_gid));
     3360        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3361                  "return group[%s] gid[%u]",
     3362                  gr->gr_name, gr->gr_gid);
    13793363
    13803364        return gr;
     
    14003384static void nwrap_files_endgrent(struct nwrap_backend *b)
    14013385{
     3386        (void) b; /* unused */
     3387
    14023388        nwrap_gr_global.idx = 0;
     3389}
     3390
     3391/* hosts functions */
     3392static int nwrap_files_gethostbyname(const char *name, int af,
     3393                                     struct hostent *result,
     3394                                     struct nwrap_vector *addr_list)
     3395{
     3396        struct nwrap_entlist *el;
     3397        struct hostent *he;
     3398        char *h_name_lower;
     3399        ENTRY e;
     3400        ENTRY *e_p;
     3401        char canon_name[DNS_NAME_MAX] = { 0 };
     3402        size_t name_len;
     3403        bool he_found = false;
     3404        bool ok;
     3405
     3406        ok = nwrap_files_cache_reload(nwrap_he_global.cache);
     3407        if (!ok) {
     3408                NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
     3409                goto no_ent;
     3410        }
     3411
     3412        name_len = strlen(name);
     3413        if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
     3414                strncpy(canon_name, name, name_len - 1);
     3415                name = canon_name;
     3416        }
     3417
     3418        if (!str_tolower_copy(&h_name_lower, name)) {
     3419                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3420                          "Out of memory while converting to lower case");
     3421                goto no_ent;
     3422        }
     3423
     3424        /* Look at hash table for element */
     3425        NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
     3426        e.key = h_name_lower;
     3427        e.data = NULL;
     3428        e_p = hsearch(e, FIND);
     3429        if (e_p == NULL) {
     3430                NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
     3431                SAFE_FREE(h_name_lower);
     3432                goto no_ent;
     3433        }
     3434        SAFE_FREE(h_name_lower);
     3435
     3436        /* Always cleanup vector and results */
     3437        if (!nwrap_vector_is_initialized(addr_list)) {
     3438                if (!nwrap_vector_init(addr_list)) {
     3439                        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3440                                  "Unable to initialize memory for addr_list vector");
     3441                        goto no_ent;
     3442                }
     3443        } else {
     3444                /* When vector is initialized data are valid no more.
     3445                 * Quick way how to free vector is: */
     3446                addr_list->count = 0;
     3447        }
     3448
     3449        /* Iterate through results */
     3450        for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
     3451        {
     3452                he = &(el->ed->ht);
     3453
     3454                /* Filter by address familiy if provided */
     3455                if (af != AF_UNSPEC && he->h_addrtype != af) {
     3456                        continue;
     3457                }
     3458
     3459                /*
     3460                 * GLIBC HACK?
     3461                 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
     3462                 */
     3463                if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
     3464                        continue;
     3465                }
     3466
     3467                if (!he_found) {
     3468                        memcpy(result, he, sizeof(struct hostent));
     3469                        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3470                                  "Name found. Returning record for %s",
     3471                                  he->h_name);
     3472                        he_found = true;
     3473                }
     3474                nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
     3475                result->h_addr_list = nwrap_vector_head(addr_list);
     3476        }
     3477
     3478        if (he_found) {
     3479                return 0;
     3480        }
     3481        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3482                  "Name found in database. No records matches type.");
     3483
     3484no_ent:
     3485        errno = ENOENT;
     3486        return -1;
     3487}
     3488
     3489#ifdef HAVE_GETHOSTBYNAME_R
     3490static int nwrap_gethostbyname_r(const char *name,
     3491                                 struct hostent *ret,
     3492                                 char *buf, size_t buflen,
     3493                                 struct hostent **result, int *h_errnop)
     3494{
     3495        struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector));
     3496        int rc;
     3497
     3498        if (addr_list == NULL) {
     3499                NWRAP_LOG(NWRAP_LOG_ERROR,
     3500                          "Unable to allocate memory for address list");
     3501                errno = ENOENT;
     3502                return -1;
     3503        }
     3504
     3505        ZERO_STRUCTP(addr_list);
     3506
     3507        rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list);
     3508        if (rc == -1) {
     3509                *h_errnop = h_errno;
     3510                if (addr_list->items != NULL) {
     3511                        free(addr_list->items);
     3512                }
     3513                SAFE_FREE(addr_list);
     3514                errno = ENOENT;
     3515                return -1;
     3516        }
     3517
     3518        if (buflen < (addr_list->count * sizeof(void *))) {
     3519                SAFE_FREE(addr_list->items);
     3520                SAFE_FREE(addr_list);
     3521                return ERANGE;
     3522        }
     3523
     3524        /* Copy all to user provided buffer and change
     3525         * pointers in returned structure.
     3526         * +1 is for ending NULL pointer. */
     3527        memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
     3528
     3529        free(addr_list->items);
     3530        free(addr_list);
     3531
     3532        ret->h_addr_list = (char **)buf;
     3533        *result = ret;
     3534        return 0;
     3535}
     3536
     3537int gethostbyname_r(const char *name,
     3538                    struct hostent *ret,
     3539                    char *buf, size_t buflen,
     3540                    struct hostent **result, int *h_errnop)
     3541{
     3542        if (!nss_wrapper_hosts_enabled()) {
     3543                return libc_gethostbyname_r(name,
     3544                                            ret,
     3545                                            buf,
     3546                                            buflen,
     3547                                            result,
     3548                                            h_errnop);
     3549        }
     3550
     3551        return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
     3552}
     3553#endif
     3554
     3555static int nwrap_files_getaddrinfo(const char *name,
     3556                                   unsigned short port,
     3557                                   const struct addrinfo *hints,
     3558                                   struct addrinfo **ai)
     3559{
     3560        struct nwrap_entlist *el;
     3561        struct hostent *he;
     3562        struct addrinfo *ai_head = NULL;
     3563        struct addrinfo *ai_cur = NULL;
     3564        char *h_name_lower;
     3565        size_t name_len;
     3566        char canon_name[DNS_NAME_MAX] = { 0 };
     3567        bool skip_canonname = false;
     3568        ENTRY e = {
     3569                .key = NULL,
     3570        };
     3571        ENTRY *e_p = NULL;
     3572        int rc;
     3573        bool ok;
     3574
     3575        ok = nwrap_files_cache_reload(nwrap_he_global.cache);
     3576        if (!ok) {
     3577                NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
     3578                return EAI_SYSTEM;
     3579        }
     3580
     3581        name_len = strlen(name);
     3582        if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
     3583                strncpy(canon_name, name, name_len - 1);
     3584                name = canon_name;
     3585        }
     3586
     3587        if (!str_tolower_copy(&h_name_lower, name)) {
     3588                NWRAP_LOG(NWRAP_LOG_DEBUG,
     3589                          "Out of memory while converting to lower case");
     3590                return EAI_MEMORY;
     3591        }
     3592
     3593        NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
     3594        e.key = h_name_lower;
     3595        e.data = NULL;
     3596        e_p = hsearch(e, FIND);
     3597        if (e_p == NULL) {
     3598                NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
     3599                SAFE_FREE(h_name_lower);
     3600                errno = ENOENT;
     3601                return EAI_NONAME;
     3602        }
     3603        NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
     3604        SAFE_FREE(h_name_lower);
     3605
     3606        rc = EAI_NONAME;
     3607        for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
     3608        {
     3609                int rc2;
     3610                struct addrinfo *ai_new = NULL;
     3611
     3612                he = &(el->ed->ht);
     3613
     3614                if (hints->ai_family != AF_UNSPEC &&
     3615                    he->h_addrtype != hints->ai_family)
     3616                {
     3617                        NWRAP_LOG(NWRAP_LOG_DEBUG,
     3618                                  "Entry found but with wrong AF - "
     3619                                  "remembering EAI_ADDRINFO.");
     3620                        rc = EAI_ADDRFAMILY;
     3621                        continue;
     3622                }
     3623
     3624                /* Function allocates memory and returns it in ai. */
     3625                rc2 = nwrap_convert_he_ai(he,
     3626                                         port,
     3627                                         hints,
     3628                                         &ai_new,
     3629                                         skip_canonname);
     3630                if (rc2 != 0) {
     3631                        NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
     3632                        if (ai_head != NULL) {
     3633                                freeaddrinfo(ai_head);
     3634                        }
     3635                        return rc2;
     3636                }
     3637                skip_canonname = true;
     3638
     3639                if (ai_head == NULL) {
     3640                        ai_head = ai_new;
     3641                }
     3642                if (ai_cur != NULL) {
     3643                        ai_cur->ai_next = ai_new;
     3644                }
     3645                ai_cur = ai_new;
     3646        }
     3647
     3648        if (ai_head != NULL) {
     3649                rc = 0;
     3650        }
     3651
     3652        *ai = ai_head;
     3653
     3654        return rc;
     3655}
     3656
     3657static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
     3658                                                 socklen_t len, int type)
     3659{
     3660        struct hostent *he;
     3661        char ip[NWRAP_INET_ADDRSTRLEN] = {0};
     3662        struct nwrap_entdata *ed;
     3663        const char *a;
     3664        size_t i;
     3665        bool ok;
     3666
     3667        (void) len; /* unused */
     3668
     3669        ok = nwrap_files_cache_reload(nwrap_he_global.cache);
     3670        if (!ok) {
     3671                NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
     3672                return NULL;
     3673        }
     3674
     3675        a = inet_ntop(type, addr, ip, sizeof(ip));
     3676        if (a == NULL) {
     3677                errno = EINVAL;
     3678                return NULL;
     3679        }
     3680
     3681        nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
     3682        {
     3683                he = &(ed->ht);
     3684                if (he->h_addrtype != type) {
     3685                        continue;
     3686                }
     3687
     3688                if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
     3689                        return he;
     3690                }
     3691        }
     3692
     3693        errno = ENOENT;
     3694        return NULL;
     3695}
     3696
     3697#ifdef HAVE_GETHOSTBYADDR_R
     3698static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
     3699                                 struct hostent *ret,
     3700                                 char *buf, size_t buflen,
     3701                                 struct hostent **result, int *h_errnop)
     3702{
     3703        *result = nwrap_files_gethostbyaddr(addr, len, type);
     3704        if (*result != NULL) {
     3705                memset(buf, '\0', buflen);
     3706                *ret = **result;
     3707                return 0;
     3708        } else {
     3709                *h_errnop = h_errno;
     3710                return -1;
     3711        }
     3712}
     3713
     3714int gethostbyaddr_r(const void *addr, socklen_t len, int type,
     3715                    struct hostent *ret,
     3716                    char *buf, size_t buflen,
     3717                    struct hostent **result, int *h_errnop)
     3718{
     3719        if (!nss_wrapper_hosts_enabled()) {
     3720                return libc_gethostbyaddr_r(addr,
     3721                                            len,
     3722                                            type,
     3723                                            ret,
     3724                                            buf,
     3725                                            buflen,
     3726                                            result,
     3727                                            h_errnop);
     3728        }
     3729
     3730        return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
     3731}
     3732#endif
     3733
     3734/* hosts enum functions */
     3735static void nwrap_files_sethostent(void)
     3736{
     3737        nwrap_he_global.idx = 0;
     3738}
     3739
     3740static struct hostent *nwrap_files_gethostent(void)
     3741{
     3742        struct hostent *he;
     3743
     3744        if (nwrap_he_global.idx == 0) {
     3745                bool ok;
     3746
     3747                ok = nwrap_files_cache_reload(nwrap_he_global.cache);
     3748                if (!ok) {
     3749                        NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
     3750                        return NULL;
     3751                }
     3752        }
     3753
     3754        if (nwrap_he_global.idx >= nwrap_he_global.num) {
     3755                errno = ENOENT;
     3756                return NULL;
     3757        }
     3758
     3759        he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
     3760
     3761        NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
     3762
     3763        return he;
     3764}
     3765
     3766static void nwrap_files_endhostent(void)
     3767{
     3768        nwrap_he_global.idx = 0;
    14033769}
    14043770
     
    14073773 */
    14083774
    1409 #ifndef SAFE_FREE
    1410 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
    1411 #endif
    14123775
    14133776static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
     
    14293792                return NULL;
    14303793        }
     3794
    14313795        return &pwd;
    14323796}
     
    14373801{
    14383802        int ret;
     3803
     3804        (void) b; /* unused */
     3805        (void) pwdst; /* unused */
     3806        (void) pwdstp; /* unused */
    14393807
    14403808        if (!b->fns->_nss_getpwnam_r) {
     
    14913859        int ret;
    14923860
     3861        (void) pwdstp; /* unused */
     3862
    14933863        if (!b->fns->_nss_getpwuid_r) {
    14943864                return ENOENT;
     
    15523922        int ret;
    15533923
     3924        (void) pwdstp; /* unused */
     3925
    15543926        if (!b->fns->_nss_getpwent_r) {
    15553927                return ENOENT;
     
    16434015        int ret;
    16444016
     4017        (void) grdstp; /* unused */
     4018
    16454019        if (!b->fns->_nss_getgrnam_r) {
    16464020                return ENOENT;
     
    17124086        int ret;
    17134087
     4088        (void) grdstp; /* unused */
     4089
    17144090        if (!b->fns->_nss_getgrgid_r) {
    17154091                return ENOENT;
     
    17894165        int ret;
    17904166
     4167        (void) grdstp; /* unused */
     4168
    17914169        if (!b->fns->_nss_getgrent_r) {
    17924170                return ENOENT;
     
    18244202}
    18254203
    1826 /*
    1827  * PUBLIC interface
    1828  */
    1829 
    1830 _PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
     4204/****************************************************************************
     4205 *   GETPWNAM
     4206 ***************************************************************************/
     4207
     4208static struct passwd *nwrap_getpwnam(const char *name)
    18314209{
    18324210        int i;
    18334211        struct passwd *pwd;
    1834 
    1835         if (!nwrap_enabled()) {
    1836                 return real_getpwnam(name);
    1837         }
    18384212
    18394213        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    18484222}
    18494223
    1850 _PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
    1851                               char *buf, size_t buflen, struct passwd **pwdstp)
     4224struct passwd *getpwnam(const char *name)
     4225{
     4226        if (!nss_wrapper_enabled()) {
     4227                return libc_getpwnam(name);
     4228        }
     4229
     4230        return nwrap_getpwnam(name);
     4231}
     4232
     4233/****************************************************************************
     4234 *   GETPWNAM_R
     4235 ***************************************************************************/
     4236
     4237static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
     4238                            char *buf, size_t buflen, struct passwd **pwdstp)
    18524239{
    18534240        int i,ret;
    1854 
    1855         if (!nwrap_enabled()) {
    1856                 return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
    1857         }
    18584241
    18594242        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    18694252}
    18704253
    1871 _PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
     4254#ifdef HAVE_GETPWNAM_R
     4255# ifdef HAVE_SOLARIS_GETPWNAM_R
     4256int getpwnam_r(const char *name, struct passwd *pwdst,
     4257               char *buf, int buflen, struct passwd **pwdstp)
     4258# else /* HAVE_SOLARIS_GETPWNAM_R */
     4259int getpwnam_r(const char *name, struct passwd *pwdst,
     4260               char *buf, size_t buflen, struct passwd **pwdstp)
     4261# endif /* HAVE_SOLARIS_GETPWNAM_R */
     4262{
     4263        if (!nss_wrapper_enabled()) {
     4264                return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
     4265        }
     4266
     4267        return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
     4268}
     4269#endif
     4270
     4271/****************************************************************************
     4272 *   GETPWUID
     4273 ***************************************************************************/
     4274
     4275static struct passwd *nwrap_getpwuid(uid_t uid)
    18724276{
    18734277        int i;
    18744278        struct passwd *pwd;
    1875 
    1876         if (!nwrap_enabled()) {
    1877                 return real_getpwuid(uid);
    1878         }
    18794279
    18804280        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    18894289}
    18904290
    1891 _PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
    1892                               char *buf, size_t buflen, struct passwd **pwdstp)
     4291struct passwd *getpwuid(uid_t uid)
     4292{
     4293        if (!nss_wrapper_enabled()) {
     4294                return libc_getpwuid(uid);
     4295        }
     4296
     4297        return nwrap_getpwuid(uid);
     4298}
     4299
     4300/****************************************************************************
     4301 *   GETPWUID_R
     4302 ***************************************************************************/
     4303
     4304static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
     4305                            char *buf, size_t buflen, struct passwd **pwdstp)
    18934306{
    18944307        int i,ret;
    1895 
    1896         if (!nwrap_enabled()) {
    1897                 return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
    1898         }
    18994308
    19004309        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    19104319}
    19114320
    1912 _PUBLIC_ void nwrap_setpwent(void)
     4321#ifdef HAVE_SOLARIS_GETPWUID_R
     4322int getpwuid_r(uid_t uid, struct passwd *pwdst,
     4323               char *buf, int buflen, struct passwd **pwdstp)
     4324#else
     4325int getpwuid_r(uid_t uid, struct passwd *pwdst,
     4326               char *buf, size_t buflen, struct passwd **pwdstp)
     4327#endif
     4328{
     4329        if (!nss_wrapper_enabled()) {
     4330                return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
     4331        }
     4332
     4333        return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
     4334}
     4335
     4336/****************************************************************************
     4337 *   SETPWENT
     4338 ***************************************************************************/
     4339
     4340static void nwrap_setpwent(void)
    19134341{
    19144342        int i;
    1915 
    1916         if (!nwrap_enabled()) {
    1917                 real_setpwent();
    1918                 return;
    1919         }
    19204343
    19214344        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    19254348}
    19264349
    1927 _PUBLIC_ struct passwd *nwrap_getpwent(void)
     4350void setpwent(void)
     4351{
     4352        if (!nss_wrapper_enabled()) {
     4353                libc_setpwent();
     4354                return;
     4355        }
     4356
     4357        nwrap_setpwent();
     4358}
     4359
     4360/****************************************************************************
     4361 *   GETPWENT
     4362 ***************************************************************************/
     4363
     4364static struct passwd *nwrap_getpwent(void)
    19284365{
    19294366        int i;
    19304367        struct passwd *pwd;
    1931 
    1932         if (!nwrap_enabled()) {
    1933                 return real_getpwent();
    1934         }
    19354368
    19364369        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    19454378}
    19464379
    1947 _PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
    1948                               size_t buflen, struct passwd **pwdstp)
     4380struct passwd *getpwent(void)
     4381{
     4382        if (!nss_wrapper_enabled()) {
     4383                return libc_getpwent();
     4384        }
     4385
     4386        return nwrap_getpwent();
     4387}
     4388
     4389/****************************************************************************
     4390 *   GETPWENT_R
     4391 ***************************************************************************/
     4392
     4393static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
     4394                            size_t buflen, struct passwd **pwdstp)
    19494395{
    19504396        int i,ret;
    1951 
    1952         if (!nwrap_enabled()) {
    1953 #ifdef SOLARIS_GETPWENT_R
    1954                 struct passwd *pw;
    1955                 pw = real_getpwent_r(pwdst, buf, buflen);
    1956                 if (!pw) {
    1957                         if (errno == 0) {
    1958                                 return ENOENT;
    1959                         }
    1960                         return errno;
    1961                 }
    1962                 if (pwdstp) {
    1963                         *pwdstp = pw;
    1964                 }
    1965                 return 0;
    1966 #else
    1967                 return real_getpwent_r(pwdst, buf, buflen, pwdstp);
    1968 #endif
    1969         }
    19704397
    19714398        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    19814408}
    19824409
    1983 _PUBLIC_ void nwrap_endpwent(void)
     4410#ifdef HAVE_SOLARIS_GETPWENT_R
     4411struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
     4412{
     4413        struct passwd *pwdstp = NULL;
     4414        int rc;
     4415
     4416        if (!nss_wrapper_enabled()) {
     4417                return libc_getpwent_r(pwdst, buf, buflen);
     4418        }
     4419        rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
     4420        if (rc < 0) {
     4421                return NULL;
     4422        }
     4423
     4424        return pwdstp;
     4425}
     4426#else /* HAVE_SOLARIS_GETPWENT_R */
     4427int getpwent_r(struct passwd *pwdst, char *buf,
     4428               size_t buflen, struct passwd **pwdstp)
     4429{
     4430        if (!nss_wrapper_enabled()) {
     4431                return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
     4432        }
     4433
     4434        return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
     4435}
     4436#endif /* HAVE_SOLARIS_GETPWENT_R */
     4437
     4438/****************************************************************************
     4439 *   ENDPWENT
     4440 ***************************************************************************/
     4441
     4442static void nwrap_endpwent(void)
    19844443{
    19854444        int i;
    1986 
    1987         if (!nwrap_enabled()) {
    1988                 real_endpwent();
    1989                 return;
    1990         }
    19914445
    19924446        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    19964450}
    19974451
    1998 _PUBLIC_ int nwrap_initgroups(const char *user, gid_t group)
     4452void endpwent(void)
     4453{
     4454        if (!nss_wrapper_enabled()) {
     4455                libc_endpwent();
     4456                return;
     4457        }
     4458
     4459        nwrap_endpwent();
     4460}
     4461
     4462/****************************************************************************
     4463 *   INITGROUPS
     4464 ***************************************************************************/
     4465
     4466static int nwrap_initgroups(const char *user, gid_t group)
    19994467{
    20004468        int i;
    2001 
    2002         if (!nwrap_enabled()) {
    2003                 return real_initgroups(user, group);
    2004         }
    20054469
    20064470        for (i=0; i < nwrap_main_global->num_backends; i++) {
    20074471                struct nwrap_backend *b = &nwrap_main_global->backends[i];
    2008                 return b->ops->nw_initgroups(b, user, group);
     4472                int rc;
     4473
     4474                rc = b->ops->nw_initgroups(b, user, group);
     4475                if (rc == 0) {
     4476                        return 0;
     4477                }
    20094478        }
    20104479
     
    20134482}
    20144483
    2015 _PUBLIC_ struct group *nwrap_getgrnam(const char *name)
     4484int initgroups(const char *user, gid_t group)
     4485{
     4486        if (!nss_wrapper_enabled()) {
     4487                return libc_initgroups(user, group);
     4488        }
     4489
     4490        return nwrap_initgroups(user, group);
     4491}
     4492
     4493/****************************************************************************
     4494 *   GETGRNAM
     4495 ***************************************************************************/
     4496
     4497static struct group *nwrap_getgrnam(const char *name)
    20164498{
    20174499        int i;
    20184500        struct group *grp;
    2019 
    2020         if (!nwrap_enabled()) {
    2021                 return real_getgrnam(name);
    2022         }
    20234501
    20244502        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    20334511}
    20344512
    2035 _PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
    2036                               char *buf, size_t buflen, struct group **grdstp)
    2037 {
    2038         int i,ret;
    2039 
    2040         if (!nwrap_enabled()) {
    2041                 return real_getgrnam_r(name, grdst, buf, buflen, grdstp);
    2042         }
     4513struct group *getgrnam(const char *name)
     4514{
     4515        if (!nss_wrapper_enabled()) {
     4516                return libc_getgrnam(name);
     4517        }
     4518
     4519        return nwrap_getgrnam(name);
     4520}
     4521
     4522/****************************************************************************
     4523 *   GETGRNAM_R
     4524 ***************************************************************************/
     4525
     4526static int nwrap_getgrnam_r(const char *name, struct group *grdst,
     4527                            char *buf, size_t buflen, struct group **grdstp)
     4528{
     4529        int i, ret;
    20434530
    20444531        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    20544541}
    20554542
    2056 _PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
     4543#ifdef HAVE_GETGRNAM_R
     4544# ifdef HAVE_SOLARIS_GETGRNAM_R
     4545int getgrnam_r(const char *name, struct group *grp,
     4546                char *buf, int buflen, struct group **pgrp)
     4547# else /* HAVE_SOLARIS_GETGRNAM_R */
     4548int getgrnam_r(const char *name, struct group *grp,
     4549               char *buf, size_t buflen, struct group **pgrp)
     4550# endif /* HAVE_SOLARIS_GETGRNAM_R */
     4551{
     4552        if (!nss_wrapper_enabled()) {
     4553                return libc_getgrnam_r(name,
     4554                                       grp,
     4555                                       buf,
     4556                                       buflen,
     4557                                       pgrp);
     4558        }
     4559
     4560        return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
     4561}
     4562#endif /* HAVE_GETGRNAM_R */
     4563
     4564/****************************************************************************
     4565 *   GETGRGID
     4566 ***************************************************************************/
     4567
     4568static struct group *nwrap_getgrgid(gid_t gid)
    20574569{
    20584570        int i;
    20594571        struct group *grp;
    2060 
    2061         if (!nwrap_enabled()) {
    2062                 return real_getgrgid(gid);
    2063         }
    20644572
    20654573        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    20744582}
    20754583
    2076 _PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
    2077                               char *buf, size_t buflen, struct group **grdstp)
     4584struct group *getgrgid(gid_t gid)
     4585{
     4586        if (!nss_wrapper_enabled()) {
     4587                return libc_getgrgid(gid);
     4588        }
     4589
     4590        return nwrap_getgrgid(gid);
     4591}
     4592
     4593/****************************************************************************
     4594 *   GETGRGID_R
     4595 ***************************************************************************/
     4596
     4597static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
     4598                            char *buf, size_t buflen, struct group **grdstp)
    20784599{
    20794600        int i,ret;
    2080 
    2081         if (!nwrap_enabled()) {
    2082                 return real_getgrgid_r(gid, grdst, buf, buflen, grdstp);
    2083         }
    20844601
    20854602        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    20954612}
    20964613
    2097 _PUBLIC_ void nwrap_setgrent(void)
     4614#ifdef HAVE_GETGRGID_R
     4615# ifdef HAVE_SOLARIS_GETGRGID_R
     4616int getgrgid_r(gid_t gid, struct group *grdst,
     4617               char *buf, int buflen, struct group **grdstp)
     4618# else /* HAVE_SOLARIS_GETGRGID_R */
     4619int getgrgid_r(gid_t gid, struct group *grdst,
     4620               char *buf, size_t buflen, struct group **grdstp)
     4621# endif /* HAVE_SOLARIS_GETGRGID_R */
     4622{
     4623        if (!nss_wrapper_enabled()) {
     4624                return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
     4625        }
     4626
     4627        return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
     4628}
     4629#endif
     4630
     4631/****************************************************************************
     4632 *   SETGRENT
     4633 ***************************************************************************/
     4634
     4635static void nwrap_setgrent(void)
    20984636{
    20994637        int i;
    2100 
    2101         if (!nwrap_enabled()) {
    2102                 real_setgrent();
    2103                 return;
    2104         }
    21054638
    21064639        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    21104643}
    21114644
    2112 _PUBLIC_ struct group *nwrap_getgrent(void)
     4645#ifdef HAVE_BSD_SETGRENT
     4646int setgrent(void)
     4647#else
     4648void setgrent(void)
     4649#endif
     4650{
     4651        if (!nss_wrapper_enabled()) {
     4652                libc_setgrent();
     4653                goto out;
     4654        }
     4655
     4656        nwrap_setgrent();
     4657
     4658out:
     4659#ifdef HAVE_BSD_SETGRENT
     4660        return 0;
     4661#else
     4662        return;
     4663#endif
     4664}
     4665
     4666/****************************************************************************
     4667 *   GETGRENT
     4668 ***************************************************************************/
     4669
     4670static struct group *nwrap_getgrent(void)
    21134671{
    21144672        int i;
    21154673        struct group *grp;
    2116 
    2117         if (!nwrap_enabled()) {
    2118                 return real_getgrent();
    2119         }
    21204674
    21214675        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    21304684}
    21314685
    2132 _PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
    2133                               size_t buflen, struct group **grdstp)
     4686struct group *getgrent(void)
     4687{
     4688        if (!nss_wrapper_enabled()) {
     4689                return libc_getgrent();
     4690        }
     4691
     4692        return nwrap_getgrent();
     4693}
     4694
     4695/****************************************************************************
     4696 *   GETGRENT_R
     4697 ***************************************************************************/
     4698
     4699static int nwrap_getgrent_r(struct group *grdst, char *buf,
     4700                            size_t buflen, struct group **grdstp)
    21344701{
    21354702        int i,ret;
    2136 
    2137         if (!nwrap_enabled()) {
    2138 #ifdef SOLARIS_GETGRENT_R
    2139                 struct group *gr;
    2140                 gr = real_getgrent_r(grdst, buf, buflen);
    2141                 if (!gr) {
    2142                         if (errno == 0) {
    2143                                 return ENOENT;
    2144                         }
    2145                         return errno;
    2146                 }
    2147                 if (grdstp) {
    2148                         *grdstp = gr;
    2149                 }
    2150                 return 0;
    2151 #else
    2152                 return real_getgrent_r(grdst, buf, buflen, grdstp);
    2153 #endif
    2154         }
    21554703
    21564704        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    21664714}
    21674715
    2168 _PUBLIC_ void nwrap_endgrent(void)
     4716#ifdef HAVE_SOLARIS_GETGRENT_R
     4717struct group *getgrent_r(struct group *src, char *buf, int buflen)
     4718{
     4719        struct group *grdstp = NULL;
     4720        int rc;
     4721
     4722        if (!nss_wrapper_enabled()) {
     4723                return libc_getgrent_r(src, buf, buflen);
     4724        }
     4725
     4726        rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
     4727        if (rc < 0) {
     4728                return NULL;
     4729        }
     4730
     4731        return grdstp;
     4732}
     4733#else /* HAVE_SOLARIS_GETGRENT_R */
     4734int getgrent_r(struct group *src, char *buf,
     4735               size_t buflen, struct group **grdstp)
     4736{
     4737        if (!nss_wrapper_enabled()) {
     4738                return libc_getgrent_r(src, buf, buflen, grdstp);
     4739        }
     4740
     4741        return nwrap_getgrent_r(src, buf, buflen, grdstp);
     4742}
     4743#endif /* HAVE_SOLARIS_GETGRENT_R */
     4744
     4745/****************************************************************************
     4746 *   ENDGRENT
     4747 ***************************************************************************/
     4748
     4749static void nwrap_endgrent(void)
    21694750{
    21704751        int i;
    2171 
    2172         if (!nwrap_enabled()) {
    2173                 real_endgrent();
    2174                 return;
    2175         }
    21764752
    21774753        for (i=0; i < nwrap_main_global->num_backends; i++) {
     
    21814757}
    21824758
    2183 _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
     4759void endgrent(void)
     4760{
     4761        if (!nss_wrapper_enabled()) {
     4762                libc_endgrent();
     4763                return;
     4764        }
     4765
     4766        nwrap_endgrent();
     4767}
     4768
     4769/****************************************************************************
     4770 *   GETGROUPLIST
     4771 ***************************************************************************/
     4772
     4773#ifdef HAVE_GETGROUPLIST
     4774static int nwrap_getgrouplist(const char *user, gid_t group,
     4775                              gid_t *groups, int *ngroups)
    21844776{
    21854777        struct group *grp;
    21864778        gid_t *groups_tmp;
    21874779        int count = 1;
    2188         const char *name_of_group = "";
    2189 
    2190         if (!nwrap_enabled()) {
    2191                 return real_getgrouplist(user, group, groups, ngroups);
    2192         }
    2193 
    2194         NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user));
     4780
     4781        NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
    21954782
    21964783        groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
    21974784        if (!groups_tmp) {
    2198                 NWRAP_ERROR(("%s:calloc failed\n",__location__));
     4785                NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
    21994786                errno = ENOMEM;
    22004787                return -1;
    22014788        }
    2202 
    2203         memcpy(groups_tmp, &group, sizeof(gid_t));
    2204 
    2205         grp = nwrap_getgrgid(group);
    2206         if (grp) {
    2207                 name_of_group = grp->gr_name;
    2208         }
     4789        groups_tmp[0] = group;
    22094790
    22104791        nwrap_setgrent();
     
    22124793                int i = 0;
    22134794
    2214                 NWRAP_VERBOSE(("%s: inspecting %s for group membership\n",
    2215                                __location__, grp->gr_name));
     4795                NWRAP_LOG(NWRAP_LOG_DEBUG,
     4796                          "Inspecting %s for group membership",
     4797                          grp->gr_name);
    22164798
    22174799                for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
    22184800
    2219                         if ((strcmp(user, grp->gr_mem[i]) == 0) &&
    2220                             (strcmp(name_of_group, grp->gr_name) != 0)) {
    2221 
    2222                                 NWRAP_DEBUG(("%s: %s is member of %s\n",
    2223                                         __location__, user, grp->gr_name));
     4801                        if (group != grp->gr_gid &&
     4802                            (strcmp(user, grp->gr_mem[i]) == 0)) {
     4803
     4804                                NWRAP_LOG(NWRAP_LOG_DEBUG,
     4805                                          "%s is member of %s",
     4806                                          user,
     4807                                          grp->gr_name);
    22244808
    22254809                                groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
    22264810                                if (!groups_tmp) {
    2227                                         NWRAP_ERROR(("%s:calloc failed\n",__location__));
     4811                                        NWRAP_LOG(NWRAP_LOG_ERROR,
     4812                                                  "Out of memory");
    22284813                                        errno = ENOMEM;
    22294814                                        return -1;
    22304815                                }
    2231 
    2232                                 memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t));
     4816                                groups_tmp[count] = grp->gr_gid;
     4817
    22334818                                count++;
    22344819                        }
     
    22384823        nwrap_endgrent();
    22394824
    2240         NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n",
    2241                        __location__, user, *ngroups));
     4825        NWRAP_LOG(NWRAP_LOG_DEBUG,
     4826                  "%s is member of %d groups",
     4827                  user, *ngroups);
    22424828
    22434829        if (*ngroups < count) {
     
    22534839        return count;
    22544840}
     4841
     4842int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
     4843{
     4844        if (!nss_wrapper_enabled()) {
     4845                return libc_getgrouplist(user, group, groups, ngroups);
     4846        }
     4847
     4848        return nwrap_getgrouplist(user, group, groups, ngroups);
     4849}
     4850#endif
     4851
     4852/**********************************************************
     4853 * SHADOW
     4854 **********************************************************/
     4855
     4856#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     4857
     4858#ifdef HAVE_SETSPENT
     4859static void nwrap_setspent(void)
     4860{
     4861        nwrap_files_setspent();
     4862}
     4863
     4864void setspent(void)
     4865{
     4866        if (!nss_wrapper_shadow_enabled()) {
     4867                return;
     4868        }
     4869
     4870        nwrap_setspent();
     4871}
     4872
     4873static struct spwd *nwrap_getspent(void)
     4874{
     4875        return nwrap_files_getspent();
     4876}
     4877
     4878struct spwd *getspent(void)
     4879{
     4880        if (!nss_wrapper_shadow_enabled()) {
     4881                return NULL;
     4882        }
     4883
     4884        return nwrap_getspent();
     4885}
     4886
     4887static void nwrap_endspent(void)
     4888{
     4889        nwrap_files_endspent();
     4890}
     4891
     4892void endspent(void)
     4893{
     4894        if (!nss_wrapper_shadow_enabled()) {
     4895                return;
     4896        }
     4897
     4898        nwrap_endspent();
     4899}
     4900#endif /* HAVE_SETSPENT */
     4901
     4902static struct spwd *nwrap_getspnam(const char *name)
     4903{
     4904        return nwrap_files_getspnam(name);
     4905}
     4906
     4907struct spwd *getspnam(const char *name)
     4908{
     4909        if (!nss_wrapper_shadow_enabled()) {
     4910                return NULL;
     4911        }
     4912
     4913        return nwrap_getspnam(name);
     4914}
     4915
     4916#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     4917
     4918/**********************************************************
     4919 * NETDB
     4920 **********************************************************/
     4921
     4922static void nwrap_sethostent(int stayopen) {
     4923        (void) stayopen; /* ignored */
     4924
     4925        nwrap_files_sethostent();
     4926}
     4927
     4928#ifdef HAVE_SOLARIS_SETHOSTENT
     4929int sethostent(int stayopen)
     4930{
     4931        if (!nss_wrapper_hosts_enabled()) {
     4932                libc_sethostent(stayopen);
     4933                return 0;
     4934        }
     4935
     4936        nwrap_sethostent(stayopen);
     4937
     4938        return 0;
     4939}
     4940#else /* HAVE_SOLARIS_SETHOSTENT */
     4941void sethostent(int stayopen)
     4942{
     4943        if (!nss_wrapper_hosts_enabled()) {
     4944                libc_sethostent(stayopen);
     4945                return;
     4946        }
     4947
     4948        nwrap_sethostent(stayopen);
     4949}
     4950#endif /* HAVE_SOLARIS_SETHOSTENT */
     4951
     4952static struct hostent *nwrap_gethostent(void)
     4953{
     4954        return nwrap_files_gethostent();
     4955}
     4956
     4957struct hostent *gethostent(void) {
     4958        if (!nss_wrapper_hosts_enabled()) {
     4959                return libc_gethostent();
     4960        }
     4961
     4962        return nwrap_gethostent();
     4963}
     4964
     4965static void nwrap_endhostent(void) {
     4966        nwrap_files_endhostent();
     4967}
     4968
     4969#ifdef HAVE_SOLARIS_ENDHOSTENT
     4970int endhostent(void)
     4971{
     4972        if (!nss_wrapper_hosts_enabled()) {
     4973                libc_endhostent();
     4974                return 0;
     4975        }
     4976
     4977        nwrap_endhostent();
     4978
     4979        return 0;
     4980}
     4981#else /* HAVE_SOLARIS_ENDHOSTENT */
     4982void endhostent(void)
     4983{
     4984        if (!nss_wrapper_hosts_enabled()) {
     4985                libc_endhostent();
     4986                return;
     4987        }
     4988
     4989        nwrap_endhostent();
     4990}
     4991#endif /* HAVE_SOLARIS_ENDHOSTENT */
     4992
     4993#ifdef BSD
     4994/* BSD implementation stores data in thread local storage but GLIBC does not */
     4995static __thread struct hostent user_he;
     4996static __thread struct nwrap_vector user_addrlist;
     4997#else
     4998static struct hostent user_he;
     4999static struct nwrap_vector user_addrlist;
     5000#endif /* BSD */
     5001static struct hostent *nwrap_gethostbyname(const char *name)
     5002{
     5003        if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
     5004                return NULL;
     5005        }
     5006        return &user_he;
     5007}
     5008
     5009struct hostent *gethostbyname(const char *name)
     5010{
     5011        if (!nss_wrapper_hosts_enabled()) {
     5012                return libc_gethostbyname(name);
     5013        }
     5014
     5015        return nwrap_gethostbyname(name);
     5016}
     5017
     5018/* This is a GNU extension - Also can be found on BSD systems */
     5019#ifdef HAVE_GETHOSTBYNAME2
     5020#ifdef BSD
     5021/* BSD implementation stores data in  thread local storage but GLIBC not */
     5022static __thread struct hostent user_he2;
     5023static __thread struct nwrap_vector user_addrlist2;
     5024#else
     5025static struct hostent user_he2;
     5026static struct nwrap_vector user_addrlist2;
     5027#endif /* BSD */
     5028static struct hostent *nwrap_gethostbyname2(const char *name, int af)
     5029{
     5030        if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
     5031                return NULL;
     5032        }
     5033        return &user_he2;
     5034}
     5035
     5036struct hostent *gethostbyname2(const char *name, int af)
     5037{
     5038        if (!nss_wrapper_hosts_enabled()) {
     5039                return libc_gethostbyname2(name, af);
     5040        }
     5041
     5042        return nwrap_gethostbyname2(name, af);
     5043}
     5044#endif
     5045
     5046static struct hostent *nwrap_gethostbyaddr(const void *addr,
     5047                                           socklen_t len, int type)
     5048{
     5049        return nwrap_files_gethostbyaddr(addr, len, type);
     5050}
     5051
     5052struct hostent *gethostbyaddr(const void *addr,
     5053                              socklen_t len, int type)
     5054{
     5055        if (!nss_wrapper_hosts_enabled()) {
     5056                return libc_gethostbyaddr(addr, len, type);
     5057        }
     5058
     5059        return nwrap_gethostbyaddr(addr, len, type);
     5060}
     5061
     5062static const struct addrinfo default_hints =
     5063{
     5064        .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
     5065        .ai_family = AF_UNSPEC,
     5066        .ai_socktype = 0,
     5067        .ai_protocol = 0,
     5068        .ai_addrlen = 0,
     5069        .ai_addr = NULL,
     5070        .ai_canonname = NULL,
     5071        .ai_next = NULL
     5072};
     5073
     5074static int nwrap_convert_he_ai(const struct hostent *he,
     5075                               unsigned short port,
     5076                               const struct addrinfo *hints,
     5077                               struct addrinfo **pai,
     5078                               bool skip_canonname)
     5079{
     5080        struct addrinfo *ai;
     5081        socklen_t socklen;
     5082
     5083        if (he == NULL) {
     5084                return EAI_MEMORY;
     5085        }
     5086
     5087        switch (he->h_addrtype) {
     5088                case AF_INET:
     5089                        socklen = sizeof(struct sockaddr_in);
     5090                        break;
     5091#ifdef HAVE_IPV6
     5092                case AF_INET6:
     5093                        socklen = sizeof(struct sockaddr_in6);
     5094                        break;
     5095#endif
     5096                default:
     5097                        return EAI_FAMILY;
     5098        }
     5099
     5100        ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
     5101        if (ai == NULL) {
     5102                return EAI_MEMORY;
     5103        }
     5104
     5105        ai->ai_flags = hints->ai_flags;
     5106        ai->ai_family = he->h_addrtype;
     5107        ai->ai_socktype = hints->ai_socktype;
     5108        ai->ai_protocol = hints->ai_protocol;
     5109        ai->ai_canonname = NULL;
     5110
     5111        if (ai->ai_socktype == 0) {
     5112                ai->ai_socktype = SOCK_DGRAM;
     5113        }
     5114        if (ai->ai_protocol == 0) {
     5115                if (ai->ai_socktype == SOCK_DGRAM) {
     5116                        ai->ai_protocol = IPPROTO_UDP;
     5117                } else if (ai->ai_socktype == SOCK_STREAM) {
     5118                        ai->ai_protocol = IPPROTO_TCP;
     5119                }
     5120        }
     5121
     5122        ai->ai_addrlen = socklen;
     5123        ai->ai_addr = (void *)(ai + 1);
     5124
     5125#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
     5126        ai->ai_addr->sa_len = socklen;
     5127#endif
     5128        ai->ai_addr->sa_family = he->h_addrtype;
     5129
     5130        switch (he->h_addrtype) {
     5131                case AF_INET:
     5132                {
     5133                        struct sockaddr_in *sinp =
     5134                                (struct sockaddr_in *) ai->ai_addr;
     5135
     5136                        memset(sinp, 0, sizeof(struct sockaddr_in));
     5137
     5138                        sinp->sin_port = htons(port);
     5139                        sinp->sin_family = AF_INET;
     5140
     5141                        memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
     5142                        memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
     5143
     5144                }
     5145                break;
     5146#ifdef HAVE_IPV6
     5147                case AF_INET6:
     5148                {
     5149                        struct sockaddr_in6 *sin6p =
     5150                                (struct sockaddr_in6 *) ai->ai_addr;
     5151
     5152                        memset(sin6p, 0, sizeof(struct sockaddr_in6));
     5153
     5154                        sin6p->sin6_port = htons(port);
     5155                        sin6p->sin6_family = AF_INET6;
     5156
     5157                        memcpy(&sin6p->sin6_addr,
     5158                               he->h_addr_list[0],
     5159                               he->h_length);
     5160                }
     5161                break;
     5162#endif
     5163        }
     5164
     5165        ai->ai_next = NULL;
     5166
     5167        if (he->h_name && !skip_canonname) {
     5168                ai->ai_canonname = strdup(he->h_name);
     5169                if (ai->ai_canonname == NULL) {
     5170                        freeaddrinfo(ai);
     5171                        return EAI_MEMORY;
     5172                }
     5173        }
     5174
     5175        *pai = ai;
     5176        return 0;
     5177}
     5178
     5179static int nwrap_getaddrinfo(const char *node,
     5180                             const char *service,
     5181                             const struct addrinfo *hints,
     5182                             struct addrinfo **res)
     5183{
     5184        struct addrinfo *ai = NULL;
     5185        unsigned short port = 0;
     5186        struct {
     5187                int family;
     5188                union {
     5189                        struct in_addr v4;
     5190#ifdef HAVE_IPV6
     5191                        struct in6_addr v6;
     5192                } in;
     5193#endif
     5194        } addr = {
     5195                .family = AF_UNSPEC,
     5196        };
     5197        int rc;
     5198
     5199        if (node == NULL && service == NULL) {
     5200                return EAI_NONAME;
     5201        }
     5202
     5203        if (hints == NULL) {
     5204                hints = &default_hints;
     5205        }
     5206
     5207        /* EAI_BADFLAGS
     5208              hints.ai_flags   contains   invalid  flags;  or,  hints.ai_flags
     5209              included AI_CANONNAME and name was NULL.
     5210        */
     5211        if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
     5212                return EAI_BADFLAGS;
     5213        }
     5214
     5215        /* If no node has been specified, let glibc deal with it */
     5216        if (node == NULL) {
     5217                int ret;
     5218                struct addrinfo *p = NULL;
     5219
     5220                ret = libc_getaddrinfo(node, service, hints, &p);
     5221
     5222                if (ret == 0) {
     5223                        *res = p;
     5224                }
     5225                return ret;
     5226        }
     5227
     5228        if (service != NULL && service[0] != '\0') {
     5229                const char *proto = NULL;
     5230                struct servent *s;
     5231                char *end_ptr;
     5232                long sl;
     5233
     5234                errno = 0;
     5235                sl = strtol(service, &end_ptr, 10);
     5236
     5237                if (*end_ptr == '\0') {
     5238                        port = sl;
     5239                        goto valid_port;
     5240                } else if (hints->ai_flags & AI_NUMERICSERV) {
     5241                        return EAI_NONAME;
     5242                }
     5243
     5244                if (hints->ai_protocol != 0) {
     5245                        struct protoent *pent;
     5246
     5247                        pent = getprotobynumber(hints->ai_protocol);
     5248                        if (pent != NULL) {
     5249                                proto = pent->p_name;
     5250                        }
     5251                }
     5252
     5253                s = getservbyname(service, proto);
     5254                if (s == NULL) {
     5255                        return EAI_NONAME;
     5256                }
     5257                port = ntohs(s->s_port);
     5258        }
     5259
     5260valid_port:
     5261
     5262        rc = inet_pton(AF_INET, node, &addr.in.v4);
     5263        if (rc == 1) {
     5264                addr.family = AF_INET;
     5265        }
     5266#ifdef HAVE_IPV6
     5267        if (addr.family == AF_UNSPEC) {
     5268                rc = inet_pton(AF_INET6, node, &addr.in.v6);
     5269                if (rc == 1) {
     5270                        addr.family = AF_INET6;
     5271                }
     5272        }
     5273#endif
     5274
     5275        if (addr.family == AF_UNSPEC) {
     5276               if (hints->ai_flags & AI_NUMERICHOST) {
     5277                        return EAI_NONAME;
     5278                }
     5279        } else if ((hints->ai_family != AF_UNSPEC) &&
     5280                   (hints->ai_family != addr.family))
     5281        {
     5282                return EAI_ADDRFAMILY;
     5283        }
     5284
     5285        rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
     5286        if (rc != 0) {
     5287                int ret;
     5288                struct addrinfo *p = NULL;
     5289
     5290                ret = libc_getaddrinfo(node, service, hints, &p);
     5291
     5292                if (ret == 0) {
     5293                        /*
     5294                         * nwrap_files_getaddrinfo failed, but libc was
     5295                         * successful -- use the result from libc.
     5296                         */
     5297                        *res = p;
     5298                        return 0;
     5299                }
     5300
     5301                return rc;
     5302        }
     5303
     5304        /*
     5305         * If the socktype was not specified, duplicate
     5306         * each ai returned, so that we have variants for
     5307         * both UDP and TCP.
     5308         */
     5309        if (hints->ai_socktype == 0) {
     5310                struct addrinfo *ai_cur;
     5311
     5312                /* freeaddrinfo() frees ai_canonname and ai so allocate them */
     5313                for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
     5314                        struct addrinfo *ai_new;
     5315
     5316                        /* duplicate the current entry */
     5317
     5318                        ai_new = malloc(sizeof(struct addrinfo));
     5319                        if (ai_new == NULL) {
     5320                                freeaddrinfo(ai);
     5321                                return EAI_MEMORY;
     5322                        }
     5323
     5324                        memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
     5325                        ai_new->ai_next = NULL;
     5326
     5327                        /* We need a deep copy or freeaddrinfo() will blow up */
     5328                        if (ai_cur->ai_canonname != NULL) {
     5329                                ai_new->ai_canonname =
     5330                                        strdup(ai_cur->ai_canonname);
     5331                        }
     5332
     5333                        if (ai_cur->ai_socktype == SOCK_DGRAM) {
     5334                                ai_new->ai_socktype = SOCK_STREAM;
     5335                        } else if (ai_cur->ai_socktype == SOCK_STREAM) {
     5336                                ai_new->ai_socktype = SOCK_DGRAM;
     5337                        }
     5338                        if (ai_cur->ai_protocol == IPPROTO_TCP) {
     5339                                ai_new->ai_protocol = IPPROTO_UDP;
     5340                        } else if (ai_cur->ai_protocol == IPPROTO_UDP) {
     5341                                ai_new->ai_protocol = IPPROTO_TCP;
     5342                        }
     5343
     5344                        /* now insert the new entry */
     5345
     5346                        ai_new->ai_next = ai_cur->ai_next;
     5347                        ai_cur->ai_next = ai_new;
     5348
     5349                        /* and move on (don't duplicate the new entry) */
     5350
     5351                        ai_cur = ai_new;
     5352                }
     5353        }
     5354
     5355        *res = ai;
     5356
     5357        return 0;
     5358}
     5359
     5360int getaddrinfo(const char *node, const char *service,
     5361                const struct addrinfo *hints,
     5362                struct addrinfo **res)
     5363{
     5364        if (!nss_wrapper_hosts_enabled()) {
     5365                return libc_getaddrinfo(node, service, hints, res);
     5366        }
     5367
     5368        return nwrap_getaddrinfo(node, service, hints, res);
     5369}
     5370
     5371static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
     5372                             char *host, size_t hostlen,
     5373                             char *serv, size_t servlen,
     5374                             int flags)
     5375{
     5376        struct hostent *he;
     5377        struct servent *service;
     5378        const char *proto;
     5379        const void *addr;
     5380        socklen_t addrlen;
     5381        uint16_t port;
     5382        sa_family_t type;
     5383
     5384        if (sa == NULL || salen < sizeof(sa_family_t)) {
     5385                return EAI_FAMILY;
     5386        }
     5387
     5388        if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
     5389                return EAI_NONAME;
     5390        }
     5391
     5392        type = sa->sa_family;
     5393        switch (type) {
     5394        case AF_INET:
     5395                if (salen < sizeof(struct sockaddr_in))
     5396                        return EAI_FAMILY;
     5397                addr = &((const struct sockaddr_in *)sa)->sin_addr;
     5398                addrlen = sizeof(((const struct sockaddr_in *)sa)->sin_addr);
     5399                port = ntohs(((const struct sockaddr_in *)sa)->sin_port);
     5400                break;
     5401#ifdef HAVE_IPV6
     5402        case AF_INET6:
     5403                if (salen < sizeof(struct sockaddr_in6))
     5404                        return EAI_FAMILY;
     5405                addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
     5406                addrlen = sizeof(((const struct sockaddr_in6 *)sa)->sin6_addr);
     5407                port = ntohs(((const struct sockaddr_in6 *)sa)->sin6_port);
     5408                break;
     5409#endif
     5410        default:
     5411                return EAI_FAMILY;
     5412        }
     5413
     5414        if (host != NULL) {
     5415                he = NULL;
     5416                if ((flags & NI_NUMERICHOST) == 0) {
     5417                        he = nwrap_files_gethostbyaddr(addr, addrlen, type);
     5418                        if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
     5419                                return EAI_NONAME;
     5420                }
     5421                if (he != NULL && he->h_name != NULL) {
     5422                        if (strlen(he->h_name) >= hostlen)
     5423                                return EAI_OVERFLOW;
     5424                        strcpy(host, he->h_name);
     5425                        if (flags & NI_NOFQDN)
     5426                                host[strcspn(host, ".")] = '\0';
     5427                } else {
     5428                        if (inet_ntop(type, addr, host, hostlen) == NULL)
     5429                                return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
     5430                }
     5431        }
     5432
     5433        if (serv != NULL) {
     5434                service = NULL;
     5435                if ((flags & NI_NUMERICSERV) == 0) {
     5436                        proto = (flags & NI_DGRAM) ? "udp" : "tcp";
     5437                        service = getservbyport(htons(port), proto);
     5438                }
     5439                if (service != NULL) {
     5440                        if (strlen(service->s_name) >= servlen)
     5441                                return EAI_OVERFLOW;
     5442                        strcpy(serv, service->s_name);
     5443                } else {
     5444                        if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
     5445                                return EAI_OVERFLOW;
     5446                }
     5447        }
     5448
     5449        return 0;
     5450}
     5451
     5452#ifdef HAVE_LINUX_GETNAMEINFO
     5453int getnameinfo(const struct sockaddr *sa, socklen_t salen,
     5454                char *host, socklen_t hostlen,
     5455                char *serv, socklen_t servlen,
     5456                int flags)
     5457#elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
     5458int getnameinfo(const struct sockaddr *sa, socklen_t salen,
     5459                char *host, socklen_t hostlen,
     5460                char *serv, socklen_t servlen,
     5461                unsigned int flags)
     5462#else
     5463int getnameinfo(const struct sockaddr *sa, socklen_t salen,
     5464                char *host, size_t hostlen,
     5465                char *serv, size_t servlen,
     5466                int flags)
     5467#endif
     5468{
     5469        if (!nss_wrapper_hosts_enabled()) {
     5470                return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
     5471        }
     5472
     5473        return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
     5474}
     5475
     5476static int nwrap_gethostname(char *name, size_t len)
     5477{
     5478        const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
     5479
     5480        if (strlen(hostname) >= len) {
     5481                errno = ENAMETOOLONG;
     5482                return -1;
     5483        }
     5484        snprintf(name, len, "%s", hostname);
     5485
     5486        return 0;
     5487}
     5488
     5489#ifdef HAVE_SOLARIS_GETHOSTNAME
     5490int gethostname(char *name, int len)
     5491#else /* HAVE_SOLARIS_GETHOSTNAME */
     5492int gethostname(char *name, size_t len)
     5493#endif /* HAVE_SOLARIS_GETHOSTNAME */
     5494{
     5495        if (!nwrap_hostname_enabled()) {
     5496                return libc_gethostname(name, len);
     5497        }
     5498
     5499        return nwrap_gethostname(name, len);
     5500}
     5501
     5502/****************************
     5503 * DESTRUCTOR
     5504 ***************************/
     5505
     5506/*
     5507 * This function is called when the library is unloaded and makes sure that
     5508 * sockets get closed and the unix file for the socket are unlinked.
     5509 */
     5510void nwrap_destructor(void)
     5511{
     5512        int i;
     5513
     5514        NWRAP_LOCK_ALL;
     5515        if (nwrap_main_global != NULL) {
     5516                struct nwrap_main *m = nwrap_main_global;
     5517
     5518                /* libc */
     5519                SAFE_FREE(m->libc->fns);
     5520                if (m->libc->handle != NULL) {
     5521                        dlclose(m->libc->handle);
     5522                }
     5523                if (m->libc->nsl_handle != NULL) {
     5524                        dlclose(m->libc->nsl_handle);
     5525                }
     5526                if (m->libc->sock_handle != NULL) {
     5527                        dlclose(m->libc->sock_handle);
     5528                }
     5529                SAFE_FREE(m->libc);
     5530
     5531                /* backends */
     5532                for (i = 0; i < m->num_backends; i++) {
     5533                        struct nwrap_backend *b = &(m->backends[i]);
     5534
     5535                        if (b->so_handle != NULL) {
     5536                                dlclose(b->so_handle);
     5537                        }
     5538                        SAFE_FREE(b->fns);
     5539                }
     5540                SAFE_FREE(m->backends);
     5541        }
     5542
     5543        if (nwrap_pw_global.cache != NULL) {
     5544                struct nwrap_cache *c = nwrap_pw_global.cache;
     5545
     5546                nwrap_files_cache_unload(c);
     5547                if (c->fd >= 0) {
     5548                        fclose(c->fp);
     5549                        c->fd = -1;
     5550                }
     5551
     5552                SAFE_FREE(nwrap_pw_global.list);
     5553                nwrap_pw_global.num = 0;
     5554        }
     5555
     5556        if (nwrap_gr_global.cache != NULL) {
     5557                struct nwrap_cache *c = nwrap_gr_global.cache;
     5558
     5559                nwrap_files_cache_unload(c);
     5560                if (c->fd >= 0) {
     5561                        fclose(c->fp);
     5562                        c->fd = -1;
     5563                }
     5564
     5565                SAFE_FREE(nwrap_gr_global.list);
     5566                nwrap_pw_global.num = 0;
     5567        }
     5568
     5569#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
     5570        if (nwrap_sp_global.cache != NULL) {
     5571                struct nwrap_cache *c = nwrap_sp_global.cache;
     5572
     5573                nwrap_files_cache_unload(c);
     5574                if (c->fd >= 0) {
     5575                        fclose(c->fp);
     5576                        c->fd = -1;
     5577                }
     5578
     5579                nwrap_sp_global.num = 0;
     5580        }
     5581#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
     5582
     5583        if (nwrap_he_global.cache != NULL) {
     5584                struct nwrap_cache *c = nwrap_he_global.cache;
     5585
     5586                nwrap_files_cache_unload(c);
     5587                if (c->fd >= 0) {
     5588                        fclose(c->fp);
     5589                        c->fd = -1;
     5590                }
     5591
     5592                nwrap_he_global.num = 0;
     5593        }
     5594
     5595        free(user_addrlist.items);
     5596#ifdef HAVE_GETHOSTBYNAME2
     5597        free(user_addrlist2.items);
     5598#endif
     5599
     5600        hdestroy();
     5601        NWRAP_UNLOCK_ALL;
     5602}
  • vendor/current/lib/nss_wrapper/wscript

    r740 r988  
    11#!/usr/bin/env python
    22
    3 import Options
     3import os
    44
    5 def set_options(opt):
    6     gr = opt.option_group('developer options')
    7     gr.add_option('--enable-nss-wrapper',
    8               help=("Turn on nss wrapper library (default=no)"),
    9               action="store_true", dest='enable_nss_wrapper', default=False)
     5VERSION="1.1.2"
    106
    117def configure(conf):
    12     if (Options.options.enable_nss_wrapper or
    13         Options.options.developer or
    14         Options.options.enable_selftest):
    15         conf.DEFINE('NSS_WRAPPER', 1)
    16         conf.ADD_GLOBAL_DEPENDENCY('nss_wrapper')
     8    if conf.CHECK_BUNDLED_SYSTEM('nss_wrapper', minversion=VERSION, set_target=False):
     9        conf.DEFINE('USING_SYSTEM_NSS_WRAPPER', 1)
     10        libnss_wrapper_so_path = 'libnss_wrapper.so'
     11    else:
     12        conf.CHECK_HEADERS('nss.h')
    1713
     14        # check HAVE_GCC_THREAD_LOCAL_STORAGE
     15        conf.CHECK_CODE('''
     16            __thread int tls;
     17
     18            int main(void) {
     19                return 0;
     20            }
     21            ''',
     22            'HAVE_GCC_THREAD_LOCAL_STORAGE',
     23            addmain=False,
     24            msg='Checking for thread local storage')
     25
     26        # check HAVE_DESTRUCTOR_ATTRIBUTE
     27        conf.CHECK_CODE('''
     28            void test_destructor_attribute(void) __attribute__ ((destructor));
     29
     30            void test_destructor_attribute(void)
     31            {
     32                return;
     33            }
     34
     35            int main(void) {
     36                return 0;
     37            }
     38            ''',
     39            'HAVE_DESTRUCTOR_ATTRIBUTE',
     40            addmain=False,
     41            msg='Checking for library destructor support')
     42
     43        conf.CHECK_FUNCS('gethostbyaddr_r gethostbyname_r')
     44        # Solaris
     45        conf.CHECK_FUNCS('__posix_getpwnam_r __posix_getpwuid_r')
     46        conf.CHECK_FUNCS('__posix_getgrgid_r __posix_getgrnam_r')
     47
     48        conf.CHECK_FUNCS_IN('nsl',
     49                            'gethostname',
     50                            checklibc=True,
     51                            headers='unistd.h')
     52
     53        # Prototype checks
     54        conf.CHECK_C_PROTOTYPE('getpwent_r',
     55                               'struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)',
     56                               define='HAVE_SOLARIS_GETPWENT_R', headers='unistd.h pwd.h')
     57        conf.CHECK_C_PROTOTYPE('getpwnam_r',
     58                               'int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)',
     59                               define='HAVE_SOLARIS_GETPWNAM_R', headers='unistd.h pwd.h')
     60        conf.CHECK_C_PROTOTYPE('getpwuid_r',
     61                               'int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)',
     62                               define='HAVE_SOLARIS_GETPWUID_R', headers='unistd.h pwd.h')
     63        conf.CHECK_C_PROTOTYPE('getgrent_r',
     64                               'struct group *getgrent_r(struct group *src, char *buf, int buflen)',
     65                               define='HAVE_SOLARIS_GETGRENT_R', headers='unistd.h grp.h')
     66        conf.CHECK_C_PROTOTYPE('getgrnam_r',
     67                               'int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)',
     68                               define='HAVE_SOLARIS_GETGRNAM_R', headers='unistd.h grp.h')
     69        conf.CHECK_C_PROTOTYPE('getgrgid_r',
     70                               'int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)',
     71                               define='HAVE_SOLARIS_GETGRGID_R', headers='unistd.h grp.h')
     72        conf.CHECK_C_PROTOTYPE('sethostent',
     73                               'int sethostent(int stayopen)',
     74                               define='HAVE_SOLARIS_SETHOSTENT', headers='unistd.h netdb.h')
     75        conf.CHECK_C_PROTOTYPE('endhostent',
     76                               'int endhostent(void)',
     77                               define='HAVE_SOLARIS_ENDHOSTENT', headers='unistd.h netdb.h')
     78        conf.CHECK_C_PROTOTYPE('gethostname',
     79                               'int gethostname(char *name, int len)',
     80                               define='HAVE_SOLARIS_GETHOSTNAME', headers='unistd.h netdb.h')
     81        conf.CHECK_C_PROTOTYPE('setgrent',
     82                               'int setgrent(void)',
     83                               define='HAVE_BSD_SETGRENT', headers='unistd.h grp.h')
     84        conf.CHECK_C_PROTOTYPE('getnameinfo',
     85                               'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)',
     86                               define='HAVE_LINUX_GETNAMEINFO', headers='unistd.h netdb.h')
     87        conf.CHECK_C_PROTOTYPE('getnameinfo',
     88                               'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)',
     89                               define='HAVE_LINUX_GETNAMEINFO_UNSIGNED', headers='unistd.h netdb.h')
     90
     91        # Create full path to nss_wrapper
     92        srcdir = os.path.realpath(conf.srcdir)
     93        libnss_wrapper_so_path = srcdir + '/bin/default/lib/nss_wrapper/libnss-wrapper.so'
     94
     95    conf.DEFINE('LIBNSS_WRAPPER_SO_PATH', libnss_wrapper_so_path)
     96    conf.DEFINE('NSS_WRAPPER', 1)
     97
     98def build(bld):
     99    if bld.CONFIG_SET("HAVE_NSS_H") and not bld.CONFIG_SET("USING_SYSTEM_NSS_WRAPPER"):
     100        # We need to do it this way or the library wont work.
     101        # Using private_library=True will add symbol version which
     102        # breaks preloading!
     103        bld.SAMBA_LIBRARY('nss_wrapper',
     104                          source='nss_wrapper.c',
     105                          deps='dl',
     106                          install=False,
     107                          realname='libnss-wrapper.so')
Note: See TracChangeset for help on using the changeset viewer.