nss_wrapper-1.1.15/README.install000644 001750 000144 00000003556 12342110056 016452 0ustar00asnusers000000 000000 Obtaining the sources ===================== Source tarballs for nss_wrapper can be downloaded from https://ftp.samba.org/pub/cwrap/ The source code repository for socket wrapper is located under git://git.samba.org/nss_wrapper.git To create a local copy, run $ git clone git://git.samba.org/nss_wrapper.git $ cd nss_wrapper Building from sources ===================== nss_wrapper uses cmake (www.cmake.org) as its build system. In an unpacked sources base directory, create a directory to contain the build results, e.g. $ mkdir obj $ cd obj Note that "obj" is just an example. The directory can be named arbitrarily. Next, run cmake to configure the build, e.g. $ cmake -DCMAKE_INSTALL_PREFIX= .. or on a 64 bit red hat system: $ cmake -DCMAKE_INSTALL_PREFIX= -DLIB_SUFFIX=64 .. The "" should be replaced by the intended installation target prefix directory, typically /usr or /usr/local. Note that the target directory does not have to be a direct or indirect subdirectory of the source base directory: It can be an arbitrary directory in the system. In the general case, ".." has to be replaced by a relative or absolute path of the source base directory in the "cmake" command line. One can control the build type with "-DCMAKE_BUILD_TYPE=" where can be one of Debug, Release, RelWithDebInfo, and some more (see cmake.org). The default is "RelWithDebInfo". After configuring with cmake, run the build with $ make Unit testing ============ In order to support running the test suite after building, the cmocka unit test framework needs to be installed (cmocka.org), and you need to specify -DUNIT_TESTING=ON in the cmake run. After running "make", $ make test runs the test suite. Installing ========== nss_wrapper is installed into the prefix directory after running "cmake" and "make" with $ make install nss_wrapper-1.1.15/src/000755 001750 000144 00000000000 14364246777 014735 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/src/nss_wrapper.c000644 001750 000144 00000437023 14364206715 017441 0ustar00asnusers000000 000000 /* * BSD 3-Clause License * * Copyright (c) 2007, Stefan Metzmacher * Copyright (c) 2009, Guenther Deschner * Copyright (c) 2014-2015, Michael Adam * Copyright (c) 2015, Robin Hack * Copyright (c) 2013-2018, Andreas Schneider * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nss_utils.h" /* * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on * Solaris */ #ifndef _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS #endif #include #include #ifdef HAVE_SHADOW_H #include #endif /* HAVE_SHADOW_H */ #include #include #include #include #if defined(HAVE_NSS_H) /* Linux and BSD */ #include typedef enum nss_status NSS_STATUS; #elif defined(HAVE_NSS_COMMON_H) /* Solaris */ #include #include #include typedef nss_status_t NSS_STATUS; # define NSS_STATUS_SUCCESS NSS_SUCCESS # define NSS_STATUS_NOTFOUND NSS_NOTFOUND # define NSS_STATUS_UNAVAIL NSS_UNAVAIL # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN #else # error "No nsswitch support detected" #endif #ifndef PTR_DIFF #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) #endif #ifndef _PUBLIC_ #define _PUBLIC_ #endif #ifndef EAI_NODATA #define EAI_NODATA EAI_NONAME #endif #ifndef EAI_ADDRFAMILY #define EAI_ADDRFAMILY EAI_FAMILY #endif #ifndef __STRING #define __STRING(x) #x #endif #ifndef __STRINGSTRING #define __STRINGSTRING(x) __STRING(x) #endif #ifndef __LINESTR__ #define __LINESTR__ __STRINGSTRING(__LINE__) #endif #ifndef __location__ #define __location__ __FILE__ ":" __LINESTR__ #endif #ifndef DNS_NAME_MAX #define DNS_NAME_MAX 255 #endif /* GCC have printf type attribute check. */ #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) #else #define PRINTF_ATTRIBUTE(a,b) #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */ #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor)) #else #define CONSTRUCTOR_ATTRIBUTE #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ #ifdef HAVE_DESTRUCTOR_ATTRIBUTE #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) #else #define DESTRUCTOR_ATTRIBUTE #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */ #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) #ifndef SAFE_FREE #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) #endif #ifndef discard_const #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) #endif #ifndef discard_const_p #define discard_const_p(type, ptr) ((type *)discard_const(ptr)) #endif #ifdef HAVE_IPV6 #define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN #else #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN #endif #define MAX(a,b) ((a) < (b) ? (b) : (a)) #define MIN(a,b) ((a) > (b) ? (b) : (a)) static bool nwrap_initialized = false; static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER; /* The mutex or accessing the id */ static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER; #define nss_wrapper_init_mutex(m) \ _nss_wrapper_init_mutex(m, #m) /* Add new global locks here please */ /* Also don't forget to add locks to * nwrap_init() function. */ # define NWRAP_REINIT_ALL do { \ int ret; \ ret = nss_wrapper_init_mutex(&nwrap_initialized_mutex); \ if (ret != 0) exit(-1); \ ret = nss_wrapper_init_mutex(&nwrap_global_mutex); \ if (ret != 0) exit(-1); \ ret = nss_wrapper_init_mutex(&nwrap_gr_global_mutex); \ if (ret != 0) exit(-1); \ ret = nss_wrapper_init_mutex(&nwrap_he_global_mutex); \ if (ret != 0) exit(-1); \ ret = nss_wrapper_init_mutex(&nwrap_pw_global_mutex); \ if (ret != 0) exit(-1); \ ret = nss_wrapper_init_mutex(&nwrap_sp_global_mutex); \ if (ret != 0) exit(-1); \ } while(0) # define NWRAP_LOCK_ALL do { \ nwrap_mutex_lock(&nwrap_initialized_mutex); \ nwrap_mutex_lock(&nwrap_global_mutex); \ nwrap_mutex_lock(&nwrap_gr_global_mutex); \ nwrap_mutex_lock(&nwrap_he_global_mutex); \ nwrap_mutex_lock(&nwrap_pw_global_mutex); \ nwrap_mutex_lock(&nwrap_sp_global_mutex); \ } while (0); # define NWRAP_UNLOCK_ALL do {\ nwrap_mutex_unlock(&nwrap_sp_global_mutex); \ nwrap_mutex_unlock(&nwrap_pw_global_mutex); \ nwrap_mutex_unlock(&nwrap_he_global_mutex); \ nwrap_mutex_unlock(&nwrap_gr_global_mutex); \ nwrap_mutex_unlock(&nwrap_global_mutex); \ nwrap_mutex_unlock(&nwrap_initialized_mutex); \ } while (0); static void nwrap_init(void); enum nwrap_dbglvl_e { NWRAP_LOG_ERROR = 0, NWRAP_LOG_WARN, NWRAP_LOG_DEBUG, NWRAP_LOG_TRACE }; #ifndef HAVE_GETPROGNAME static const char *getprogname(void) { #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME) return program_invocation_short_name; #elif defined(HAVE_GETEXECNAME) return getexecname(); #else return NULL; #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */ } #endif /* HAVE_GETPROGNAME */ static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); # define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__) static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) { char buffer[1024]; va_list va; const char *d; unsigned int lvl = 0; const char *prefix = "NWRAP"; const char *progname = getprogname(); d = getenv("NSS_WRAPPER_DEBUGLEVEL"); if (d != NULL) { lvl = atoi(d); } if (lvl < dbglvl) { return; } va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); switch (dbglvl) { case NWRAP_LOG_ERROR: prefix = "NWRAP_ERROR"; break; case NWRAP_LOG_WARN: prefix = "NWRAP_WARN"; break; case NWRAP_LOG_DEBUG: prefix = "NWRAP_DEBUG"; break; case NWRAP_LOG_TRACE: prefix = "NWRAP_TRACE"; break; } if (progname == NULL) { progname = ""; } fprintf(stderr, "%s[%s (%u)] - %s: %s\n", prefix, progname, (unsigned int)getpid(), func, buffer); } /***************** * LIBC *****************/ #define LIBC_NAME "libc.so" typedef struct passwd *(*__libc_getpwnam)(const char *name); typedef int (*__libc_getpwnam_r)(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); typedef struct passwd *(*__libc_getpwuid)(uid_t uid); typedef int (*__libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); typedef void (*__libc_setpwent)(void); typedef struct passwd *(*__libc_getpwent)(void); #ifdef HAVE_GETPWENT_R # ifdef HAVE_SOLARIS_GETPWENT_R typedef struct passwd *(*__libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen); # else /* HAVE_SOLARIS_GETPWENT_R */ typedef int (*__libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); # endif /* HAVE_SOLARIS_GETPWENT_R */ #endif /* HAVE_GETPWENT_R */ typedef void (*__libc_endpwent)(void); typedef int (*__libc_initgroups)(const char *user, gid_t gid); typedef struct group *(*__libc_getgrnam)(const char *name); typedef int (*__libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result); typedef struct group *(*__libc_getgrgid)(gid_t gid); typedef int (*__libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result); typedef void (*__libc_setgrent)(void); typedef struct group *(*__libc_getgrent)(void); #ifdef HAVE_GETGRENT_R # ifdef HAVE_SOLARIS_GETGRENT_R typedef struct group *(*__libc_getgrent_r)(struct group *group, char *buf, size_t buflen); # else /* HAVE_SOLARIS_GETGRENT_R */ typedef int (*__libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result); # endif /* HAVE_SOLARIS_GETGRENT_R */ #endif /* HAVE_GETGRENT_R */ typedef void (*__libc_endgrent)(void); typedef int (*__libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups); typedef void (*__libc_sethostent)(int stayopen); typedef struct hostent *(*__libc_gethostent)(void); typedef void (*__libc_endhostent)(void); typedef struct hostent *(*__libc_gethostbyname)(const char *name); #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ typedef struct hostent *(*__libc_gethostbyname2)(const char *name, int af); #endif #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ typedef int (*__libc_gethostbyname2_r)(const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #endif typedef struct hostent *(*__libc_gethostbyaddr)(const void *addr, socklen_t len, int type); typedef int (*__libc_getaddrinfo)(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); typedef int (*__libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); typedef int (*__libc_gethostname)(char *name, size_t len); #ifdef HAVE_GETHOSTBYNAME_R typedef int (*__libc_gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #endif #ifdef HAVE_GETHOSTBYADDR_R typedef int (*__libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #endif #define NWRAP_SYMBOL_ENTRY(i) \ union { \ __libc_##i f; \ void *obj; \ } _libc_##i struct nwrap_libc_symbols { NWRAP_SYMBOL_ENTRY(getpwnam); NWRAP_SYMBOL_ENTRY(getpwnam_r); NWRAP_SYMBOL_ENTRY(getpwuid); NWRAP_SYMBOL_ENTRY(getpwuid_r); NWRAP_SYMBOL_ENTRY(setpwent); NWRAP_SYMBOL_ENTRY(getpwent); #ifdef HAVE_GETPWENT_R NWRAP_SYMBOL_ENTRY(getpwent_r); #endif NWRAP_SYMBOL_ENTRY(endpwent); NWRAP_SYMBOL_ENTRY(initgroups); NWRAP_SYMBOL_ENTRY(getgrnam); NWRAP_SYMBOL_ENTRY(getgrnam_r); NWRAP_SYMBOL_ENTRY(getgrgid); NWRAP_SYMBOL_ENTRY(getgrgid_r); NWRAP_SYMBOL_ENTRY(setgrent); NWRAP_SYMBOL_ENTRY(getgrent); #ifdef HAVE_GETGRENT_R NWRAP_SYMBOL_ENTRY(getgrent_r); #endif NWRAP_SYMBOL_ENTRY(endgrent); NWRAP_SYMBOL_ENTRY(getgrouplist); NWRAP_SYMBOL_ENTRY(sethostent); NWRAP_SYMBOL_ENTRY(gethostent); NWRAP_SYMBOL_ENTRY(endhostent); NWRAP_SYMBOL_ENTRY(gethostbyname); #ifdef HAVE_GETHOSTBYNAME_R NWRAP_SYMBOL_ENTRY(gethostbyname_r); #endif #ifdef HAVE_GETHOSTBYNAME2 NWRAP_SYMBOL_ENTRY(gethostbyname2); #endif #ifdef HAVE_GETHOSTBYNAME2_R NWRAP_SYMBOL_ENTRY(gethostbyname2_r); #endif NWRAP_SYMBOL_ENTRY(gethostbyaddr); #ifdef HAVE_GETHOSTBYADDR_R NWRAP_SYMBOL_ENTRY(gethostbyaddr_r); #endif NWRAP_SYMBOL_ENTRY(getaddrinfo); NWRAP_SYMBOL_ENTRY(getnameinfo); NWRAP_SYMBOL_ENTRY(gethostname); }; #undef NWRAP_SYMBOL_ENTRY typedef NSS_STATUS (*__nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_setpwent)(void); typedef NSS_STATUS (*__nss_getpwent_r)(struct passwd *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_endpwent)(void); typedef NSS_STATUS (*__nss_initgroups_dyn)(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); typedef NSS_STATUS (*__nss_getgrnam_r)(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_setgrent)(void); typedef NSS_STATUS (*__nss_getgrent_r)(struct group *result, char *buffer, size_t buflen, int *errnop); typedef NSS_STATUS (*__nss_endgrent)(void); typedef NSS_STATUS (*__nss_gethostbyaddr_r)(const void *addr, socklen_t addrlen, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop); typedef NSS_STATUS (*__nss_gethostbyname2_r)(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop); #define NWRAP_NSS_MODULE_SYMBOL_ENTRY(i) \ union { \ __nss_##i f; \ void *obj; \ } _nss_##i struct nwrap_nss_module_symbols { NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwnam_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwuid_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(setpwent); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getpwent_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(endpwent); NWRAP_NSS_MODULE_SYMBOL_ENTRY(initgroups_dyn); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrnam_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrgid_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(setgrent); NWRAP_NSS_MODULE_SYMBOL_ENTRY(getgrent_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(endgrent); NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyaddr_r); NWRAP_NSS_MODULE_SYMBOL_ENTRY(gethostbyname2_r); }; struct nwrap_backend { const char *name; const char *so_path; void *so_handle; struct nwrap_ops *ops; struct nwrap_nss_module_symbols *symbols; }; struct nwrap_vector; struct nwrap_ops { struct passwd * (*nw_getpwnam)(struct nwrap_backend *b, const char *name); int (*nw_getpwnam_r)(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); struct passwd * (*nw_getpwuid)(struct nwrap_backend *b, uid_t uid); int (*nw_getpwuid_r)(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); void (*nw_setpwent)(struct nwrap_backend *b); struct passwd * (*nw_getpwent)(struct nwrap_backend *b); int (*nw_getpwent_r)(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); void (*nw_endpwent)(struct nwrap_backend *b); int (*nw_initgroups_dyn)(struct nwrap_backend *b, const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); struct group * (*nw_getgrnam)(struct nwrap_backend *b, const char *name); int (*nw_getgrnam_r)(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); struct group * (*nw_getgrgid)(struct nwrap_backend *b, gid_t gid); int (*nw_getgrgid_r)(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); void (*nw_setgrent)(struct nwrap_backend *b); struct group * (*nw_getgrent)(struct nwrap_backend *b); int (*nw_getgrent_r)(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); void (*nw_endgrent)(struct nwrap_backend *b); struct hostent *(*nw_gethostbyaddr)(struct nwrap_backend *b, const void *addr, socklen_t len, int type); struct hostent *(*nw_gethostbyname)(struct nwrap_backend *b, const char *name); struct hostent *(*nw_gethostbyname2)(struct nwrap_backend *b, const char *name, int af); int (*nw_gethostbyname2_r)(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, char *buf, size_t buflen, struct hostent **hedstp); }; /* Public prototypes */ bool nss_wrapper_enabled(void); bool nss_wrapper_shadow_enabled(void); bool nss_wrapper_hosts_enabled(void); /* prototypes for files backend */ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, const char *name); static int nwrap_files_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b, uid_t uid); static int nwrap_files_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_files_setpwent(struct nwrap_backend *b); static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b); static int nwrap_files_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_files_endpwent(struct nwrap_backend *b); static int nwrap_files_initgroups_dyn(struct nwrap_backend *b, const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, const char *name); static int nwrap_files_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_files_getgrgid(struct nwrap_backend *b, gid_t gid); static int nwrap_files_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_files_setgrent(struct nwrap_backend *b); static struct group *nwrap_files_getgrent(struct nwrap_backend *b); static int nwrap_files_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_files_endgrent(struct nwrap_backend *b); static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b, const void *addr, socklen_t len, int type); static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b, const char *name); #ifdef HAVE_GETHOSTBYNAME2 static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b, const char *name, int af); #endif /* HAVE_GETHOSTBYNAME2 */ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, char *buf, size_t buflen, struct hostent **hedstp); /* prototypes for module backend */ static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b); static int nwrap_module_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, const char *name); static int nwrap_module_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, uid_t uid); static int nwrap_module_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp); static void nwrap_module_setpwent(struct nwrap_backend *b); static void nwrap_module_endpwent(struct nwrap_backend *b); static struct group *nwrap_module_getgrent(struct nwrap_backend *b); static int nwrap_module_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, const char *name); static int nwrap_module_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, gid_t gid); static int nwrap_module_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp); static void nwrap_module_setgrent(struct nwrap_backend *b); static void nwrap_module_endgrent(struct nwrap_backend *b); static int nwrap_module_initgroups_dyn(struct nwrap_backend *b, const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b, const void *addr, socklen_t len, int type); static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b, const char *name); static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b, const char *name, int af); static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, char *buf, size_t buflen, struct hostent **hedstp); struct nwrap_ops nwrap_files_ops = { .nw_getpwnam = nwrap_files_getpwnam, .nw_getpwnam_r = nwrap_files_getpwnam_r, .nw_getpwuid = nwrap_files_getpwuid, .nw_getpwuid_r = nwrap_files_getpwuid_r, .nw_setpwent = nwrap_files_setpwent, .nw_getpwent = nwrap_files_getpwent, .nw_getpwent_r = nwrap_files_getpwent_r, .nw_endpwent = nwrap_files_endpwent, .nw_initgroups_dyn = nwrap_files_initgroups_dyn, .nw_getgrnam = nwrap_files_getgrnam, .nw_getgrnam_r = nwrap_files_getgrnam_r, .nw_getgrgid = nwrap_files_getgrgid, .nw_getgrgid_r = nwrap_files_getgrgid_r, .nw_setgrent = nwrap_files_setgrent, .nw_getgrent = nwrap_files_getgrent, .nw_getgrent_r = nwrap_files_getgrent_r, .nw_endgrent = nwrap_files_endgrent, .nw_gethostbyaddr = nwrap_files_gethostbyaddr, .nw_gethostbyname = nwrap_files_gethostbyname, #ifdef HAVE_GETHOSTBYNAME2 .nw_gethostbyname2 = nwrap_files_gethostbyname2, #endif /* HAVE_GETHOSTBYNAME2 */ .nw_gethostbyname2_r = nwrap_files_gethostbyname2_r, }; struct nwrap_ops nwrap_module_ops = { .nw_getpwnam = nwrap_module_getpwnam, .nw_getpwnam_r = nwrap_module_getpwnam_r, .nw_getpwuid = nwrap_module_getpwuid, .nw_getpwuid_r = nwrap_module_getpwuid_r, .nw_setpwent = nwrap_module_setpwent, .nw_getpwent = nwrap_module_getpwent, .nw_getpwent_r = nwrap_module_getpwent_r, .nw_endpwent = nwrap_module_endpwent, .nw_initgroups_dyn = nwrap_module_initgroups_dyn, .nw_getgrnam = nwrap_module_getgrnam, .nw_getgrnam_r = nwrap_module_getgrnam_r, .nw_getgrgid = nwrap_module_getgrgid, .nw_getgrgid_r = nwrap_module_getgrgid_r, .nw_setgrent = nwrap_module_setgrent, .nw_getgrent = nwrap_module_getgrent, .nw_getgrent_r = nwrap_module_getgrent_r, .nw_endgrent = nwrap_module_endgrent, .nw_gethostbyaddr = nwrap_module_gethostbyaddr, .nw_gethostbyname = nwrap_module_gethostbyname, .nw_gethostbyname2 = nwrap_module_gethostbyname2, .nw_gethostbyname2_r = nwrap_module_gethostbyname2_r, }; struct nwrap_libc { void *handle; void *nsl_handle; void *sock_handle; struct nwrap_libc_symbols symbols; }; struct nwrap_main { size_t num_backends; struct nwrap_backend *backends; struct nwrap_libc *libc; }; static struct nwrap_main *nwrap_main_global; static struct nwrap_main __nwrap_main_global; /* * PROTOTYPES */ static int nwrap_convert_he_ai(const struct hostent *he, unsigned short port, const struct addrinfo *hints, struct addrinfo **pai, bool skip_canonname); #ifdef HAVE_GETGROUPLIST static int nwrap_getgrouplist(const char *user, gid_t group, long int *size, gid_t **groupsp, long int limit); #endif /* * VECTORS */ #define DEFAULT_VECTOR_CAPACITY 16 struct nwrap_vector { void **items; size_t count; size_t capacity; }; /* Macro returns pointer to first element of vector->items array. * * nwrap_vector is used as a memory backend which take care of * memory allocations and other stuff like memory growing. * nwrap_vectors should not be considered as some abstract structures. * On this level, vectors are more handy than direct realloc/malloc * calls. * * nwrap_vector->items is array inside nwrap_vector which can be * directly pointed by libc structure assembled by cwrap itself. * * EXAMPLE: * * 1) struct hostent contains char **h_addr_list element. * 2) nwrap_vector holds array of pointers to addresses. * It's easier to use vector to store results of * file parsing etc. * * Now, pretend that cwrap assembled struct hostent and * we need to set h_addr_list to point to nwrap_vector. * Idea behind is to shield users from internal nwrap_vector * implementation. * (Yes, not fully - array terminated by NULL is needed because * it's result expected by libc function caller.) * * * CODE EXAMPLE: * * struct hostent he; * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector)); * ... don't care about failed allocation now ... * * ... fill nwrap vector ... * * struct hostent he; * he.h_addr_list = nwrap_vector_head(vector); * */ #define nwrap_vector_head(vect) ((void *)((vect)->items)) #define nwrap_vector_foreach(item, vect, iter) \ for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \ item != NULL; \ (item) = (vect).items[++iter]) #define nwrap_vector_is_initialized(vector) ((vector)->items != NULL) static inline bool nwrap_vector_init(struct nwrap_vector *const vector) { if (vector == NULL) { return false; } /* count is initialized by ZERO_STRUCTP */ ZERO_STRUCTP(vector); vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1)); if (vector->items == NULL) { return false; } vector->capacity = DEFAULT_VECTOR_CAPACITY; memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1)); return true; } static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item) { assert (vector != NULL); if (vector->items == NULL) { nwrap_vector_init(vector); } if (vector->count == vector->capacity) { /* Items array _MUST_ be NULL terminated because it's passed * as result to caller which expect NULL terminated array from libc. */ void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1)); if (items == NULL) { return false; } vector->items = items; /* Don't count ending NULL to capacity */ vector->capacity *= 2; } vector->items[vector->count] = item; vector->count += 1; vector->items[vector->count] = NULL; return true; } static bool nwrap_vector_merge(struct nwrap_vector *dst, struct nwrap_vector *src) { void **dst_items = NULL; size_t count; if (src->count == 0) { return true; } count = dst->count + src->count; /* We don't need reallocation if we have enough capacity. */ if (src->count > (dst->capacity - dst->count)) { dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *)); if (dst_items == NULL) { return false; } dst->items = dst_items; dst->capacity = count; } memcpy((void *)(((long *)dst->items) + dst->count), src->items, src->count * sizeof(void *)); dst->count = count; return true; } struct nwrap_cache { const char *path; int fd; FILE *fp; struct stat st; void *private_data; struct nwrap_vector lines; bool (*parse_line)(struct nwrap_cache *, char *line); void (*unload)(struct nwrap_cache *); }; /* passwd */ struct nwrap_pw { struct nwrap_cache *cache; struct passwd *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_pw; struct nwrap_pw nwrap_pw_global; static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_pw_unload(struct nwrap_cache *nwrap); /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) struct nwrap_sp { struct nwrap_cache *cache; struct spwd *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_sp; struct nwrap_sp nwrap_sp_global; static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_sp_unload(struct nwrap_cache *nwrap); #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* group */ struct nwrap_gr { struct nwrap_cache *cache; struct group *list; int num; int idx; }; struct nwrap_cache __nwrap_cache_gr; struct nwrap_gr nwrap_gr_global; /* hosts */ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_he_unload(struct nwrap_cache *nwrap); struct nwrap_addrdata { unsigned char host_addr[16]; /* IPv4 or IPv6 address */ }; static size_t max_hostents = 100; struct nwrap_entdata { struct nwrap_addrdata addr; struct hostent ht; struct nwrap_vector nwrap_addrdata; ssize_t aliases_count; }; struct nwrap_entlist { struct nwrap_entlist *next; struct nwrap_entdata *ed; }; struct nwrap_he { struct nwrap_cache *cache; struct nwrap_vector entries; struct nwrap_vector lists; int num; int idx; }; static struct nwrap_cache __nwrap_cache_he; static struct nwrap_he nwrap_he_global; /********************************************************* * NWRAP PROTOTYPES *********************************************************/ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_gr_unload(struct nwrap_cache *nwrap); #if ! defined(HAVE_CONSTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_INIT) /* xlC and other oldschool compilers support (only) this */ #pragma init (nwrap_constructor) #endif void nwrap_constructor(void) CONSTRUCTOR_ATTRIBUTE; #if ! defined(HAVE_DESTRUCTOR_ATTRIBUTE) && defined(HAVE_PRAGMA_FINI) #pragma fini (nwrap_destructor) #endif void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE; /********************************************************* * NWRAP LIBC LOADER FUNCTIONS *********************************************************/ enum nwrap_lib { NWRAP_LIBC, NWRAP_LIBNSL, NWRAP_LIBSOCKET, }; static const char *nwrap_str_lib(enum nwrap_lib lib) { switch (lib) { case NWRAP_LIBC: return "libc"; case NWRAP_LIBNSL: return "libnsl"; case NWRAP_LIBSOCKET: return "libsocket"; } /* Compiler would warn us about unhandled enum value if we get here */ return "unknown"; } static void *nwrap_load_lib_handle(enum nwrap_lib lib) { int flags = RTLD_LAZY; void *handle = NULL; int i; #ifdef RTLD_DEEPBIND const char *env_preload = getenv("LD_PRELOAD"); const char *env_deepbind = getenv("NSS_WRAPPER_DISABLE_DEEPBIND"); bool enable_deepbind = true; /* Don't do a deepbind if we run with libasan */ if (env_preload != NULL && strlen(env_preload) < 1024) { const char *p = strstr(env_preload, "libasan.so"); if (p != NULL) { enable_deepbind = false; } } if (env_deepbind != NULL && strlen(env_deepbind) >= 1) { enable_deepbind = false; } if (enable_deepbind) { flags |= RTLD_DEEPBIND; } #endif switch (lib) { case NWRAP_LIBNSL: #ifdef HAVE_LIBNSL handle = nwrap_main_global->libc->nsl_handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libnsl.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->nsl_handle = handle; } break; #endif /* FALL TROUGH */ case NWRAP_LIBSOCKET: #ifdef HAVE_LIBSOCKET handle = nwrap_main_global->libc->sock_handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libsocket.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->sock_handle = handle; } break; #endif /* FALL TROUGH */ case NWRAP_LIBC: handle = nwrap_main_global->libc->handle; if (handle == NULL) { for (i = 10; i >= 0; i--) { char soname[256] = {0}; snprintf(soname, sizeof(soname), "libc.so.%d", i); handle = dlopen(soname, flags); if (handle != NULL) { break; } } nwrap_main_global->libc->handle = handle; } break; } if (handle == NULL) { #ifdef RTLD_NEXT handle = nwrap_main_global->libc->handle = nwrap_main_global->libc->sock_handle = nwrap_main_global->libc->nsl_handle = RTLD_NEXT; #else NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to dlopen library: %s\n", dlerror()); exit(-1); #endif } return handle; } static void *_nwrap_bind_symbol(enum nwrap_lib lib, const char *fn_name) { void *handle; void *func; nwrap_init(); handle = nwrap_load_lib_handle(lib); func = dlsym(handle, fn_name); if (func == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to find %s: %s\n", fn_name, dlerror()); exit(-1); } NWRAP_LOG(NWRAP_LOG_TRACE, "Loaded %s from %s", fn_name, nwrap_str_lib(lib)); return func; } #define nwrap_mutex_lock(m) _nwrap_mutex_lock(m, #m, __func__, __LINE__) static void _nwrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) { int ret; ret = pthread_mutex_lock(mutex); if (ret != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s", getpid(), getppid(), caller, line, name, strerror(ret)); abort(); } } #define nwrap_mutex_unlock(m) _nwrap_mutex_unlock(m, #m, __func__, __LINE__) static void _nwrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) { int ret; ret = pthread_mutex_unlock(mutex); if (ret != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s", getpid(), getppid(), caller, line, name, strerror(ret)); abort(); } } #define nwrap_bind_symbol_libc(sym_name) \ if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \ nwrap_main_global->libc->symbols._libc_##sym_name.obj = \ _nwrap_bind_symbol(NWRAP_LIBC, #sym_name); \ } \ #define nwrap_bind_symbol_libc_posix(sym_name) \ if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \ nwrap_main_global->libc->symbols._libc_##sym_name.obj = \ _nwrap_bind_symbol(NWRAP_LIBC, "__posix_" #sym_name); \ } \ #define nwrap_bind_symbol_libnsl(sym_name) \ if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \ nwrap_main_global->libc->symbols._libc_##sym_name.obj = \ _nwrap_bind_symbol(NWRAP_LIBNSL, #sym_name); \ } \ #define nwrap_bind_symbol_libsocket(sym_name) \ if (nwrap_main_global->libc->symbols._libc_##sym_name.obj == NULL) { \ nwrap_main_global->libc->symbols._libc_##sym_name.obj = \ _nwrap_bind_symbol(NWRAP_LIBSOCKET, #sym_name); \ } \ static void nwrap_bind_symbol_all(void); /* INTERNAL HELPER FUNCTIONS */ static void nwrap_lines_unload(struct nwrap_cache *const nwrap) { size_t p; void *item; nwrap_vector_foreach(item, nwrap->lines, p) { /* Maybe some vectors were merged ... */ SAFE_FREE(item); } SAFE_FREE(nwrap->lines.items); ZERO_STRUCTP(&nwrap->lines); } /* * IMPORTANT * * Functions expeciall from libc need to be loaded individually, you can't load * all at once or gdb will segfault at startup. The same applies to valgrind and * has probably something todo with with the linker. * So we need load each function at the point it is called the first time. */ static struct passwd *libc_getpwnam(const char *name) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwnam.f(name); } #ifdef HAVE_GETPWNAM_R static int libc_getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwnam_r.f(name, pwd, buf, buflen, result); } #endif static struct passwd *libc_getpwuid(uid_t uid) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwuid.f(uid); } #ifdef HAVE_GETPWUID_R static int libc_getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwuid_r.f(uid, pwd, buf, buflen, result); } #endif static inline void str_tolower(char *dst, char *src) { register char *src_tmp = src; register char *dst_tmp = dst; while (*src_tmp != '\0') { *dst_tmp = tolower(*src_tmp); ++src_tmp; ++dst_tmp; } } static bool str_tolower_copy(char **dst_name, const char *const src_name) { char *h_name_lower; if ((dst_name == NULL) || (src_name == NULL)) { return false; } h_name_lower = strdup(src_name); if (h_name_lower == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup"); return false; } str_tolower(h_name_lower, h_name_lower); *dst_name = h_name_lower; return true; } static void libc_setpwent(void) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_setpwent.f(); } static struct passwd *libc_getpwent(void) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwent.f(); } #ifdef HAVE_GETPWENT_R # ifdef HAVE_SOLARIS_GETPWENT_R static struct passwd *libc_getpwent_r(struct passwd *pwdst, char *buf, int buflen) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst, buf, buflen); } # else /* HAVE_SOLARIS_GETPWENT_R */ static int libc_getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getpwent_r.f(pwdst, buf, buflen, pwdstp); } # endif /* HAVE_SOLARIS_GETPWENT_R */ #endif /* HAVE_GETPWENT_R */ static void libc_endpwent(void) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_endpwent.f(); } static int libc_initgroups(const char *user, gid_t gid) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_initgroups.f(user, gid); } static struct group *libc_getgrnam(const char *name) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrnam.f(name); } #ifdef HAVE_GETGRNAM_R static int libc_getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrnam_r.f(name, grp, buf, buflen, result); } #endif static struct group *libc_getgrgid(gid_t gid) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrgid.f(gid); } #ifdef HAVE_GETGRGID_R static int libc_getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrgid_r.f(gid, grp, buf, buflen, result); } #endif static void libc_setgrent(void) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_setgrent.f(); } static struct group *libc_getgrent(void) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrent.f(); } #ifdef HAVE_GETGRENT_R # ifdef HAVE_SOLARIS_GETGRENT_R static struct group *libc_getgrent_r(struct group *group, char *buf, size_t buflen) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group, buf, buflen); } # else /* HAVE_SOLARIS_GETGRENT_R */ static int libc_getgrent_r(struct group *group, char *buf, size_t buflen, struct group **result) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrent_r.f(group, buf, buflen, result); } # endif /* HAVE_SOLARIS_GETGRENT_R */ #endif /* HAVE_GETGRENT_R */ static void libc_endgrent(void) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_endgrent.f(); } #ifdef HAVE_GETGROUPLIST static int libc_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getgrouplist.f(user, group, groups, ngroups); } #endif static void libc_sethostent(int stayopen) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_sethostent.f(stayopen); } static struct hostent *libc_gethostent(void) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostent.f(); } static void libc_endhostent(void) { nwrap_bind_symbol_all(); nwrap_main_global->libc->symbols._libc_endhostent.f(); } static struct hostent *libc_gethostbyname(const char *name) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyname.f(name); } #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ static struct hostent *libc_gethostbyname2(const char *name, int af) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyname2.f(name, af); } #endif #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ static int libc_gethostbyname2_r(const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyname2_r.f(name, af, ret, buf, buflen, result, h_errnop); } #endif static struct hostent *libc_gethostbyaddr(const void *addr, socklen_t len, int type) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyaddr.f(addr, len, type); } static int libc_gethostname(char *name, size_t len) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostname.f(name, len); } #ifdef HAVE_GETHOSTBYNAME_R static int libc_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyname_r.f(name, ret, buf, buflen, result, h_errnop); } #endif #ifdef HAVE_GETHOSTBYADDR_R static int libc_gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_gethostbyaddr_r.f(addr, len, type, ret, buf, buflen, result, h_errnop); } #endif static int libc_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getaddrinfo.f(node, service, hints, res); } static int libc_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { nwrap_bind_symbol_all(); return nwrap_main_global->libc->symbols._libc_getnameinfo.f(sa, salen, host, hostlen, serv, servlen, flags); } static void __nwrap_bind_symbol_all_once(void) { nwrap_bind_symbol_libc(getpwnam); #ifdef HAVE_GETPWNAM_R # ifdef HAVE___POSIX_GETPWNAM_R nwrap_bind_symbol_libc_posix(getpwnam_r); # else nwrap_bind_symbol_libc(getpwnam_r); # endif #endif nwrap_bind_symbol_libc(getpwuid); #ifdef HAVE_GETPWUID_R # ifdef HAVE___POSIX_GETPWUID_R nwrap_bind_symbol_libc_posix(getpwuid_r); # else nwrap_bind_symbol_libc(getpwuid_r); # endif #endif nwrap_bind_symbol_libc(setpwent); nwrap_bind_symbol_libc(getpwent); #ifdef HAVE_GETPWENT_R nwrap_bind_symbol_libc(getpwent_r); #endif nwrap_bind_symbol_libc(endpwent); nwrap_bind_symbol_libc(initgroups); nwrap_bind_symbol_libc(getgrnam); #ifdef HAVE_GETGRNAM_R # ifdef HAVE___POSIX_GETGRNAM_R nwrap_bind_symbol_libc_posix(getgrnam_r); # else nwrap_bind_symbol_libc(getgrnam_r); # endif #endif nwrap_bind_symbol_libc(getgrgid); #ifdef HAVE_GETGRGID_R # ifdef HAVE___POSIX_GETGRGID_R nwrap_bind_symbol_libc_posix(getgrgid_r); # else nwrap_bind_symbol_libc(getgrgid_r); # endif #endif nwrap_bind_symbol_libc(setgrent); nwrap_bind_symbol_libc(getgrent); nwrap_bind_symbol_libc(getgrent_r); nwrap_bind_symbol_libc(endgrent); nwrap_bind_symbol_libc(getgrouplist); nwrap_bind_symbol_libnsl(sethostent); nwrap_bind_symbol_libnsl(gethostent); nwrap_bind_symbol_libnsl(endhostent); nwrap_bind_symbol_libnsl(gethostbyname); #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ nwrap_bind_symbol_libnsl(gethostbyname2); #endif #ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ nwrap_bind_symbol_libnsl(gethostbyname2_r); #endif nwrap_bind_symbol_libnsl(gethostbyaddr); nwrap_bind_symbol_libnsl(gethostname); #ifdef HAVE_GETHOSTBYNAME_R nwrap_bind_symbol_libnsl(gethostbyname_r); #endif #ifdef HAVE_GETHOSTBYADDR_R nwrap_bind_symbol_libnsl(gethostbyaddr_r); #endif nwrap_bind_symbol_libsocket(getaddrinfo); nwrap_bind_symbol_libsocket(getnameinfo); } static void nwrap_bind_symbol_all(void) { static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT; pthread_once(&all_symbol_binding_once, __nwrap_bind_symbol_all_once); } /********************************************************* * NWRAP NSS MODULE LOADER FUNCTIONS *********************************************************/ static void *_nwrap_bind_nss_module_symbol(struct nwrap_backend *b, const char *fn_name) { void *res = NULL; char *s = NULL; int rc; if (b->so_handle == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "No handle"); return NULL; } rc = asprintf(&s, "_nss_%s_%s", b->name, fn_name); if (rc == -1) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return NULL; } res = dlsym(b->so_handle, s); if (res == NULL) { NWRAP_LOG(NWRAP_LOG_WARN, "Cannot find function %s in %s", s, b->so_path); } SAFE_FREE(s); return res; } #define nwrap_nss_module_bind_symbol(sym_name) \ if (symbols->_nss_##sym_name.obj == NULL) { \ symbols->_nss_##sym_name.obj = \ _nwrap_bind_nss_module_symbol(b, #sym_name); \ } #define nwrap_nss_module_bind_symbol2(sym_name, alt_name) \ if (symbols->_nss_##sym_name.obj == NULL) { \ symbols->_nss_##sym_name.obj = \ _nwrap_bind_nss_module_symbol(b, #alt_name); \ } static struct nwrap_nss_module_symbols * nwrap_bind_nss_module_symbols(struct nwrap_backend *b) { struct nwrap_nss_module_symbols *symbols; if (!b->so_handle) { return NULL; } symbols = calloc(1, sizeof(struct nwrap_nss_module_symbols)); if (symbols == NULL) { return NULL; } nwrap_nss_module_bind_symbol(getpwnam_r); nwrap_nss_module_bind_symbol(getpwuid_r); nwrap_nss_module_bind_symbol(setpwent); nwrap_nss_module_bind_symbol(getpwent_r); nwrap_nss_module_bind_symbol(endpwent); nwrap_nss_module_bind_symbol(initgroups_dyn); nwrap_nss_module_bind_symbol(getgrnam_r); nwrap_nss_module_bind_symbol(getgrgid_r); nwrap_nss_module_bind_symbol(setgrent); nwrap_nss_module_bind_symbol(getgrent_r); nwrap_nss_module_bind_symbol(endgrent); nwrap_nss_module_bind_symbol(gethostbyaddr_r); nwrap_nss_module_bind_symbol(gethostbyname2_r); return symbols; } static void *nwrap_load_module(const char *so_path) { void *h; if (!so_path || !strlen(so_path)) { return NULL; } h = dlopen(so_path, RTLD_LAZY); if (!h) { NWRAP_LOG(NWRAP_LOG_ERROR, "Cannot open shared library %s", so_path); return NULL; } return h; } static bool nwrap_module_init(const char *name, struct nwrap_ops *ops, const char *so_path, size_t *num_backends, struct nwrap_backend **backends) { struct nwrap_backend *b = NULL; size_t n = *num_backends + 1; b = realloc(*backends, sizeof(struct nwrap_backend) * n); if (b == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } *backends = b; b = &((*backends)[*num_backends]); *b = (struct nwrap_backend) { .name = name, .ops = ops, .so_path = so_path, }; if (so_path != NULL) { b->so_handle = nwrap_load_module(so_path); b->symbols = nwrap_bind_nss_module_symbols(b); if (b->symbols == NULL) { return false; } } *num_backends = n; return true; } static void nwrap_libc_init(struct nwrap_main *r) { r->libc = calloc(1, sizeof(struct nwrap_libc)); if (r->libc == NULL) { printf("Failed to allocate memory for libc"); exit(-1); } } static void nwrap_backend_init(struct nwrap_main *r) { const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH"); const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX"); r->num_backends = 0; r->backends = NULL; if (!nwrap_module_init("files", &nwrap_files_ops, NULL, &r->num_backends, &r->backends)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize 'files' backend"); return; } if (module_so_path != NULL && module_so_path[0] != '\0' && module_fn_name != NULL && module_fn_name[0] != '\0') { if (!nwrap_module_init(module_fn_name, &nwrap_module_ops, module_so_path, &r->num_backends, &r->backends)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize '%s' backend", module_fn_name); return; } } } static int _nss_wrapper_init_mutex(pthread_mutex_t *m, const char *name) { pthread_mutexattr_t ma; bool need_destroy = false; int ret = 0; #define __CHECK(cmd) do { \ ret = cmd; \ if (ret != 0) { \ NWRAP_LOG(NWRAP_LOG_ERROR, \ "%s: %s - failed %d", \ name, #cmd, ret); \ goto done; \ } \ } while(0) *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; __CHECK(pthread_mutexattr_init(&ma)); need_destroy = true; __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK)); __CHECK(pthread_mutex_init(m, &ma)); done: if (need_destroy) { pthread_mutexattr_destroy(&ma); } return ret; } static void nwrap_init(void) { const char *env; char *endptr; size_t max_hostents_tmp; int ok; nwrap_mutex_lock(&nwrap_initialized_mutex); if (nwrap_initialized) { nwrap_mutex_unlock(&nwrap_initialized_mutex); return; } /* * Still holding nwrap_initialized lock here. * We don't use NWRAP_(UN)LOCK_ALL macros here because we * want to avoid overhead when other threads do their job. */ nwrap_mutex_lock(&nwrap_global_mutex); nwrap_mutex_lock(&nwrap_gr_global_mutex); nwrap_mutex_lock(&nwrap_he_global_mutex); nwrap_mutex_lock(&nwrap_pw_global_mutex); nwrap_mutex_lock(&nwrap_sp_global_mutex); nwrap_initialized = true; env = getenv("NSS_WRAPPER_MAX_HOSTENTS"); if (env != NULL) { max_hostents_tmp = (size_t)strtoul(env, &endptr, 10); if ((*env == '\0') || (*endptr != '\0') || (max_hostents_tmp == 0)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Error parsing NSS_WRAPPER_MAX_HOSTENTS " "value or value is too small. " "Using default value: %lu.", (unsigned long)max_hostents); } else { max_hostents = max_hostents_tmp; } } /* Initialize hash table */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Initializing hash table of size %lu items.", (unsigned long)max_hostents); ok = hcreate(max_hostents); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table"); exit(-1); } nwrap_main_global = &__nwrap_main_global; nwrap_libc_init(nwrap_main_global); nwrap_backend_init(nwrap_main_global); /* passwd */ nwrap_pw_global.cache = &__nwrap_cache_pw; nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD"); nwrap_pw_global.cache->fp = NULL; nwrap_pw_global.cache->fd = -1; nwrap_pw_global.cache->private_data = &nwrap_pw_global; nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line; nwrap_pw_global.cache->unload = nwrap_pw_unload; /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) nwrap_sp_global.cache = &__nwrap_cache_sp; nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW"); nwrap_sp_global.cache->fp = NULL; nwrap_sp_global.cache->fd = -1; nwrap_sp_global.cache->private_data = &nwrap_sp_global; nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line; nwrap_sp_global.cache->unload = nwrap_sp_unload; #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* group */ nwrap_gr_global.cache = &__nwrap_cache_gr; nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP"); nwrap_gr_global.cache->fp = NULL; nwrap_gr_global.cache->fd = -1; nwrap_gr_global.cache->private_data = &nwrap_gr_global; nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line; nwrap_gr_global.cache->unload = nwrap_gr_unload; /* hosts */ nwrap_he_global.cache = &__nwrap_cache_he; nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS"); nwrap_he_global.cache->fp = NULL; nwrap_he_global.cache->fd = -1; nwrap_he_global.cache->private_data = &nwrap_he_global; nwrap_he_global.cache->parse_line = nwrap_he_parse_line; nwrap_he_global.cache->unload = nwrap_he_unload; /* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */ nwrap_mutex_unlock(&nwrap_sp_global_mutex); nwrap_mutex_unlock(&nwrap_pw_global_mutex); nwrap_mutex_unlock(&nwrap_he_global_mutex); nwrap_mutex_unlock(&nwrap_gr_global_mutex); nwrap_mutex_unlock(&nwrap_global_mutex); nwrap_mutex_unlock(&nwrap_initialized_mutex); } bool nss_wrapper_enabled(void) { nwrap_init(); if (nwrap_pw_global.cache->path == NULL || nwrap_pw_global.cache->path[0] == '\0') { return false; } if (nwrap_gr_global.cache->path == NULL || nwrap_gr_global.cache->path[0] == '\0') { return false; } return true; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) bool nss_wrapper_shadow_enabled(void) { nwrap_init(); if (nwrap_sp_global.cache->path == NULL || nwrap_sp_global.cache->path[0] == '\0') { return false; } return true; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ bool nss_wrapper_hosts_enabled(void) { nwrap_init(); if (nwrap_he_global.cache->path == NULL || nwrap_he_global.cache->path[0] == '\0') { return false; } return true; } static bool nwrap_hostname_enabled(void) { nwrap_init(); if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) { return false; } return true; } static bool nwrap_parse_file(struct nwrap_cache *nwrap) { char *line = NULL; ssize_t n; /* Unused but getline needs it */ size_t len; bool ok; if (nwrap->st.st_size == 0) { NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0"); return true; } /* Support for 32-bit system I guess */ if (nwrap->st.st_size > INT32_MAX) { NWRAP_LOG(NWRAP_LOG_ERROR, "Size[%u] larger than INT32_MAX", (unsigned)nwrap->st.st_size); return false; } rewind(nwrap->fp); do { n = getline(&line, &len, nwrap->fp); if (n < 0) { SAFE_FREE(line); if (feof(nwrap->fp)) { break; } NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to read line from file: %s", nwrap->path); return false; } if (line[n - 1] == '\n') { line[n - 1] = '\0'; } if (line[0] == '\0') { SAFE_FREE(line); continue; } ok = nwrap->parse_line(nwrap, line); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to parse line file: %s", line); SAFE_FREE(line); return false; } /* Line is parsed without issues so add it to list */ ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add line to vector"); return false; } /* This forces getline to allocate new memory for line. */ line = NULL; } while (!feof(nwrap->fp)); return true; } static void nwrap_files_cache_unload(struct nwrap_cache *nwrap) { nwrap->unload(nwrap); nwrap_lines_unload(nwrap); } static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap) { struct stat st; int ret; bool ok; bool retried = false; assert(nwrap != NULL); reopen: if (nwrap->fd < 0) { nwrap->fp = fopen(nwrap->path, "re"); if (nwrap->fp == NULL) { nwrap->fd = -1; NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to open '%s' readonly %d:%s", nwrap->path, nwrap->fd, strerror(errno)); return false; } nwrap->fd = fileno(nwrap->fp); NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path); } ret = fstat(nwrap->fd, &st); if (ret != 0 && errno == EBADF && retried == false) { /* maybe something closed the fd on our behalf */ NWRAP_LOG(NWRAP_LOG_TRACE, "fstat(%s) - %d:%s - reopen", nwrap->path, ret, strerror(errno)); retried = true; memset(&nwrap->st, 0, sizeof(nwrap->st)); fclose(nwrap->fp); nwrap->fp = NULL; nwrap->fd = -1; goto reopen; } else if (ret != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "fstat(%s) - %d:%s", nwrap->path, ret, strerror(errno)); fclose(nwrap->fp); nwrap->fp = NULL; nwrap->fd = -1; return false; } if (retried == false && st.st_nlink == 0) { /* maybe someone has replaced the file... */ NWRAP_LOG(NWRAP_LOG_TRACE, "st_nlink == 0, reopen %s", nwrap->path); retried = true; memset(&nwrap->st, 0, sizeof(nwrap->st)); fclose(nwrap->fp); nwrap->fp = NULL; nwrap->fd = -1; goto reopen; } if (st.st_mtime == nwrap->st.st_mtime) { NWRAP_LOG(NWRAP_LOG_TRACE, "st_mtime[%u] hasn't changed, skip reload", (unsigned)st.st_mtime); return true; } NWRAP_LOG(NWRAP_LOG_TRACE, "st_mtime has changed [%u] => [%u], start reload", (unsigned)st.st_mtime, (unsigned)nwrap->st.st_mtime); nwrap->st = st; nwrap_files_cache_unload(nwrap); ok = nwrap_parse_file(nwrap); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path); nwrap_files_cache_unload(nwrap); return false; } NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path); return true; } /* * the caller has to call nwrap_unload() on failure */ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_pw *nwrap_pw; char *c; char *p; char *e; struct passwd *pw; size_t list_size; nwrap_pw = (struct nwrap_pw *)nwrap->private_data; list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1); pw = (struct passwd *)realloc(nwrap_pw->list, list_size); if (!pw) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%u) failed", (unsigned)list_size); return false; } nwrap_pw->list = pw; pw = &nwrap_pw->list[nwrap_pw->num]; c = line; /* name */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_name = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name); /* password */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_passwd = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd); /* uid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; pw->pw_uid = (uid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid); /* gid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; pw->pw_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid); #ifdef HAVE_STRUCT_PASSWD_PW_CLASS pw->pw_class = discard_const_p(char, ""); NWRAP_LOG(NWRAP_LOG_TRACE, "class[%s]", pw->pw_class); #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */ #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE pw->pw_change = 0; NWRAP_LOG(NWRAP_LOG_TRACE, "change[%lu]", (unsigned long)pw->pw_change); #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */ #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE pw->pw_expire = 0; NWRAP_LOG(NWRAP_LOG_TRACE, "expire[%lu]", (unsigned long)pw->pw_expire); #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */ /* gecos */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; pw->pw_gecos = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos); /* dir */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c); return false; } *p = '\0'; p++; pw->pw_dir = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir); /* shell */ pw->pw_shell = c; NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell); NWRAP_LOG(NWRAP_LOG_DEBUG, "Added user[%s:%s:%u:%u:%s:%s:%s]", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell); nwrap_pw->num++; return true; } static void nwrap_pw_unload(struct nwrap_cache *nwrap) { struct nwrap_pw *nwrap_pw; nwrap_pw = (struct nwrap_pw *)nwrap->private_data; SAFE_FREE(nwrap_pw->list); nwrap_pw->num = 0; nwrap_pw->idx = 0; } static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst, char *buf, size_t buflen, struct passwd **dstp) { char *first; char *last; off_t ofs; first = src->pw_name; last = src->pw_shell; while (*last) last++; ofs = PTR_DIFF(last + 1, first); if (ofs > (off_t) buflen) { return ERANGE; } memcpy(buf, first, ofs); ofs = PTR_DIFF(src->pw_name, first); dst->pw_name = buf + ofs; ofs = PTR_DIFF(src->pw_passwd, first); dst->pw_passwd = buf + ofs; dst->pw_uid = src->pw_uid; dst->pw_gid = src->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_CLASS ofs = PTR_DIFF(src->pw_class, first); dst->pw_class = buf + ofs; #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */ #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE dst->pw_change = 0; #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */ #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE dst->pw_expire = 0; #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */ ofs = PTR_DIFF(src->pw_gecos, first); dst->pw_gecos = buf + ofs; ofs = PTR_DIFF(src->pw_dir, first); dst->pw_dir = buf + ofs; ofs = PTR_DIFF(src->pw_shell, first); dst->pw_shell = buf + ofs; if (dstp) { *dstp = dst; } return 0; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_sp *nwrap_sp; struct spwd *sp; size_t list_size; char *c; char *e; char *p; nwrap_sp = (struct nwrap_sp *)nwrap->private_data; list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1); sp = (struct spwd *)realloc(nwrap_sp->list, list_size); if (sp == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%u) failed", (unsigned)list_size); return false; } nwrap_sp->list = sp; sp = &nwrap_sp->list[nwrap_sp->num]; c = line; /* name */ p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "name -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_namp = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp); /* pwd */ p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "pwd -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_pwdp = c; c = p; /* lstchg (long) */ if (c[0] == ':') { sp->sp_lstchg = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_lstchg = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "lstchg -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* min (long) */ if (c[0] == ':') { sp->sp_min = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_min = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "min -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* max (long) */ if (c[0] == ':') { sp->sp_max = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_max = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "max -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* warn (long) */ if (c[0] == ':') { sp->sp_warn = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_warn = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "warn -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* inact (long) */ if (c[0] == ':') { sp->sp_inact = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_inact = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "inact -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; /* expire (long) */ if (c[0] == ':') { sp->sp_expire = -1; p++; } else { p = strchr(c, ':'); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; sp->sp_expire = strtol(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "expire -- Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } } c = p; nwrap_sp->num++; return true; } static void nwrap_sp_unload(struct nwrap_cache *nwrap) { struct nwrap_sp *nwrap_sp; nwrap_sp = (struct nwrap_sp *)nwrap->private_data; SAFE_FREE(nwrap_sp->list); nwrap_sp->num = 0; nwrap_sp->idx = 0; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /* * the caller has to call nwrap_unload() on failure */ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_gr *nwrap_gr; char *c; char *p; char *e; struct group *gr; size_t list_size; unsigned nummem; nwrap_gr = (struct nwrap_gr *)nwrap->private_data; list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1); gr = (struct group *)realloc(nwrap_gr->list, list_size); if (!gr) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed"); return false; } nwrap_gr->list = gr; gr = &nwrap_gr->list[nwrap_gr->num]; c = line; /* name */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; gr->gr_name = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name); /* password */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; gr->gr_passwd = c; c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd); /* gid */ p = strchr(c, ':'); if (!p) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; p++; e = NULL; gr->gr_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } if (e[0] != '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s' - %s", line, c, strerror(errno)); return false; } c = p; NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid); /* members */ gr->gr_mem = (char **)malloc(sizeof(char *)); if (!gr->gr_mem) { NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } gr->gr_mem[0] = NULL; for(nummem = 0; p != NULL && p[0] != '\0'; nummem++) { char **m; size_t m_size; c = p; p = strchr(c, ','); if (p) { *p = '\0'; p++; } if (strlen(c) == 0) { break; } m_size = sizeof(char *) * (nummem+2); m = (char **)realloc(gr->gr_mem, m_size); if (!m) { NWRAP_LOG(NWRAP_LOG_ERROR, "realloc(%zd) failed", m_size); return false; } gr->gr_mem = m; gr->gr_mem[nummem] = c; gr->gr_mem[nummem+1] = NULL; NWRAP_LOG(NWRAP_LOG_TRACE, "member[%u]: '%s'", nummem, gr->gr_mem[nummem]); } NWRAP_LOG(NWRAP_LOG_DEBUG, "Added group[%s:%s:%u:] with %u members", gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem); nwrap_gr->num++; return true; } static void nwrap_gr_unload(struct nwrap_cache *nwrap) { int i; struct nwrap_gr *nwrap_gr; nwrap_gr = (struct nwrap_gr *)nwrap->private_data; if (nwrap_gr->list) { for (i=0; i < nwrap_gr->num; i++) { SAFE_FREE(nwrap_gr->list[i].gr_mem); } SAFE_FREE(nwrap_gr->list); } nwrap_gr->num = 0; nwrap_gr->idx = 0; } static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed) { struct nwrap_entlist *el; if (ed == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "entry is NULL, can't create list item"); return NULL; } el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist)); if (el == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed"); return NULL; } el->next = NULL; el->ed = ed; return el; } static bool nwrap_ed_inventarize_add_new(char *const h_name, struct nwrap_entdata *const ed) { ENTRY e; ENTRY *p; struct nwrap_entlist *el; bool ok; if (h_name == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add"); return false; } el = nwrap_entlist_init(ed); if (el == NULL) { return false; } e.key = h_name; e.data = (void *)el; p = hsearch(e, ENTER); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full (%s)!", strerror(errno)); return false; } ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to add list entry to vector."); return false; } return true; } static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed, struct nwrap_entlist *const el) { struct nwrap_entlist *cursor; struct nwrap_entlist *el_new; if (el == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add"); return false; } for (cursor = el; cursor->next != NULL; cursor = cursor->next) { if (cursor->ed == ed) { /* The entry already exists in this list. */ return true; } } if (cursor->ed == ed) { /* The entry already exists in this list. */ return true; } el_new = nwrap_entlist_init(ed); if (el_new == NULL) { return false; } cursor->next = el_new; return true; } static bool nwrap_ed_inventarize(char *const name, struct nwrap_entdata *const ed) { ENTRY e; ENTRY *p; bool ok; e.key = name; e.data = NULL; NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key); p = hsearch(e, FIND); if (p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name); ok = nwrap_ed_inventarize_add_new(name, ed); } else { struct nwrap_entlist *el = (struct nwrap_entlist *)p->data; NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name); ok = nwrap_ed_inventarize_add_to_existing(ed, el); } return ok; } static bool nwrap_add_hname(struct nwrap_entdata *const ed) { char *const h_name = (char *const)(ed->ht.h_name); unsigned i; bool ok; ok = nwrap_ed_inventarize(h_name, ed); if (!ok) { return false; } if (ed->ht.h_aliases == NULL) { return true; } /* Itemize aliases */ for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) { char *h_name_alias; h_name_alias = ed->ht.h_aliases[i]; NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias); if (!nwrap_ed_inventarize(h_name_alias, ed)) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add alias: %s", h_name_alias); return false; } } return true; } static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line) { struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data; bool do_aliases = true; ssize_t aliases_count = 0; char *p; char *i; char *n; char *ip; bool ok; struct nwrap_entdata *ed = (struct nwrap_entdata *) malloc(sizeof(struct nwrap_entdata)); if (ed == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for nwrap_entdata"); return false; } ZERO_STRUCTP(ed); i = line; /* * IP */ /* Walk to first char */ for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } } for (i = p; !isspace((int)*p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } } *p = '\0'; if (inet_pton(AF_INET, i, ed->addr.host_addr)) { ed->ht.h_addrtype = AF_INET; ed->ht.h_length = 4; #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) { ed->ht.h_addrtype = AF_INET6; ed->ht.h_length = 16; #endif } else { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, i); free(ed); return false; } ip = i; ok = nwrap_vector_add_item(&(ed->nwrap_addrdata), (void *const)ed->addr.host_addr); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector"); free(ed); return false; } ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata); p++; /* * FQDN */ /* Walk to first char */ for (n = p; *p != '_' && !isalnum((int) *p); p++) { if (*p == '\0') { NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, n); free(ed); return false; } } for (n = p; !isspace((int)*p); p++) { if (*p == '\0') { do_aliases = false; break; } } *p = '\0'; /* Convert to lowercase. This operate on same memory region */ str_tolower(n, n); ed->ht.h_name = n; /* glib's getent always dereferences he->h_aliases */ ed->ht.h_aliases = malloc(sizeof(char *)); if (ed->ht.h_aliases == NULL) { free(ed); return false; } ed->ht.h_aliases[0] = NULL; /* * Aliases */ while (do_aliases) { char **aliases; char *a; p++; /* Walk to first char */ for (a = p; *p != '_' && !isalnum((int) *p); p++) { if (*p == '\0') { do_aliases = false; break; } } /* Only trailing spaces are left */ if (!do_aliases) { break; } for (a = p; !isspace((int)*p); p++) { if (*p == '\0') { do_aliases = false; break; } } *p = '\0'; aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2)); if (aliases == NULL) { free(ed); return false; } ed->ht.h_aliases = aliases; str_tolower(a, a); aliases[aliases_count] = a; aliases[aliases_count + 1] = NULL; aliases_count += 1; } ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector"); free(ed); return false; } ed->aliases_count = aliases_count; /* Inventarize item */ ok = nwrap_add_hname(ed); if (!ok) { return false; } ok = nwrap_ed_inventarize(ip, ed); if (!ok) { return false; } nwrap_he->num++; return true; } static void nwrap_he_unload(struct nwrap_cache *nwrap) { struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data; struct nwrap_entdata *ed; struct nwrap_entlist *el; size_t i; int rc; nwrap_vector_foreach (ed, nwrap_he->entries, i) { SAFE_FREE(ed->nwrap_addrdata.items); SAFE_FREE(ed->ht.h_aliases); SAFE_FREE(ed); } SAFE_FREE(nwrap_he->entries.items); nwrap_he->entries.count = nwrap_he->entries.capacity = 0; nwrap_vector_foreach(el, nwrap_he->lists, i) { while (el != NULL) { struct nwrap_entlist *el_next; el_next = el->next; SAFE_FREE(el); el = el_next; } } SAFE_FREE(nwrap_he->lists.items); nwrap_he->lists.count = nwrap_he->lists.capacity = 0; nwrap_he->num = 0; nwrap_he->idx = 0; /* * If we unload the file, the pointers in the hash table point to * invalid memory. So we need to destroy the hash table and recreate * it. */ hdestroy(); rc = hcreate(max_hostents); if (rc == 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table"); exit(-1); } } /* user functions */ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, const char *name) { int i; bool ok; (void) b; /* unused */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name); ok = nwrap_files_cache_reload(nwrap_pw_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file"); return NULL; } for (i=0; i= nwrap_pw_global.num) { errno = ENOENT; return NULL; } pw = &nwrap_pw_global.list[nwrap_pw_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return user[%s] uid[%u]", pw->pw_name, pw->pw_uid); return pw; } static int nwrap_files_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { struct passwd *pw; pw = nwrap_files_getpwent(b); if (!pw) { if (errno == 0) { return ENOENT; } return errno; } return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp); } static void nwrap_files_endpwent(struct nwrap_backend *b) { (void) b; /* unused */ nwrap_pw_global.idx = 0; } /* shadow */ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) #ifdef HAVE_SETSPENT static void nwrap_files_setspent(void) { nwrap_sp_global.idx = 0; } static struct spwd *nwrap_files_getspent(void) { struct spwd *sp; if (nwrap_sp_global.idx == 0) { bool ok; ok = nwrap_files_cache_reload(nwrap_sp_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file"); return NULL; } } if (nwrap_sp_global.idx >= nwrap_sp_global.num) { errno = ENOENT; return NULL; } sp = &nwrap_sp_global.list[nwrap_sp_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return user[%s]", sp->sp_namp); return sp; } static void nwrap_files_endspent(void) { nwrap_sp_global.idx = 0; } #endif /* HAVE_SETSPENT */ static struct spwd *nwrap_files_getspnam(const char *name) { int i; bool ok; NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name); ok = nwrap_files_cache_reload(nwrap_sp_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file"); return NULL; } for (i=0; igr_name); for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { if (group != grp->gr_gid && (strcmp(user, grp->gr_mem[i]) == 0)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "%s is member of %s", user, grp->gr_name); if (*start == *size) { long int newsize; gid_t *newgroups; newsize = 2 * (*size); if (limit > 0 && newsize > limit) { newsize = MAX(limit, *size); } newgroups = (gid_t *) realloc((*groups), newsize * sizeof(**groups)); if (!newgroups) { errno = ENOMEM; return -1; } *groups = newgroups; *size = newsize; } (*groups)[*start] = grp->gr_gid; (*start)++; } } } nwrap_files_endgrent(b); return *start; } /* group functions */ static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, const char *name) { int i; bool ok; (void) b; /* unused */ ok = nwrap_files_cache_reload(nwrap_gr_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file"); return NULL; } for (i=0; i= nwrap_gr_global.num) { errno = ENOENT; return NULL; } gr = &nwrap_gr_global.list[nwrap_gr_global.idx++]; NWRAP_LOG(NWRAP_LOG_DEBUG, "return group[%s] gid[%u]", gr->gr_name, gr->gr_gid); return gr; } static int nwrap_files_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { struct group *gr; gr = nwrap_files_getgrent(b); if (!gr) { if (errno == 0) { return ENOENT; } return errno; } return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp); } static void nwrap_files_endgrent(struct nwrap_backend *b) { (void) b; /* unused */ nwrap_gr_global.idx = 0; } /* hosts functions */ static int nwrap_files_internal_gethostbyname(const char *name, int af, struct hostent *result, struct nwrap_vector *addr_list) { struct nwrap_entlist *el; struct hostent *he; char *h_name_lower; ENTRY e; ENTRY *e_p; char canon_name[DNS_NAME_MAX] = { 0 }; size_t name_len; bool he_found = false; bool ok; /* * We need to make sure we have zeroed return pointer for consumers * which don't check return values, e.g. OpenLDAP. */ ZERO_STRUCTP(result); ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); goto no_ent; } name_len = strlen(name); if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') { memcpy(canon_name, name, name_len - 1); canon_name[name_len] = '\0'; name = canon_name; } if (!str_tolower_copy(&h_name_lower, name)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while converting to lower case"); goto no_ent; } /* Look at hash table for element */ NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower); e.key = h_name_lower; e.data = NULL; e_p = hsearch(e, FIND); if (e_p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower); SAFE_FREE(h_name_lower); goto no_ent; } SAFE_FREE(h_name_lower); /* Always cleanup vector and results */ if (!nwrap_vector_is_initialized(addr_list)) { if (!nwrap_vector_init(addr_list)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Unable to initialize memory for addr_list vector"); goto no_ent; } } else { /* When vector is initialized data are valid no more. * Quick way how to free vector is: */ addr_list->count = 0; } /* Iterate through results */ for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next) { he = &(el->ed->ht); /* Filter by address familiy if provided */ if (af != AF_UNSPEC && he->h_addrtype != af) { continue; } /* * GLIBC HACK? * glibc doesn't return ipv6 addresses when AF_UNSPEC is used */ if (af == AF_UNSPEC && he->h_addrtype != AF_INET) { continue; } if (!he_found) { memcpy(result, he, sizeof(struct hostent)); NWRAP_LOG(NWRAP_LOG_DEBUG, "Name found. Returning record for %s", he->h_name); he_found = true; } nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata); result->h_addr_list = nwrap_vector_head(addr_list); } if (he_found) { return 0; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Name found in database. No records matches type."); no_ent: errno = ENOENT; return -1; } static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, char *buf, size_t buflen, struct hostent **hedstp) { struct nwrap_vector *addr_list = NULL; union { char *ptr; char **list; } g; int rc; (void) b; /* unused */ (void) af; /* unused */ if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) { errno = EINVAL; return -1; } *hedstp = NULL; buf[0] = '\0'; addr_list = calloc(1, sizeof(struct nwrap_vector)); if (addr_list == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for address list"); errno = ENOENT; return -1; } rc = nwrap_files_internal_gethostbyname(name, af, hedst, addr_list); if (rc == -1) { SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); errno = ENOENT; return -1; } /* +1 i for ending NULL pointer */ if (buflen < ((addr_list->count + 1) * sizeof(void *))) { SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); return ERANGE; } /* Copy all to user provided buffer and change * pointers in returned structure. * +1 is for ending NULL pointer. */ memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *)); SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); g.ptr = buf; hedst->h_addr_list = g.list; *hedstp = hedst; return 0; } #ifdef HAVE_GETHOSTBYNAME_R static int nwrap_gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { int rc; size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; rc = b->ops->nw_gethostbyname2_r(b, name, AF_UNSPEC, ret, buf, buflen, result); if (rc == 0) { return 0; } else if (rc == ERANGE) { return ERANGE; } } *h_errnop = h_errno; return ENOENT; } int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } #endif #ifdef HAVE_GETHOSTBYNAME2_R static int nwrap_gethostbyname2_r(const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { int rc; size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; rc = b->ops->nw_gethostbyname2_r(b, name, af, ret, buf, buflen, result); if (rc == 0) { return 0; } else if (rc == ERANGE) { return ERANGE; } } *h_errnop = h_errno; return ENOENT; } int gethostbyname2_r(const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname2_r(name, af, ret, buf, buflen, result, h_errnop); } return nwrap_gethostbyname2_r(name, af, ret, buf, buflen, result, h_errnop); } #endif static int nwrap_files_getaddrinfo(const char *name, unsigned short port, const struct addrinfo *hints, struct addrinfo **ai) { struct nwrap_entlist *el; struct hostent *he; struct addrinfo *ai_head = NULL; struct addrinfo *ai_cur = NULL; char *h_name_lower; size_t name_len; char canon_name[DNS_NAME_MAX] = { 0 }; bool skip_canonname = false; ENTRY e = { .key = NULL, }; ENTRY *e_p = NULL; int rc; bool ok; ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); return EAI_SYSTEM; } name_len = strlen(name); if (name_len == 0) { return EAI_NONAME; } if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') { memcpy(canon_name, name, name_len - 1); canon_name[name_len] = '\0'; name = canon_name; } if (!str_tolower_copy(&h_name_lower, name)) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while converting to lower case"); return EAI_MEMORY; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower); e.key = h_name_lower; e.data = NULL; e_p = hsearch(e, FIND); if (e_p == NULL) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower); SAFE_FREE(h_name_lower); errno = ENOENT; return EAI_NONAME; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower); SAFE_FREE(h_name_lower); rc = EAI_NONAME; for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next) { int rc2; struct addrinfo *ai_new = NULL; he = &(el->ed->ht); if (hints->ai_family != AF_UNSPEC && he->h_addrtype != hints->ai_family) { NWRAP_LOG(NWRAP_LOG_DEBUG, "Entry found but with wrong AF - " "remembering EAI_ADDRINFO."); rc = EAI_ADDRFAMILY; continue; } /* Function allocates memory and returns it in ai. */ rc2 = nwrap_convert_he_ai(he, port, hints, &ai_new, skip_canonname); if (rc2 != 0) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai"); if (ai_head != NULL) { freeaddrinfo(ai_head); } return rc2; } skip_canonname = true; if (ai_head == NULL) { ai_head = ai_new; } if (ai_cur != NULL) { ai_cur->ai_next = ai_new; } ai_cur = ai_new; } if (ai_head != NULL) { rc = 0; } *ai = ai_head; return rc; } static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b, const void *addr, socklen_t len, int type) { struct hostent *he; char ip[NWRAP_INET_ADDRSTRLEN] = {0}; struct nwrap_entdata *ed; const char *a; size_t i; bool ok; (void) b; /* unused */ (void) len; /* unused */ ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); return NULL; } a = inet_ntop(type, addr, ip, sizeof(ip)); if (a == NULL) { errno = EINVAL; return NULL; } nwrap_vector_foreach(ed, nwrap_he_global.entries, i) { he = &(ed->ht); if (he->h_addrtype != type) { continue; } if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) { return he; } } errno = ENOENT; return NULL; } #ifdef HAVE_GETHOSTBYADDR_R static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; *result = b->ops->nw_gethostbyaddr(b, addr, len, type); if (*result != NULL) { break; } } if (*result != NULL) { memset(buf, '\0', buflen); *ret = **result; return 0; } *h_errnop = h_errno; return -1; } int gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop); } return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop); } #endif /* hosts enum functions */ static void nwrap_files_sethostent(void) { nwrap_he_global.idx = 0; } static struct hostent *nwrap_files_gethostent(void) { struct hostent *he; if (nwrap_he_global.idx == 0) { bool ok; ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file"); return NULL; } } if (nwrap_he_global.idx >= nwrap_he_global.num) { errno = ENOENT; return NULL; } he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht; NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name); return he; } static void nwrap_files_endhostent(void) { nwrap_he_global.idx = 0; } /* * module backend */ static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, const char *name) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (b->symbols->_nss_getpwnam_r.f == NULL) { return NULL; } status = b->symbols->_nss_getpwnam_r.f(name, &pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwnam_r(struct nwrap_backend *b, const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; *pwdstp = NULL; if (b->symbols->_nss_getpwnam_r.f == NULL) { return NSS_STATUS_NOTFOUND; } ret = b->symbols->_nss_getpwnam_r.f(name, pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *pwdstp = pwdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, uid_t uid) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (b->symbols->_nss_getpwuid_r.f == NULL) { return NULL; } status = b->symbols->_nss_getpwuid_r.f(uid, &pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwuid_r(struct nwrap_backend *b, uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; *pwdstp = NULL; if (b->symbols->_nss_getpwuid_r.f == NULL) { return ENOENT; } ret = b->symbols->_nss_getpwuid_r.f(uid, pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *pwdstp = pwdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_setpwent(struct nwrap_backend *b) { if (b->symbols->_nss_setpwent.f == NULL) { return; } b->symbols->_nss_setpwent.f(); } static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b) { static struct passwd pwd; static char buf[1000]; NSS_STATUS status; if (b->symbols->_nss_getpwent_r.f == NULL) { return NULL; } status = b->symbols->_nss_getpwent_r.f(&pwd, buf, sizeof(buf), &errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; } if (status != NSS_STATUS_SUCCESS) { return NULL; } return &pwd; } static int nwrap_module_getpwent_r(struct nwrap_backend *b, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { int ret; *pwdstp = NULL; if (b->symbols->_nss_getpwent_r.f == NULL) { return ENOENT; } ret = b->symbols->_nss_getpwent_r.f(pwdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *pwdstp = pwdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_endpwent(struct nwrap_backend *b) { if (b->symbols->_nss_endpwent.f == NULL) { return; } b->symbols->_nss_endpwent.f(); } static int nwrap_module_initgroups_dyn(struct nwrap_backend *b, const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) { if (b->symbols->_nss_initgroups_dyn.f == NULL) { return NSS_STATUS_UNAVAIL; } return b->symbols->_nss_initgroups_dyn.f(user, group, start, size, groups, limit, errnop); } static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, const char *name) { static struct group grp; static char *buf; static int buflen = 1000; NSS_STATUS status; if (b->symbols->_nss_getgrnam_r.f == NULL) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->symbols->_nss_getgrnam_r.f(name, &grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrnam_r(struct nwrap_backend *b, const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; *grdstp = NULL; if (b->symbols->_nss_getgrnam_r.f == NULL) { return ENOENT; } ret = b->symbols->_nss_getgrnam_r.f(name, grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *grdstp = grdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, gid_t gid) { static struct group grp; static char *buf; static int buflen = 1000; NSS_STATUS status; if (b->symbols->_nss_getgrgid_r.f == NULL) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->symbols->_nss_getgrgid_r.f(gid, &grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrgid_r(struct nwrap_backend *b, gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; *grdstp = NULL; if (b->symbols->_nss_getgrgid_r.f == NULL) { return ENOENT; } ret = b->symbols->_nss_getgrgid_r.f(gid, grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *grdstp = grdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_setgrent(struct nwrap_backend *b) { if (b->symbols->_nss_setgrent.f == NULL) { return; } b->symbols->_nss_setgrent.f(); } static struct group *nwrap_module_getgrent(struct nwrap_backend *b) { static struct group grp; static char *buf; static int buflen = 1024; NSS_STATUS status; if (b->symbols->_nss_getgrent_r.f == NULL) { return NULL; } if (!buf) { buf = (char *)malloc(buflen); } again: status = b->symbols->_nss_getgrent_r.f(&grp, buf, buflen, &errno); if (status == NSS_STATUS_TRYAGAIN) { buflen *= 2; buf = (char *)realloc(buf, buflen); if (!buf) { return NULL; } goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &grp; } static int nwrap_module_getgrent_r(struct nwrap_backend *b, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { int ret; *grdstp = NULL; if (b->symbols->_nss_getgrent_r.f == NULL) { return ENOENT; } ret = b->symbols->_nss_getgrent_r.f(grdst, buf, buflen, &errno); switch (ret) { case NSS_STATUS_SUCCESS: *grdstp = grdst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return ret; } } static void nwrap_module_endgrent(struct nwrap_backend *b) { if (b->symbols->_nss_endgrent.f == NULL) { return; } b->symbols->_nss_endgrent.f(); } static struct hostent *nwrap_module_gethostbyaddr(struct nwrap_backend *b, const void *addr, socklen_t len, int type) { static struct hostent he; static char *buf = NULL; static size_t buflen = 1000; NSS_STATUS status; if (b->symbols->_nss_gethostbyaddr_r.f == NULL) { return NULL; } if (buf == NULL) { buf = (char *)malloc(buflen); if (buf == NULL) { return NULL; } } again: status = b->symbols->_nss_gethostbyaddr_r.f(addr, len, type, &he, buf, buflen, &errno, &h_errno); if (status == NSS_STATUS_TRYAGAIN) { char *p = NULL; buflen *= 2; p = (char *)realloc(buf, buflen); if (p == NULL) { SAFE_FREE(buf); return NULL; } buf = p; goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &he; } static int nwrap_module_gethostbyname2_r(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, char *buf, size_t buflen, struct hostent **hedstp) { NSS_STATUS status; *hedstp = NULL; if (b->symbols->_nss_gethostbyname2_r.f == NULL) { return ENOENT; } status = b->symbols->_nss_gethostbyname2_r.f(name, af, hedst, buf, buflen, &errno, &h_errno); switch (status) { case NSS_STATUS_SUCCESS: *hedstp = hedst; return 0; case NSS_STATUS_NOTFOUND: if (errno != 0) { return errno; } return ENOENT; case NSS_STATUS_TRYAGAIN: if (errno != 0) { return errno; } return ERANGE; default: if (errno != 0) { return errno; } return status; } } static struct hostent *nwrap_module_gethostbyname(struct nwrap_backend *b, const char *name) { static struct hostent he; static char *buf = NULL; static size_t buflen = 1000; NSS_STATUS status; if (b->symbols->_nss_gethostbyname2_r.f == NULL) { return NULL; } if (buf == NULL) { buf = (char *)malloc(buflen); if (buf == NULL) { return NULL; } } again: status = b->symbols->_nss_gethostbyname2_r.f(name, AF_UNSPEC, &he, buf, buflen, &errno, &h_errno); if (status == NSS_STATUS_TRYAGAIN) { char *p = NULL; buflen *= 2; p = (char *)realloc(buf, buflen); if (p == NULL) { SAFE_FREE(buf); return NULL; } buf = p; goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &he; } static struct hostent *nwrap_module_gethostbyname2(struct nwrap_backend *b, const char *name, int af) { static struct hostent he; static char *buf = NULL; static size_t buflen = 1000; NSS_STATUS status; if (b->symbols->_nss_gethostbyname2_r.f == NULL) { return NULL; } if (buf == NULL) { buf = (char *)malloc(buflen); if (buf == NULL) { return NULL; } } again: status = b->symbols->_nss_gethostbyname2_r.f(name, af, &he, buf, buflen, &errno, &h_errno); if (status == NSS_STATUS_TRYAGAIN) { char *p = NULL; buflen *= 2; p = (char *)realloc(buf, buflen); if (p == NULL) { SAFE_FREE(buf); return NULL; } buf = p; goto again; } if (status == NSS_STATUS_NOTFOUND) { SAFE_FREE(buf); return NULL; } if (status != NSS_STATUS_SUCCESS) { SAFE_FREE(buf); return NULL; } return &he; } /**************************************************************************** * GETPWNAM ***************************************************************************/ static struct passwd *nwrap_getpwnam(const char *name) { size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwnam(b, name); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwnam(const char *name) { if (!nss_wrapper_enabled()) { return libc_getpwnam(name); } return nwrap_getpwnam(name); } /**************************************************************************** * GETPWNAM_R ***************************************************************************/ static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETPWNAM_R # ifdef HAVE_SOLARIS_GETPWNAM_R int getpwnam_r(const char *name, struct passwd *pwdst, char *buf, int buflen, struct passwd **pwdstp) # else /* HAVE_SOLARIS_GETPWNAM_R */ int getpwnam_r(const char *name, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) # endif /* HAVE_SOLARIS_GETPWNAM_R */ { if (!nss_wrapper_enabled()) { return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp); } return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp); } #endif /**************************************************************************** * GETPWUID ***************************************************************************/ static struct passwd *nwrap_getpwuid(uid_t uid) { size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwuid(b, uid); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwuid(uid_t uid) { if (!nss_wrapper_enabled()) { return libc_getpwuid(uid); } return nwrap_getpwuid(uid); } /**************************************************************************** * GETPWUID_R ***************************************************************************/ static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_SOLARIS_GETPWUID_R int getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, int buflen, struct passwd **pwdstp) #else int getpwuid_r(uid_t uid, struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) #endif { if (!nss_wrapper_enabled()) { return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); } return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); } /**************************************************************************** * SETPWENT ***************************************************************************/ static void nwrap_setpwent(void) { size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_setpwent(b); } } void setpwent(void) { if (!nss_wrapper_enabled()) { libc_setpwent(); return; } nwrap_setpwent(); } /**************************************************************************** * GETPWENT ***************************************************************************/ static struct passwd *nwrap_getpwent(void) { size_t i; struct passwd *pwd; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; pwd = b->ops->nw_getpwent(b); if (pwd) { return pwd; } } return NULL; } struct passwd *getpwent(void) { if (!nss_wrapper_enabled()) { return libc_getpwent(); } return nwrap_getpwent(); } /**************************************************************************** * GETPWENT_R ***************************************************************************/ #ifdef HAVE_GETPWENT_R static int nwrap_getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } # ifdef HAVE_SOLARIS_GETPWENT_R struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen) { struct passwd *pwdstp = NULL; int rc; if (!nss_wrapper_enabled()) { return libc_getpwent_r(pwdst, buf, buflen); } rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp); if (rc < 0) { return NULL; } return pwdstp; } # else /* HAVE_SOLARIS_GETPWENT_R */ int getpwent_r(struct passwd *pwdst, char *buf, size_t buflen, struct passwd **pwdstp) { if (!nss_wrapper_enabled()) { return libc_getpwent_r(pwdst, buf, buflen, pwdstp); } return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp); } # endif /* HAVE_SOLARIS_GETPWENT_R */ #endif /* HAVE_GETPWENT_R */ /**************************************************************************** * ENDPWENT ***************************************************************************/ static void nwrap_endpwent(void) { size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_endpwent(b); } } void endpwent(void) { if (!nss_wrapper_enabled()) { libc_endpwent(); return; } nwrap_endpwent(); } /**************************************************************************** * INITGROUPS ***************************************************************************/ static int nwrap_initgroups(const char *user, gid_t group) { #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 /* No extra groups allowed. */ return 0; #elif !defined(HAVE_GETGROUPLIST) return 0; #else long int size; long int limit; gid_t *groups; int ngroups; int result; const char *env = getenv("UID_WRAPPER"); if (env == NULL || env[0] != '1') { NWRAP_LOG(NWRAP_LOG_WARN, "initgroups() requires uid_wrapper to work!"); return 0; } limit = sysconf(_SC_NGROUPS_MAX); if (limit > 0) { size = MIN(limit, 64); } else { size = 16; } groups = (gid_t *)malloc(size * sizeof(gid_t)); if (groups == NULL) { /* No more memory. */ return -1; } ngroups = nwrap_getgrouplist(user, group, &size, &groups, limit); /* Try to set the maximum number of groups the kernel can handle. */ do { result = setgroups(ngroups, groups); } while (result == -1 && errno == EINVAL && --ngroups > 0); free(groups); return result; #endif } int initgroups(const char *user, gid_t group) { if (!nss_wrapper_enabled()) { return libc_initgroups(user, group); } return nwrap_initgroups(user, group); } /**************************************************************************** * GETGRNAM ***************************************************************************/ static struct group *nwrap_getgrnam(const char *name) { size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrnam(b, name); if (grp) { return grp; } } return NULL; } struct group *getgrnam(const char *name) { if (!nss_wrapper_enabled()) { return libc_getgrnam(name); } return nwrap_getgrnam(name); } /**************************************************************************** * GETGRNAM_R ***************************************************************************/ static int nwrap_getgrnam_r(const char *name, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETGRNAM_R # ifdef HAVE_SOLARIS_GETGRNAM_R int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp) # else /* HAVE_SOLARIS_GETGRNAM_R */ int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **pgrp) # endif /* HAVE_SOLARIS_GETGRNAM_R */ { if (!nss_wrapper_enabled()) { return libc_getgrnam_r(name, grp, buf, buflen, pgrp); } return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp); } #endif /* HAVE_GETGRNAM_R */ /**************************************************************************** * GETGRGID ***************************************************************************/ static struct group *nwrap_getgrgid(gid_t gid) { size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrgid(b, gid); if (grp) { return grp; } } return NULL; } struct group *getgrgid(gid_t gid) { if (!nss_wrapper_enabled()) { return libc_getgrgid(gid); } return nwrap_getgrgid(gid); } /**************************************************************************** * GETGRGID_R ***************************************************************************/ static int nwrap_getgrgid_r(gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } #ifdef HAVE_GETGRGID_R # ifdef HAVE_SOLARIS_GETGRGID_R int getgrgid_r(gid_t gid, struct group *grdst, char *buf, int buflen, struct group **grdstp) # else /* HAVE_SOLARIS_GETGRGID_R */ int getgrgid_r(gid_t gid, struct group *grdst, char *buf, size_t buflen, struct group **grdstp) # endif /* HAVE_SOLARIS_GETGRGID_R */ { if (!nss_wrapper_enabled()) { return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp); } return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp); } #endif /**************************************************************************** * SETGRENT ***************************************************************************/ static void nwrap_setgrent(void) { size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_setgrent(b); } } #ifdef HAVE_BSD_SETGRENT int setgrent(void) #else void setgrent(void) #endif { if (!nss_wrapper_enabled()) { libc_setgrent(); goto out; } nwrap_setgrent(); out: #ifdef HAVE_BSD_SETGRENT return 0; #else return; #endif } /**************************************************************************** * GETGRENT ***************************************************************************/ static struct group *nwrap_getgrent(void) { size_t i; struct group *grp; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; grp = b->ops->nw_getgrent(b); if (grp) { return grp; } } return NULL; } struct group *getgrent(void) { if (!nss_wrapper_enabled()) { return libc_getgrent(); } return nwrap_getgrent(); } /**************************************************************************** * GETGRENT_R ***************************************************************************/ #ifdef HAVE_GETGRENT_R static int nwrap_getgrent_r(struct group *grdst, char *buf, size_t buflen, struct group **grdstp) { size_t i; int ret; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp); if (ret == ENOENT) { continue; } return ret; } return ENOENT; } # ifdef HAVE_SOLARIS_GETGRENT_R struct group *getgrent_r(struct group *src, char *buf, int buflen) { struct group *grdstp = NULL; int rc; if (!nss_wrapper_enabled()) { return libc_getgrent_r(src, buf, buflen); } rc = nwrap_getgrent_r(src, buf, buflen, &grdstp); if (rc < 0) { return NULL; } return grdstp; } # else /* HAVE_SOLARIS_GETGRENT_R */ int getgrent_r(struct group *src, char *buf, size_t buflen, struct group **grdstp) { if (!nss_wrapper_enabled()) { return libc_getgrent_r(src, buf, buflen, grdstp); } return nwrap_getgrent_r(src, buf, buflen, grdstp); } # endif /* HAVE_SOLARIS_GETGRENT_R */ #endif /* HAVE_GETGRENT_R */ /**************************************************************************** * ENDGRENT ***************************************************************************/ static void nwrap_endgrent(void) { size_t i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; b->ops->nw_endgrent(b); } } void endgrent(void) { if (!nss_wrapper_enabled()) { libc_endgrent(); return; } nwrap_endgrent(); } /**************************************************************************** * GETGROUPLIST ***************************************************************************/ #ifdef HAVE_GETGROUPLIST static int nwrap_getgrouplist(const char *user, gid_t group, long int *size, gid_t **groupsp, long int limit) { enum nss_status status = NSS_STATUS_UNAVAIL; /* Start is one, because we have the first group as parameter. */ long int start = 1; size_t i; /* Never store more than the starting *SIZE number of elements. */ assert(*size > 0); (*groupsp)[0] = group; for (i = 0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; long int prev_start = start; long int cnt = prev_start; status = b->ops->nw_initgroups_dyn(b, user, group, &start, size, groupsp, limit, &errno); /* Remove duplicates. */ while (cnt < start) { long int inner; for (inner = 0; inner < prev_start; ++inner) if ((*groupsp)[inner] == (*groupsp)[cnt]) break; if (inner < prev_start) (*groupsp)[cnt] = (*groupsp)[--start]; else ++cnt; } NWRAP_LOG(NWRAP_LOG_DEBUG, "Resource '%s' returned status=%d and increased " "count of groups to %ld", b->name, status, start); } return start; } int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) { long int size; int total, retval; gid_t *newgroups; if (!nss_wrapper_enabled()) { return libc_getgrouplist(user, group, groups, ngroups); } size = MAX(1, *ngroups); newgroups = (gid_t *)malloc(size * sizeof(gid_t)); if (newgroups == NULL) { return -1; } total = nwrap_getgrouplist(user, group, &size, &newgroups, -1); if (groups != NULL) { memcpy(groups, newgroups, MIN(*ngroups, total) * sizeof(gid_t)); } free(newgroups); retval = total > *ngroups ? -1 : total; *ngroups = total; return retval; } #endif /********************************************************** * SHADOW **********************************************************/ #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) #ifdef HAVE_SETSPENT static void nwrap_setspent(void) { nwrap_files_setspent(); } void setspent(void) { if (!nss_wrapper_shadow_enabled()) { return; } nwrap_setspent(); } static struct spwd *nwrap_getspent(void) { return nwrap_files_getspent(); } struct spwd *getspent(void) { if (!nss_wrapper_shadow_enabled()) { return NULL; } return nwrap_getspent(); } static void nwrap_endspent(void) { nwrap_files_endspent(); } void endspent(void) { if (!nss_wrapper_shadow_enabled()) { return; } nwrap_endspent(); } #endif /* HAVE_SETSPENT */ static struct spwd *nwrap_getspnam(const char *name) { return nwrap_files_getspnam(name); } struct spwd *getspnam(const char *name) { if (!nss_wrapper_shadow_enabled()) { return NULL; } return nwrap_getspnam(name); } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ /********************************************************** * NETDB **********************************************************/ static void nwrap_sethostent(int stayopen) { (void) stayopen; /* ignored */ nwrap_files_sethostent(); } #ifdef HAVE_SOLARIS_SETHOSTENT int sethostent(int stayopen) { if (!nss_wrapper_hosts_enabled()) { libc_sethostent(stayopen); return 0; } nwrap_sethostent(stayopen); return 0; } #else /* HAVE_SOLARIS_SETHOSTENT */ void sethostent(int stayopen) { if (!nss_wrapper_hosts_enabled()) { libc_sethostent(stayopen); return; } nwrap_sethostent(stayopen); } #endif /* HAVE_SOLARIS_SETHOSTENT */ static struct hostent *nwrap_gethostent(void) { return nwrap_files_gethostent(); } struct hostent *gethostent(void) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostent(); } return nwrap_gethostent(); } static void nwrap_endhostent(void) { nwrap_files_endhostent(); } #ifdef HAVE_SOLARIS_ENDHOSTENT int endhostent(void) { if (!nss_wrapper_hosts_enabled()) { libc_endhostent(); return 0; } nwrap_endhostent(); return 0; } #else /* HAVE_SOLARIS_ENDHOSTENT */ void endhostent(void) { if (!nss_wrapper_hosts_enabled()) { libc_endhostent(); return; } nwrap_endhostent(); } #endif /* HAVE_SOLARIS_ENDHOSTENT */ #ifdef BSD /* BSD implementation stores data in thread local storage but GLIBC does not */ static __thread struct hostent user_he; static __thread struct nwrap_vector user_addrlist; #else static struct hostent user_he; static struct nwrap_vector user_addrlist; #endif /* BSD */ static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b, const char *name) { int ret; (void) b; /* unused */ ret = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist); if (ret == 0) { return &user_he; } return NULL; } static struct hostent *nwrap_gethostbyname(const char *name) { size_t i; struct hostent *he = NULL; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; he = b->ops->nw_gethostbyname(b, name); if (he != NULL) { return he; } } return NULL; } struct hostent *gethostbyname(const char *name) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname(name); } return nwrap_gethostbyname(name); } /* This is a GNU extension - Also can be found on BSD systems */ #ifdef HAVE_GETHOSTBYNAME2 #ifdef BSD /* BSD implementation stores data in thread local storage but GLIBC not */ static __thread struct hostent user_he2; static __thread struct nwrap_vector user_addrlist2; #else static struct hostent user_he2; static struct nwrap_vector user_addrlist2; #endif /* BSD */ static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b, const char *name, int af) { int ret; (void) b; /* unused */ ret = nwrap_files_internal_gethostbyname(name, af, &user_he2, &user_addrlist2); if (ret == 0) { return &user_he2; } return NULL; } static struct hostent *nwrap_gethostbyname2(const char *name, int af) { size_t i; struct hostent *he = NULL; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; he = b->ops->nw_gethostbyname2(b, name, af); if (he != NULL) { return he; } } return NULL; } struct hostent *gethostbyname2(const char *name, int af) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyname2(name, af); } return nwrap_gethostbyname2(name, af); } #endif static struct hostent *nwrap_gethostbyaddr(const void *addr, socklen_t len, int type) { size_t i; struct hostent *he = NULL; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; he = b->ops->nw_gethostbyaddr(b, addr, len, type); if (he != NULL) { return he; } } return NULL; } struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) { if (!nss_wrapper_hosts_enabled()) { return libc_gethostbyaddr(addr, len, type); } return nwrap_gethostbyaddr(addr, len, type); } static const struct addrinfo default_hints = { .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED, .ai_family = AF_UNSPEC, .ai_socktype = 0, .ai_protocol = 0, .ai_addrlen = 0, .ai_addr = NULL, .ai_canonname = NULL, .ai_next = NULL }; static int nwrap_convert_he_ai(const struct hostent *he, unsigned short port, const struct addrinfo *hints, struct addrinfo **pai, bool skip_canonname) { struct addrinfo *ai; socklen_t socklen; if (he == NULL) { return EAI_MEMORY; } switch (he->h_addrtype) { case AF_INET: socklen = sizeof(struct sockaddr_in); break; #ifdef HAVE_IPV6 case AF_INET6: socklen = sizeof(struct sockaddr_in6); break; #endif default: return EAI_FAMILY; } ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen); if (ai == NULL) { return EAI_MEMORY; } ai->ai_flags = hints->ai_flags; ai->ai_family = he->h_addrtype; ai->ai_socktype = hints->ai_socktype; ai->ai_protocol = hints->ai_protocol; ai->ai_canonname = NULL; if (ai->ai_socktype == 0) { ai->ai_socktype = SOCK_DGRAM; } if (ai->ai_protocol == 0) { if (ai->ai_socktype == SOCK_DGRAM) { ai->ai_protocol = IPPROTO_UDP; } else if (ai->ai_socktype == SOCK_STREAM) { ai->ai_protocol = IPPROTO_TCP; } } ai->ai_addrlen = socklen; ai->ai_addr = (void *)(ai + 1); #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN ai->ai_addr->sa_len = socklen; #endif ai->ai_addr->sa_family = he->h_addrtype; switch (he->h_addrtype) { case AF_INET: { union { struct sockaddr *sa; struct sockaddr_in *in; } addr; addr.sa = ai->ai_addr; memset(addr.in, 0, sizeof(struct sockaddr_in)); addr.in->sin_port = htons(port); addr.in->sin_family = AF_INET; memset(addr.in->sin_zero, '\0', sizeof (addr.in->sin_zero)); memcpy(&(addr.in->sin_addr), he->h_addr_list[0], he->h_length); } break; #ifdef HAVE_IPV6 case AF_INET6: { union { struct sockaddr *sa; struct sockaddr_in6 *in6; } addr; addr.sa = ai->ai_addr; memset(addr.in6, 0, sizeof(struct sockaddr_in6)); addr.in6->sin6_port = htons(port); addr.in6->sin6_family = AF_INET6; memcpy(&addr.in6->sin6_addr, he->h_addr_list[0], he->h_length); } break; #endif } ai->ai_next = NULL; if (he->h_name && !skip_canonname) { ai->ai_canonname = strdup(he->h_name); if (ai->ai_canonname == NULL) { freeaddrinfo(ai); return EAI_MEMORY; } } *pai = ai; return 0; } static int nwrap_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *ai = NULL; unsigned short port = 0; struct { int family; union { struct in_addr v4; #ifdef HAVE_IPV6 struct in6_addr v6; } in; #endif } addr = { .family = AF_UNSPEC, }; int rc; if (node == NULL && service == NULL) { return EAI_NONAME; } if (hints == NULL) { hints = &default_hints; } /* EAI_BADFLAGS hints.ai_flags contains invalid flags; or, hints.ai_flags included AI_CANONNAME and name was NULL. */ if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) { return EAI_BADFLAGS; } /* If no node has been specified, let glibc deal with it */ if (node == NULL) { int ret; struct addrinfo *p = NULL; ret = libc_getaddrinfo(node, service, hints, &p); if (ret == 0) { *res = p; } return ret; } if (service != NULL && service[0] != '\0') { const char *proto = NULL; struct servent *s; char *end_ptr; long sl; errno = 0; sl = strtol(service, &end_ptr, 10); if (*end_ptr == '\0') { port = sl; goto valid_port; } else if (hints->ai_flags & AI_NUMERICSERV) { return EAI_NONAME; } if (hints->ai_protocol != 0) { struct protoent *pent; pent = getprotobynumber(hints->ai_protocol); if (pent != NULL) { proto = pent->p_name; } } s = getservbyname(service, proto); if (s == NULL) { return EAI_NONAME; } port = ntohs(s->s_port); } valid_port: rc = inet_pton(AF_INET, node, &addr.in.v4); if (rc == 1) { addr.family = AF_INET; } #ifdef HAVE_IPV6 if (addr.family == AF_UNSPEC) { rc = inet_pton(AF_INET6, node, &addr.in.v6); if (rc == 1) { addr.family = AF_INET6; } } #endif if (addr.family == AF_UNSPEC) { if (hints->ai_flags & AI_NUMERICHOST) { return EAI_NONAME; } } else if ((hints->ai_family != AF_UNSPEC) && (hints->ai_family != addr.family)) { return EAI_ADDRFAMILY; } rc = nwrap_files_getaddrinfo(node, port, hints, &ai); if (rc != 0) { int ret; struct addrinfo *p = NULL; ret = libc_getaddrinfo(node, service, hints, &p); if (ret == 0) { /* * nwrap_files_getaddrinfo failed, but libc was * successful -- use the result from libc. */ *res = p; return 0; } return rc; } /* * If the socktype was not specified, duplicate * each ai returned, so that we have variants for * both UDP and TCP. */ if (hints->ai_socktype == 0) { struct addrinfo *ai_cur; /* freeaddrinfo() frees ai_canonname and ai so allocate them */ for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) { struct addrinfo *ai_new; /* duplicate the current entry */ ai_new = malloc(sizeof(struct addrinfo)); if (ai_new == NULL) { freeaddrinfo(ai); return EAI_MEMORY; } memcpy(ai_new, ai_cur, sizeof(struct addrinfo)); ai_new->ai_next = NULL; /* We need a deep copy or freeaddrinfo() will blow up */ if (ai_cur->ai_canonname != NULL) { ai_new->ai_canonname = strdup(ai_cur->ai_canonname); } if (ai_cur->ai_socktype == SOCK_DGRAM) { ai_new->ai_socktype = SOCK_STREAM; } else if (ai_cur->ai_socktype == SOCK_STREAM) { ai_new->ai_socktype = SOCK_DGRAM; } if (ai_cur->ai_protocol == IPPROTO_TCP) { ai_new->ai_protocol = IPPROTO_UDP; } else if (ai_cur->ai_protocol == IPPROTO_UDP) { ai_new->ai_protocol = IPPROTO_TCP; } /* now insert the new entry */ ai_new->ai_next = ai_cur->ai_next; ai_cur->ai_next = ai_new; /* and move on (don't duplicate the new entry) */ ai_cur = ai_new; } } *res = ai; return 0; } int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { if (!nss_wrapper_hosts_enabled()) { return libc_getaddrinfo(node, service, hints, res); } return nwrap_getaddrinfo(node, service, hints, res); } static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct hostent *he; struct servent *service; const char *proto; const void *addr; socklen_t addrlen; uint16_t port; sa_family_t type; size_t i; if (sa == NULL || salen < sizeof(sa_family_t)) { return EAI_FAMILY; } if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) { return EAI_NONAME; } type = sa->sa_family; switch (type) { case AF_INET: { union { const struct sockaddr *sa; const struct sockaddr_in *in; } a; if (salen < sizeof(struct sockaddr_in)) { return EAI_FAMILY; } a.sa = sa; addr = &(a.in->sin_addr); addrlen = sizeof(a.in->sin_addr); port = ntohs(a.in->sin_port); break; } #ifdef HAVE_IPV6 case AF_INET6: { union { const struct sockaddr *sa; const struct sockaddr_in6 *in6; } a; if (salen < sizeof(struct sockaddr_in6)) { return EAI_FAMILY; } a.sa = sa; addr = &(a.in6->sin6_addr); addrlen = sizeof(a.in6->sin6_addr); port = ntohs(a.in6->sin6_port); break; } #endif default: return EAI_FAMILY; } if (host != NULL) { he = NULL; if ((flags & NI_NUMERICHOST) == 0) { for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; he = b->ops->nw_gethostbyaddr(b, addr, addrlen, type); if (he != NULL) { break; } } if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL)) return EAI_NONAME; } if (he != NULL && he->h_name != NULL) { if (strlen(he->h_name) >= hostlen) return EAI_OVERFLOW; snprintf(host, hostlen, "%s", he->h_name); if (flags & NI_NOFQDN) host[strcspn(host, ".")] = '\0'; } else { if (inet_ntop(type, addr, host, hostlen) == NULL) return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL; } } if (serv != NULL) { service = NULL; if ((flags & NI_NUMERICSERV) == 0) { proto = (flags & NI_DGRAM) ? "udp" : "tcp"; service = getservbyport(htons(port), proto); } if (service != NULL) { if (strlen(service->s_name) >= servlen) return EAI_OVERFLOW; snprintf(serv, servlen, "%s", service->s_name); } else { if (snprintf(serv, servlen, "%u", port) >= (int) servlen) return EAI_OVERFLOW; } } return 0; } #ifdef HAVE_LINUX_GETNAMEINFO int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) #elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED) int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, unsigned int flags) #else int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) #endif { if (!nss_wrapper_hosts_enabled()) { return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } static int nwrap_gethostname(char *name, size_t len) { const char *hostname = getenv("NSS_WRAPPER_HOSTNAME"); if (strlen(hostname) >= len) { errno = ENAMETOOLONG; return -1; } snprintf(name, len, "%s", hostname); return 0; } #ifdef HAVE_SOLARIS_GETHOSTNAME int gethostname(char *name, int len) #else /* HAVE_SOLARIS_GETHOSTNAME */ int gethostname(char *name, size_t len) #endif /* HAVE_SOLARIS_GETHOSTNAME */ { if (!nwrap_hostname_enabled()) { return libc_gethostname(name, len); } return nwrap_gethostname(name, len); } static void nwrap_thread_prepare(void) { nwrap_init(); NWRAP_LOCK_ALL; } static void nwrap_thread_parent(void) { NWRAP_UNLOCK_ALL; } static void nwrap_thread_child(void) { NWRAP_REINIT_ALL; } /**************************** * CONSTRUCTOR ***************************/ void nwrap_constructor(void) { NWRAP_REINIT_ALL; /* * If we hold a lock and the application forks, then the child * is not able to unlock the mutex and we are in a deadlock. * * Setting these handlers should prevent such deadlocks. */ pthread_atfork(&nwrap_thread_prepare, &nwrap_thread_parent, &nwrap_thread_child); /* Do not call nwrap_init() here. */ } /**************************** * DESTRUCTOR ***************************/ /* * This function is called when the library is unloaded and makes sure that * sockets get closed and the unix file for the socket are unlinked. */ void nwrap_destructor(void) { size_t i; NWRAP_LOCK_ALL; if (nwrap_main_global != NULL) { struct nwrap_main *m = nwrap_main_global; /* libc */ if (m->libc != NULL) { if (m->libc->handle != NULL #ifdef RTLD_NEXT && m->libc->handle != RTLD_NEXT #endif ) { dlclose(m->libc->handle); } if (m->libc->nsl_handle != NULL #ifdef RTLD_NEXT && m->libc->nsl_handle != RTLD_NEXT #endif ) { dlclose(m->libc->nsl_handle); } if (m->libc->sock_handle != NULL #ifdef RTLD_NEXT && m->libc->sock_handle != RTLD_NEXT #endif ) { dlclose(m->libc->sock_handle); } SAFE_FREE(m->libc); } /* backends */ if (m->backends != NULL) { for (i = 0; i < m->num_backends; i++) { struct nwrap_backend *b = &(m->backends[i]); if (b->so_handle != NULL) { dlclose(b->so_handle); } SAFE_FREE(b->symbols); } SAFE_FREE(m->backends); } } if (nwrap_pw_global.cache != NULL) { struct nwrap_cache *c = nwrap_pw_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } SAFE_FREE(nwrap_pw_global.list); nwrap_pw_global.num = 0; } if (nwrap_gr_global.cache != NULL) { struct nwrap_cache *c = nwrap_gr_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } SAFE_FREE(nwrap_gr_global.list); nwrap_pw_global.num = 0; } #if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) if (nwrap_sp_global.cache != NULL) { struct nwrap_cache *c = nwrap_sp_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } nwrap_sp_global.num = 0; } #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */ if (nwrap_he_global.cache != NULL) { struct nwrap_cache *c = nwrap_he_global.cache; nwrap_files_cache_unload(c); if (c->fd >= 0) { fclose(c->fp); c->fd = -1; } nwrap_he_global.num = 0; } free(user_addrlist.items); #ifdef HAVE_GETHOSTBYNAME2 free(user_addrlist2.items); #endif hdestroy(); NWRAP_UNLOCK_ALL; } nss_wrapper-1.1.15/src/CMakeLists.txt000644 001750 000144 00000002227 14364217634 017466 0ustar00asnusers000000 000000 project(libnss_wrapper C) add_library(nss_utils STATIC nss_utils.c) target_compile_options(nss_utils PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) add_library(nss_wrapper SHARED nss_wrapper.c) target_compile_options(nss_wrapper PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) if (BSD) target_compile_options(nss_wrapper PRIVATE -DBSD) endif() target_include_directories(nss_wrapper PRIVATE ${CMAKE_BINARY_DIR}) target_link_libraries(nss_wrapper nss_utils ${NWRAP_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties( nss_wrapper PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} ) install(TARGETS nss_wrapper RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_L_LIBDIR}) set(NSS_WRAPPER_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}nss_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}" PARENT_SCOPE) nss_wrapper-1.1.15/src/nss_utils.c000644 001750 000144 00000007042 14364206715 017113 0ustar00asnusers000000 000000 /* * BSD 3-Clause License * * Copyright (c) 2007, Stefan Metzmacher * Copyright (c) 2009, Guenther Deschner * Copyright (c) 2014-2015, Michael Adam * Copyright (c) 2015, Robin Hack * Copyright (c) 2013-2018, Andreas Schneider * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include "nss_utils.h" int nwrap_gr_copy_r(const struct group *src, struct group *dst, char *buf, size_t buflen, struct group **dstp) { char *p = NULL; uintptr_t align = 0; unsigned int gr_mem_cnt = 0; unsigned i; size_t total_len; size_t gr_name_len = strlen(src->gr_name) + 1; size_t gr_passwd_len = strlen(src->gr_passwd) + 1; union { char *ptr; char **data; } g_mem; for (i = 0; src->gr_mem[i] != NULL; i++) { gr_mem_cnt++; } /* Align the memory for storing pointers */ align = __alignof__(char *) - ((p - (char *)0) % __alignof__(char *)); total_len = align + (1 + gr_mem_cnt) * sizeof(char *) + gr_name_len + gr_passwd_len; if (total_len > buflen) { errno = ERANGE; return -1; } buflen -= total_len; /* gr_mem */ p = buf + align; g_mem.ptr = p; dst->gr_mem = g_mem.data; /* gr_name */ p += (1 + gr_mem_cnt) * sizeof(char *); dst->gr_name = p; /* gr_passwd */ p += gr_name_len; dst->gr_passwd = p; /* gr_mem[x] */ p += gr_passwd_len; /* gr_gid */ dst->gr_gid = src->gr_gid; memcpy(dst->gr_name, src->gr_name, gr_name_len); memcpy(dst->gr_passwd, src->gr_passwd, gr_passwd_len); /* Set the terminating entry */ dst->gr_mem[gr_mem_cnt] = NULL; /* Now add the group members content */ total_len = 0; for (i = 0; i < gr_mem_cnt; i++) { size_t len = strlen(src->gr_mem[i]) + 1; dst->gr_mem[i] = p; total_len += len; p += len; } if (total_len > buflen) { errno = ERANGE; return -1; } for (i = 0; i < gr_mem_cnt; i++) { size_t len = strlen(src->gr_mem[i]) + 1; memcpy(dst->gr_mem[i], src->gr_mem[i], len); } if (dstp != NULL) { *dstp = dst; } return 0; } nss_wrapper-1.1.15/src/nss_utils.h000644 001750 000144 00000004011 14364206715 017111 0ustar00asnusers000000 000000 /* * BSD 3-Clause License * * Copyright (c) 2007, Stefan Metzmacher * Copyright (c) 2009, Guenther Deschner * Copyright (c) 2014-2015, Michael Adam * Copyright (c) 2015, Robin Hack * Copyright (c) 2013-2018, Andreas Schneider * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef NSS_UTILS_H #define NSS_UTILS_H #include int nwrap_gr_copy_r(const struct group *src, struct group *dst, char *buf, size_t buflen, struct group **dstp); #endif //NSS_UTILS_H nss_wrapper-1.1.15/CTestConfig.cmake000644 001750 000144 00000000430 13634203624 017274 0ustar00asnusers000000 000000 set(UPDATE_TYPE "true") set(CTEST_PROJECT_NAME "nss_wrapper") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_DROP_METHOD "https") set(CTEST_DROP_SITE "test.cmocka.org") set(CTEST_DROP_LOCATION "/submit.php?project=${CTEST_PROJECT_NAME}") set(CTEST_DROP_SITE_CDASH TRUE) nss_wrapper-1.1.15/TODO000644 001750 000144 00000000453 13634203624 014617 0ustar00asnusers000000 000000 TODO ===== Library -------- * Replace hcreate() as it messes with applications also using it. Testing -------- * Split the testsuite in several tests. * Add missing tests. Check the code coverage on http://mock.cryptomilk.org/index.php?project=nsswrapper to see what tests are still needed. nss_wrapper-1.1.15/CHANGELOG000644 001750 000144 00000006114 14364246635 015353 0ustar00asnusers000000 000000 ChangeLog ========== version 1.1.15 (released 2023-01-25) * Fixed linking issue in tests * Fixed a memory leak in tests version 1.1.14 (released 2023-01-25) * Fixed implementation of initgroups() * Fixed implementation of getgrouplist() * Avoid dclose(RTLD_NEXT) version 1.1.13 (released 2022-10-09) * Fixed possible mutex and threading issues version 1.1.12 (released 2022-06-24) * Added (de)contructor support on AIX with pragma init/finish * Fixed possible crash in getaddrinfo() * Fixed issues with processes closing all fds when forking * Fixed issues with setgrent() and endpwent() nss module support version 1.1.11 (released 2020-04-02) * Fixed strict aliasing issues on armv7hl (32bit) version 1.1.10 (released 2020-03-19) * Fixed crash bug in OpenLDAP libraries with gethostbyname_r() * Code cleanup in gethostbyname(2)(_r) functions version 1.1.9 (released 2020-03-16) * Fixed log spam when loading modules version 1.1.8 (released 2020-02-17) * Fixed path to library in nss_wrapper.pc * Try different backends for gethostbyaddr nd gethostbyname version 1.1.7 (released 2019-11-11) * Added NSS_WRAPPER_DISABLE_DEEPBIND env variable * Improvded logging * Fixed location in cmake config version 1.1.6 (released 2019-05-19) * Fixed issues with memory alignment of getgrnam() * Fixed getpwnam() on FreeBSD * Started to use modern cmake (>= 3.5.0) version 1.1.5 (released 2018-10-31) * Fixed running on older distributions version 1.1.4 (released 2018-10-31) * Fixed module getpw* functions * Fixed nss_wrapper.pl to use correct perl binary * Fixed compatibility with musl-libc version 1.1.3 (released 2015-03-18) * Added support for BSD 'struct passwd' members * Replaced strcpy() with snprintf() version 1.1.2 (released 2015-12-17) * Fixed segfault while reloading hosts file * Fixed issue where are not fault tolerant if an alias has already been added version 1.1.1 (released 2015-11-23) * Fixed nss_wrapper build on Solaris version 1.1.0 (released 2015-11-20) * Added support for initgroups() * Added support for shadow files (getspnam(), etc.) * Improved support for multi address handling in getaddrinfo() * Improved file parser * Fixed compilation on machines without IPv4 support * Fixed service string sanity check in getaddrinfo() (bso #11501) * Fixed AI_NUMERICHOST handling in getaddrinfo() (bso # 11477) version 1.0.3 (released 2014-09-11) * Added a nss_wrapper manpage. * Fixed cmake find_package configs. * Fixed resolving hostnames with a trailing dot. * Fixed an overflow when checking if a IPv6 address is IPv4. * Fall back to RTLD_NEXT for symbol binding if we can't find libc. version 1.0.2 (released 2014-04-08) * Added public nss_wrapper_enabled(). * Added public nss_wrapper_hosts_enabled(). * Fixed segfault in 'getent hosts' without aliases. * Fixed IPv4 and IPv6 resolving with 'getent ahosts'. version 1.0.1 (released 2014-02-04) * Added --libs to pkg-config. * Added nss_wrapper-config.cmake * Fixed a bug packaging the obj directory. version 1.0.0 (released 2014-02-02) * Initial release nss_wrapper-1.1.15/CompilerChecks.cmake000644 001750 000144 00000012335 14255266062 020033 0ustar00asnusers000000 000000 include(AddCCompilerFlag) include(CheckCCompilerFlagSSP) if (UNIX) # # Check for -Werror turned on if possible # # This will prevent that compiler flags are detected incorrectly. # check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR) if (REQUIRED_FLAGS_WERROR) set(CMAKE_REQUIRED_FLAGS "-Werror") if (PICKY_DEVELOPER) list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror") endif() endif() add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS) #add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS) #add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS) check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT) if (REQUIRED_FLAGS_WFORMAT) list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat") set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat") endif() add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS) # Allow zero for a variadic macro argument string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID) if ("${_C_COMPILER_ID}" STREQUAL "clang") add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS) endif() add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel)) add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS) endif() endif() if (NOT SOLARIS) check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG) if (WITH_STACK_PROTECTOR_STRONG) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong") # This is needed as Solaris has a seperate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong") endif() else (WITH_STACK_PROTECTOR_STRONG) check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector") # This is needed as Solaris has a seperate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector") endif() endif() endif (WITH_STACK_PROTECTOR_STRONG) check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION) if (WITH_STACK_CLASH_PROTECTION) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection") endif() endif() if (PICKY_DEVELOPER) add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS) endif() # Unset CMAKE_REQUIRED_FLAGS unset(CMAKE_REQUIRED_FLAGS) endif() if (MSVC) add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS) endif() if (SUPPORTED_COMPILER_FLAGS) set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE) endif() if (SUPPORTED_LINKER_FLAGS) set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE) endif() nss_wrapper-1.1.15/tests/000755 001750 000144 00000000000 14364246777 015310 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/tests/test_shadow.c000644 001750 000144 00000002457 13634203624 017767 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include static void test_nwrap_getspent(void **state) { struct spwd *sp; uint32_t i; (void)state; /* unused */ setspent(); for (sp = getspent(), i = 0; sp != NULL; sp = getspent(), i++) { if (i == 0) { assert_string_equal(sp->sp_namp, "alice"); } else { assert_string_equal(sp->sp_namp, "bob"); } } endspent(); } static void test_nwrap_getspnam(void **state) { char *encrypted_password; struct spwd *sp; (void)state; /* unused */ sp = getspnam("alice"); assert_non_null(sp); assert_string_equal(sp->sp_namp, "alice"); encrypted_password = crypt("secret", sp->sp_pwdp); assert_non_null(encrypted_password); assert_string_equal(encrypted_password, sp->sp_pwdp); sp = getspnam("bob"); assert_non_null(sp); assert_string_equal(sp->sp_namp, "bob"); encrypted_password = crypt("secret", sp->sp_pwdp); assert_non_null(encrypted_password); assert_string_equal(encrypted_password, sp->sp_pwdp); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getspent), cmocka_unit_test(test_nwrap_getspnam), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/shadow.in000644 001750 000144 00000000356 13634203624 017110 0ustar00asnusers000000 000000 alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/:1:0:99999:7::: bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/:2:0:99999:7::: nss_wrapper-1.1.15/tests/test_nwrap_disabled.c000644 001750 000144 00000004527 13634203624 021460 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_passwd_group(void **state) { struct passwd *pwd; struct group *grp; (void) state; /* unused */ pwd = getpwuid(getuid()); assert_non_null(pwd); pwd = getpwnam(pwd->pw_name); assert_non_null(pwd); grp = getgrgid(pwd->pw_gid); assert_non_null(grp); grp = getgrnam(grp->gr_name); assert_non_null(grp); } /* Test libnsl */ static void test_nwrap_hostent(void **state) { #ifdef HAVE_NONNULL_GETHOSTENT struct hostent *he; (void) state; /* unused */ sethostent(0); he = gethostent(); assert_non_null(he); endhostent(); #else (void) state; /* unused */ sethostent(0); gethostent(); endhostent(); #endif } static void test_nwrap_gethostname(void **state) { char host[256] = {0}; int rc; (void) state; /* unused */ rc = gethostname(host, sizeof(host)); assert_int_equal(rc, 0); assert_true(strlen(host) > 1); } static void test_nwrap_getaddrinfo_local(void **state) { struct addrinfo hints; struct addrinfo *res; union { struct sockaddr *sa; struct sockaddr_in *in; } addr; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; rc = getaddrinfo("127.0.0.1", NULL, &hints, &res); assert_int_equal(rc, 0); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); #ifdef HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES assert_string_equal(res->ai_canonname, "127.0.0.1"); #else /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ assert_null(res->ai_canonname); #endif /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ addr.sa = res->ai_addr; assert_int_equal(ntohl(addr.in->sin_addr.s_addr), INADDR_LOOPBACK); freeaddrinfo(res); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_passwd_group), cmocka_unit_test(test_nwrap_hostent), cmocka_unit_test(test_nwrap_gethostname), cmocka_unit_test(test_nwrap_getaddrinfo_local), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/valgrind.supp000644 001750 000144 00000001026 13634203624 020005 0ustar00asnusers000000 000000 ### GLIBC { glibc_dlopen_worker_alloc Memcheck:Leak fun:*alloc ... fun:dl_open_worker fun:_dl_catch_error fun:_dl_open fun:dlopen_doit fun:_dl_catch_error fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 } { glibc_dlopen_alloc Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 } { glibc_dlclose_alloc Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlclose } { glibc___sha512_crypt_alloc Memcheck:Leak fun:malloc fun:realloc fun:__sha512_crypt } nss_wrapper-1.1.15/tests/test_getnameinfo.c000644 001750 000144 00000016565 13634203624 021003 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_getnameinfo(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(53); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "magrathea.galaxy.site"); assert_string_equal(serv, "domain"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(53); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); assert_string_equal(serv, "domain"); } static void test_nwrap_getnameinfo_numeric(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(53); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_NUMERICHOST; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "127.0.0.11"); assert_string_equal(serv, "domain"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(53); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); flags = NI_NUMERICSERV; rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); assert_string_equal(serv, "53"); } static void test_nwrap_getnameinfo_any(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "0.0.0.0", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "0.0.0.0"); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "::"); assert_string_equal(serv, "ssh"); } static void test_nwrap_getnameinfo_local(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "127.0.0.1"); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "::1"); assert_string_equal(serv, "ssh"); } static void test_nwrap_getnameinfo_null(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; struct sockaddr_in6 sin6; int flags = 0; int rc; (void) state; /* unused */ rc = getnameinfo(NULL, 0, host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, EAI_FAMILY); /* IPv4 */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), NULL, 0, serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "ssh"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), host, sizeof(host), NULL, 0, flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); /* IPv6 */ sin6.sin6_family = AF_INET6; sin6.sin6_port = htons(22); rc = inet_pton(AF_INET6, "::13", &sin6.sin6_addr); assert_int_equal(rc, 1); rc = getnameinfo((const struct sockaddr *)&sin6, sizeof(struct sockaddr_in6), NULL, 0, NULL, 0, flags); assert_int_equal(rc, 0); assert_string_equal(host, "beteigeuze.galaxy.site"); } static void test_nwrap_getnameinfo_flags(void **state) { char host[256] = {0}; char serv[256] = {0}; struct sockaddr_in sin; int flags = 0; int rc; (void) state; /* unused */ /* NI_NAMEREQD */ sin.sin_family = AF_INET; sin.sin_port = htons(22); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_NAMEREQD; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), NULL, 0, NULL, 0, flags); assert_int_equal(rc, EAI_NONAME); /* NI_DGRAM */ sin.sin_family = AF_INET; sin.sin_port = htons(513); rc = inet_pton(AF_INET, "127.0.0.11", &sin.sin_addr); assert_int_equal(rc, 1); flags = NI_DGRAM; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "who"); /* STREAM (port 513) */ flags = 0; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(serv, "login"); /* NI_NOFQDN */ flags = NI_NOFQDN; rc = getnameinfo((const struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, sizeof(host), serv, sizeof(serv), flags); assert_int_equal(rc, 0); assert_string_equal(host, "magrathea"); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getnameinfo), cmocka_unit_test(test_nwrap_getnameinfo_numeric), cmocka_unit_test(test_nwrap_getnameinfo_any), cmocka_unit_test(test_nwrap_getnameinfo_local), cmocka_unit_test(test_nwrap_getnameinfo_null), cmocka_unit_test(test_nwrap_getnameinfo_flags), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/testsuite.c000644 001750 000144 00000047417 13634217552 017506 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include /* * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h gives us * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on * Solaris */ #ifndef _POSIX_PTHREAD_SEMANTICS #define _POSIX_PTHREAD_SEMANTICS #endif #include #include #include #include #include #include #ifdef NDEBUG #define DEBUG(...) #else #define DEBUG(...) printf(__VA_ARGS__) #endif #ifndef SAFE_FREE #define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) #endif static void assert_passwd_equal(const struct passwd *p1, const struct passwd *p2) { assert_string_equal(p1->pw_name, p2->pw_name); assert_string_equal(p1->pw_passwd, p2->pw_passwd); assert_int_equal(p1->pw_uid, p2->pw_uid); assert_int_equal(p1->pw_gid, p2->pw_gid); assert_string_equal(p1->pw_gecos, p2->pw_gecos); assert_string_equal(p1->pw_dir, p2->pw_dir); assert_string_equal(p1->pw_shell, p2->pw_shell); } static void assert_group_equal(const struct group *g1, const struct group *g2) { int i; assert_string_equal(g1->gr_name, g2->gr_name); assert_string_equal(g1->gr_passwd, g2->gr_passwd); assert_int_equal(g1->gr_gid, g2->gr_gid); assert_false(g1->gr_mem != NULL && g2->gr_mem == NULL); assert_false(g1->gr_mem == NULL && g2->gr_mem != NULL); if (g1->gr_mem == NULL && g2->gr_mem == NULL) { return; } for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) { assert_string_equal(g1->gr_mem[i], g2->gr_mem[i]); } } static bool copy_passwd(const struct passwd *pwd, struct passwd *p) { p->pw_name = strdup(pwd->pw_name); p->pw_passwd = strdup(pwd->pw_passwd); p->pw_uid = pwd->pw_uid; p->pw_gid = pwd->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_CLASS p->pw_class = strdup(pwd->pw_class); #endif #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE p->pw_change = pwd->pw_change; #endif #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE p->pw_expire = pwd->pw_expire; #endif p->pw_gecos = strdup(pwd->pw_gecos); p->pw_dir = strdup(pwd->pw_dir); p->pw_shell = strdup(pwd->pw_shell); return true; } static void free_passwd(struct passwd *p) { SAFE_FREE(p->pw_name); SAFE_FREE(p->pw_passwd); #ifdef HAVE_STRUCT_PASSWD_PW_CLASS SAFE_FREE(p->pw_class); #endif SAFE_FREE(p->pw_gecos); SAFE_FREE(p->pw_dir); SAFE_FREE(p->pw_shell); } static void free_passwds(struct passwd *pwds, size_t num_pwds) { size_t i; for(i = 0; i < num_pwds; i++) { free_passwd(&pwds[i]); } free(pwds); } static void print_passwd(struct passwd *pwd) { (void)pwd; DEBUG("%s:%s:%lu:%lu:%s:%s:%s\n", pwd->pw_name, pwd->pw_passwd, (unsigned long)pwd->pw_uid, (unsigned long)pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); } static bool test_nwrap_getpwnam(const char *name, struct passwd *pwd_p) { struct passwd *pwd = NULL; bool ok; DEBUG("Testing getpwnam: %s\n", name); pwd = getpwnam(name); if (pwd == NULL) { return false; } print_passwd(pwd); if (pwd_p == NULL) { return true; } ok = copy_passwd(pwd, pwd_p); return ok; } static void test_nwrap_getpwnam_r(const char *name, struct passwd *pwd_p) { struct passwd pwd, *pwdp; char buffer[4096]; int ret; DEBUG("Testing getpwnam_r: %s\n", name); ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } assert_ptr_equal(&pwd, pwdp); print_passwd(&pwd); if (pwd_p) { copy_passwd(&pwd, pwd_p); } } static bool test_nwrap_getpwuid(uid_t uid, struct passwd *pwd_p) { struct passwd *pwd = NULL; bool ok; DEBUG("Testing getpwuid: %lu\n", (unsigned long)uid); pwd = getpwuid(uid); if (pwd == NULL) { return false; } print_passwd(pwd); if (pwd_p == NULL) { return true; } ok = copy_passwd(pwd, pwd_p); return ok; } static bool test_nwrap_getpwuid_r(uid_t uid, struct passwd *pwd_p) { struct passwd pwd, *pwdp; char buffer[4096]; int ret; DEBUG("Testing getpwuid_r: %lu\n", (unsigned long)uid); ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } assert_ptr_equal(&pwd, pwdp); print_passwd(&pwd); if (pwd_p) { copy_passwd(&pwd, pwd_p); } return true; } static bool copy_group(const struct group *grp, struct group *g) { int i; g->gr_name = strdup(grp->gr_name); g->gr_passwd = strdup(grp->gr_passwd); g->gr_gid = grp->gr_gid; g->gr_mem = NULL; for (i = 0; grp->gr_mem != NULL && grp->gr_mem[i] != NULL; i++) { char **mem; mem = realloc(g->gr_mem, sizeof(char *) * (i + 2)); assert_non_null(mem); g->gr_mem = mem; g->gr_mem[i] = strdup(grp->gr_mem[i]); assert_non_null(g->gr_mem[i]); g->gr_mem[i + 1] = NULL; } return true; } static void free_group(struct group *g) { SAFE_FREE(g->gr_name); SAFE_FREE(g->gr_passwd); if (g->gr_mem != NULL) { int i; for (i = 0; g->gr_mem[i] != NULL; i++) { SAFE_FREE(g->gr_mem[i]); } SAFE_FREE(g->gr_mem); } } static void free_groups(struct group *grps, size_t num_grps) { size_t i; for(i = 0; i < num_grps; i++) { free_group(&grps[i]); } free(grps); } static void print_group(struct group *grp) { int i; DEBUG("%s:%s:%lu:", grp->gr_name, grp->gr_passwd, (unsigned long)grp->gr_gid); if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) { DEBUG("\n"); return; } for (i=0; grp->gr_mem[i+1]; i++) { DEBUG("%s,", grp->gr_mem[i]); } DEBUG("%s\n", grp->gr_mem[i]); } static bool test_nwrap_getgrnam(const char *name, struct group *grp_p) { struct group *grp = NULL; bool ok; DEBUG("Testing getgrnam: %s\n", name); grp = getgrnam(name); if (grp == NULL) { return false; } print_group(grp); if (grp_p == NULL) { return true; } ok = copy_group(grp, grp_p); return ok; } static bool test_nwrap_getgrnam_r(const char *name, struct group *grp_p) { struct group grp, *grpp; char buffer[4096]; int ret; DEBUG("Testing getgrnam_r: %s\n", name); ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } assert_ptr_equal(&grp, grpp); print_group(&grp); if (grp_p) { copy_group(&grp, grp_p); } return true; } static bool test_nwrap_getgrgid(gid_t gid, struct group *grp_p) { struct group *grp = NULL; bool ok; DEBUG("Testing getgrgid: %lu\n", (unsigned long)gid); grp = getgrgid(gid); if (grp == NULL) { return false; } print_group(grp); if (grp_p == NULL) { return true; } ok = copy_group(grp, grp_p); return ok; } static bool test_nwrap_getgrgid_r(gid_t gid, struct group *grp_p) { struct group grp, *grpp; char buffer[4096]; int ret; DEBUG("Testing getgrgid_r: %lu\n", (unsigned long)gid); ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } assert_true(ret); } assert_ptr_equal(&grp, grpp); print_group(&grp); if (grp_p) { copy_group(&grp, grp_p); } return true; } static bool test_nwrap_enum_passwd(struct passwd **pwd_array_p, size_t *num_pwd_p) { struct passwd *pwd; struct passwd *pwd_array = NULL; size_t num_pwd = 0; DEBUG("Testing setpwent\n"); setpwent(); while ((pwd = getpwent()) != NULL) { DEBUG("Testing getpwent\n"); print_passwd(pwd); if (pwd_array_p && num_pwd_p) { pwd_array = realloc(pwd_array, sizeof(struct passwd) * (num_pwd + 1)); assert_non_null(pwd_array); copy_passwd(pwd, &pwd_array[num_pwd]); num_pwd++; } } DEBUG("Testing endpwent\n"); endpwent(); if (pwd_array_p) { *pwd_array_p = pwd_array; } if (num_pwd_p) { *num_pwd_p = num_pwd; } return true; } static bool test_nwrap_enum_r_passwd(struct passwd **pwd_array_p, size_t *num_pwd_p) { struct passwd *pwd_array = NULL; size_t num_pwd = 0; /* Skip these tests if the platform does not provide getpwent_r() */ #ifdef HAVE_GETPWENT_R struct passwd pwd, *pwdp; char buffer[4096]; int ret; DEBUG("Testing setpwent\n"); setpwent(); while (1) { DEBUG("Testing getpwent_r\n"); #ifdef HAVE_SOLARIS_GETPWENT_R pwdp = getpwent_r(&pwd, buffer, sizeof(buffer)); if (pwdp == NULL) { break; } #else /* HAVE_SOLARIS_GETPWENT_R */ ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } break; } #endif /* HAVE_SOLARIS_GETPWENT_R */ print_passwd(&pwd); if (pwd_array_p && num_pwd_p) { pwd_array = realloc(pwd_array, sizeof(struct passwd) * (num_pwd + 1)); assert_non_null(pwd_array); copy_passwd(&pwd, &pwd_array[num_pwd]); num_pwd++; } } DEBUG("Testing endpwent\n"); endpwent(); #endif /* HAVE_GETPWENT_R */ if (pwd_array_p) { *pwd_array_p = pwd_array; } if (num_pwd_p) { *num_pwd_p = num_pwd; } return true; } static bool test_nwrap_passwd(void) { struct passwd *pwd, pwd1, pwd2; size_t i, num_pwd; test_nwrap_enum_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); free_passwd(&pwd1); free_passwd(&pwd2); } free_passwds(pwd, num_pwd); return true; } static void test_nwrap_passwd_r(void) { struct passwd *pwd, pwd1, pwd2; size_t i, num_pwd; test_nwrap_enum_r_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam_r(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid_r(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); free_passwd(&pwd1); free_passwd(&pwd2); } free_passwds(pwd, num_pwd); } static bool test_nwrap_passwd_r_cross(void) { struct passwd *pwd, pwd1, pwd2, pwd3, pwd4; size_t i, num_pwd; test_nwrap_enum_r_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { test_nwrap_getpwnam_r(pwd[i].pw_name, &pwd1); assert_passwd_equal(&pwd[i], &pwd1); test_nwrap_getpwuid_r(pwd[i].pw_uid, &pwd2); assert_passwd_equal(&pwd[i], &pwd2); assert_passwd_equal(&pwd1, &pwd2); test_nwrap_getpwnam(pwd[i].pw_name, &pwd3); assert_passwd_equal(&pwd[i], &pwd3); test_nwrap_getpwuid(pwd[i].pw_uid, &pwd4); assert_passwd_equal(&pwd[i], &pwd4); assert_passwd_equal(&pwd3, &pwd4); free_passwd(&pwd1); free_passwd(&pwd2); free_passwd(&pwd3); free_passwd(&pwd4); } free_passwds(pwd, num_pwd); return true; } static bool test_nwrap_enum_group(struct group **grp_array_p, size_t *num_grp_p) { struct group *grp; struct group *grp_array = NULL; size_t num_grp = 0; DEBUG("Testing setgrent\n"); setgrent(); while ((grp = getgrent()) != NULL) { DEBUG("Testing getgrent\n"); print_group(grp); if (grp_array_p && num_grp_p) { grp_array = realloc(grp_array, sizeof(struct group) * (num_grp + 1)); assert_non_null(grp_array); copy_group(grp, &grp_array[num_grp]); num_grp++; } } DEBUG("Testing endgrent\n"); endgrent(); if (grp_array_p) { *grp_array_p = grp_array; } if (num_grp_p) { *num_grp_p = num_grp; } return true; } static bool test_nwrap_enum_r_group(struct group **grp_array_p, size_t *num_grp_p) { struct group *grp_array = NULL; size_t num_grp = 0; /* Skip these tests if the platform does not provide getgrent_r() */ #ifdef HAVE_GETGRENT_R struct group grp, *grpp; char buffer[4096]; int ret; DEBUG("Testing setgrent\n"); setgrent(); while (1) { DEBUG("Testing getgrent_r\n"); #ifdef HAVE_SOLARIS_GETGRENT_R grpp = getgrent_r(&grp, buffer, sizeof(buffer)); if (grpp == NULL) { break; } #else /* HAVE_SOLARIS_GETGRENT_R */ ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp); if (ret != 0) { if (ret != ENOENT) { DEBUG("got %d return code\n", ret); } break; } #endif /* HAVE_SOLARIS_GETGRENT_R */ print_group(&grp); if (grp_array_p && num_grp_p) { grp_array = realloc(grp_array, sizeof(struct group) * (num_grp + 1)); assert_non_null(grp_array); copy_group(&grp, &grp_array[num_grp]); num_grp++; } } DEBUG("Testing endgrent\n"); endgrent(); #endif /* HAVE_GETGRENT_R */ if (grp_array_p) { *grp_array_p = grp_array; } if (num_grp_p) { *num_grp_p = num_grp; } return true; } static bool test_nwrap_group(void) { struct group *grp, grp1, grp2; size_t i, num_grp; test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); free_group(&grp1); free_group(&grp2); } free_groups(grp, num_grp); return true; } static bool test_nwrap_group_r(void) { struct group *grp, grp1, grp2; size_t i, num_grp; test_nwrap_enum_r_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam_r(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid_r(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); free_group(&grp1); free_group(&grp2); } free_groups(grp, num_grp); return true; } static bool test_nwrap_group_r_cross(void) { struct group *grp, grp1, grp2, grp3, grp4; size_t i, num_grp; test_nwrap_enum_r_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { test_nwrap_getgrnam_r(grp[i].gr_name, &grp1); assert_group_equal(&grp[i], &grp1); test_nwrap_getgrgid_r(grp[i].gr_gid, &grp2); assert_group_equal(&grp[i], &grp2); assert_group_equal(&grp1, &grp2); test_nwrap_getgrnam(grp[i].gr_name, &grp3); assert_group_equal(&grp[i], &grp3); test_nwrap_getgrgid(grp[i].gr_gid, &grp4); assert_group_equal(&grp[i], &grp4); assert_group_equal(&grp3, &grp4); free_group(&grp1); free_group(&grp2); free_group(&grp3); free_group(&grp4); } free_groups(grp, num_grp); return true; } #ifdef HAVE_GETGROUPLIST static bool test_nwrap_getgrouplist(const char *user, gid_t gid, gid_t **gids_p, int *num_gids_p) { int ret; int num_groups = 0; gid_t *groups = NULL; DEBUG("Testing getgrouplist: %s\n", user); ret = getgrouplist(user, gid, NULL, &num_groups); if (ret == -1 || num_groups != 0) { groups = malloc(sizeof(gid_t) * num_groups); assert_non_null(groups); ret = getgrouplist(user, gid, groups, &num_groups); } assert_false(ret == -1); DEBUG("%s is member in %d groups\n", user, num_groups); if (gids_p) { *gids_p = groups; } if (num_gids_p) { *num_gids_p = num_groups; } return true; } static bool test_nwrap_user_in_group(const struct passwd *pwd, const struct group *grp) { int i; for (i = 0; grp->gr_mem != NULL && grp->gr_mem[i] != NULL; i++) { if (strcmp(grp->gr_mem[i], pwd->pw_name) == 0) { return true; } } return false; } static bool test_nwrap_membership_user(const struct passwd *pwd, struct group *grp_array, size_t num_grp) { int num_user_groups = 0; size_t num_user_groups_from_enum = 0; gid_t *user_groups = NULL; size_t i; int g; bool primary_group_had_user_member = false; test_nwrap_getgrouplist(pwd->pw_name, pwd->pw_gid, &user_groups, &num_user_groups); for (g=0; g < num_user_groups; g++) { test_nwrap_getgrgid(user_groups[g], NULL); } free(user_groups); for (i=0; i < num_grp; i++) { struct group grp = grp_array[i]; if (test_nwrap_user_in_group(pwd, &grp)) { struct group current_grp = { .gr_name = NULL, }; num_user_groups_from_enum++; test_nwrap_getgrnam(grp.gr_name, ¤t_grp); if (current_grp.gr_gid == pwd->pw_gid) { DEBUG("primary group %s of user %s lists user as member\n", current_grp.gr_name, pwd->pw_name); primary_group_had_user_member = true; } free_group(¤t_grp); continue; } } if (!primary_group_had_user_member) { num_user_groups_from_enum++; } assert_int_equal(num_user_groups, num_user_groups_from_enum); return true; } static void test_nwrap_membership(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); struct passwd *pwd; size_t num_pwd; struct group *grp; size_t num_grp; size_t i; (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_enum_passwd(&pwd, &num_pwd); test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_pwd; i++) { test_nwrap_membership_user(&pwd[i], grp, num_grp); } free_passwds(pwd, num_pwd); free_groups(grp, num_grp); } #endif /* HAVE_GETGROUPLIST */ static void test_nwrap_enumeration(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_passwd(); test_nwrap_group(); } static void test_nwrap_reentrant_enumeration(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } DEBUG("Testing re-entrant calls\n"); test_nwrap_passwd_r(); test_nwrap_group_r(); } static void test_nwrap_reentrant_enumeration_crosschecks(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } DEBUG("Testing re-entrant calls with cross checks\n"); test_nwrap_passwd_r_cross(); test_nwrap_group_r_cross(); } static bool test_nwrap_passwd_duplicates(void) { struct passwd *pwd; size_t d, i, num_pwd; int duplicates = 0; test_nwrap_enum_passwd(&pwd, &num_pwd); for (i=0; i < num_pwd; i++) { const char *current_name = pwd[i].pw_name; for (d=0; d < num_pwd; d++) { const char *dup_name = pwd[d].pw_name; if (d == i) { continue; } if (strcmp(current_name, dup_name) != 0) { continue; } DEBUG("found duplicate names:"); print_passwd(&pwd[d]); print_passwd(&pwd[i]); duplicates++; } } free_passwds(pwd, num_pwd); assert_false(duplicates); return true; } static bool test_nwrap_group_duplicates(void) { struct group *grp; size_t d, i, num_grp; int duplicates = 0; test_nwrap_enum_group(&grp, &num_grp); for (i=0; i < num_grp; i++) { const char *current_name = grp[i].gr_name; for (d=0; d < num_grp; d++) { const char *dup_name = grp[d].gr_name; if (d == i) { continue; } if (strcmp(current_name, dup_name) != 0) { continue; } DEBUG("found duplicate names:"); print_group(&grp[d]); print_group(&grp[i]); duplicates++; } } free_groups(grp, num_grp); assert_false(duplicates); return true; } static void test_nwrap_duplicates(void **state) { const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); const char *old_group = getenv("NSS_WRAPPER_GROUP"); (void) state; /* unused */ if (!old_pwd || !old_group) { DEBUG("ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); return; } test_nwrap_passwd_duplicates(); test_nwrap_group_duplicates(); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_enumeration), cmocka_unit_test(test_nwrap_reentrant_enumeration), cmocka_unit_test(test_nwrap_reentrant_enumeration_crosschecks), #ifdef HAVE_GETGROUPLIST cmocka_unit_test(test_nwrap_membership), #endif cmocka_unit_test(test_nwrap_duplicates), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/CMakeLists.txt000644 001750 000144 00000012303 14364217634 020035 0ustar00asnusers000000 000000 project(tests C) set(TESTSUITE_LIBRARIES nss_utils ${NWRAP_REQUIRED_LIBRARIES} ${CMOCKA_LIBRARY}) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) add_library(nss_nwrap SHARED nss_nwrap.c) target_compile_options(nss_nwrap PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_include_directories(nss_nwrap PRIVATE ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR}) target_link_libraries(nss_nwrap PRIVATE nss_utils) set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}) configure_file(passwd.in ${CMAKE_CURRENT_BINARY_DIR}/passwd @ONLY) configure_file(group.in ${CMAKE_CURRENT_BINARY_DIR}/group @ONLY) configure_file(hosts.in ${CMAKE_CURRENT_BINARY_DIR}/hosts @ONLY) configure_file(shadow.in ${CMAKE_CURRENT_BINARY_DIR}/shadow @ONLY) # If there is uid_wrapper, we can better test initgroups() since uid_wrapper # provides privilege for setgroups(). find_package(uid_wrapper 1.3.0) set(NWRAP_TESTS testsuite test_nwrap_vector test_getaddrinfo test_getnameinfo test_gethostby_name_addr test_gethostent test_getpwuid_module test_initgroups) if (HAVE_SHADOW_H) list(APPEND NWRAP_TESTS test_shadow) endif (HAVE_SHADOW_H) function(ADD_CMOCKA_TEST_ENVIRONMENT _TEST_NAME) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if (CMAKE_BUILD_TYPE_LOWER STREQUAL "addresssanitizer") find_library(ASAN_LIBRARY NAMES asan) if (NOT ASAN_LIBRARY) foreach(version RANGE 10 1) if (NOT ASAN_LIBRARY) find_library(ASAN_LIBRARY libasan.so.${version}) endif() endforeach() endif() endif() endif() if (ASAN_LIBRARY) list(APPEND PRELOAD_LIBRARIES ${ASAN_LIBRARY}) endif() if (uid_wrapper_FOUND) list(APPEND PRELOAD_LIBRARIES ${UID_WRAPPER_LIBRARY}) endif() list(APPEND PRELOAD_LIBRARIES ${NSS_WRAPPER_LOCATION}) if (OSX) set(TORTURE_ENVIRONMENT "DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${NSS_WRAPPER_LOCATION}") else () string(REPLACE ";" ":" _TMP_ENV "${PRELOAD_LIBRARIES}") set(TORTURE_ENVIRONMENT "LD_PRELOAD=${_TMP_ENV}") endif() if (uid_wrapper_FOUND) list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER=1) endif() list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_PASSWD=${CMAKE_CURRENT_BINARY_DIR}/passwd) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_GROUP=${CMAKE_CURRENT_BINARY_DIR}/group) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_SHADOW=${CMAKE_CURRENT_BINARY_DIR}/shadow) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_HOSTS=${CMAKE_CURRENT_BINARY_DIR}/hosts) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_MODULE_SO_PATH=${CMAKE_CURRENT_BINARY_DIR}/libnss_nwrap.so) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_MODULE_FN_PREFIX=nwrap) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if (CMAKE_BUILD_TYPE_LOWER STREQUAL "threadsanitizer") list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_DISABLE_DEEPBIND=1) if (uid_wrapper_FOUND) list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER_DISABLE_DEEPBIND=1) endif() endif() endif() set_property(TEST ${_TEST_NAME} PROPERTY ENVIRONMENT "${TORTURE_ENVIRONMENT}") endfunction() foreach(_NWRAP_TEST ${NWRAP_TESTS}) add_cmocka_test(${_NWRAP_TEST} SOURCES ${_NWRAP_TEST}.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TESTSUITE_LIBRARIES} LINK_OPTIONS ${DEFAULT_LINK_FLAGS}) if (BSD) target_compile_options(${_NWRAP_TEST} PRIVATE -DBSD) endif() target_include_directories(${_NWRAP_TEST} PRIVATE ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR}) add_cmocka_test_environment(${_NWRAP_TEST}) endforeach() if (HAVE_SHADOW_H) # This is needed to check the hash in tests/shadow.in target_link_libraries(test_shadow PRIVATE crypt) endif (HAVE_SHADOW_H) target_link_libraries(test_nwrap_vector PRIVATE ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(test_gethostby_name_addr PRIVATE ${CMAKE_THREAD_LIBS_INIT}) # Test nwrap without wrapping so the libc functions are called if (NOT CMAKE_BUILD_TYPE_LOWER MATCHES "sanitizer") add_cmocka_test(test_nwrap_disabled SOURCES test_nwrap_disabled.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TESTSUITE_LIBRARIES} LINK_OPTIONS ${DEFAULT_LINK_FLAGS}) target_include_directories(test_nwrap_disabled PRIVATE ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR}) set_property( TEST test_nwrap_disabled PROPERTY ENVIRONMENT LD_PRELOAD=${NSS_WRAPPER_LOCATION}) endif() nss_wrapper-1.1.15/tests/nss_nwrap.c000644 001750 000144 00000017701 14364206715 017460 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include "../src/nss_utils.h" #if defined(HAVE_NSS_H) /* Linux and BSD */ #include typedef enum nss_status NSS_STATUS; #elif defined(HAVE_NSS_COMMON_H) /* Solaris */ #include #include #include typedef nss_status_t NSS_STATUS; # define NSS_STATUS_SUCCESS NSS_SUCCESS # define NSS_STATUS_NOTFOUND NSS_NOTFOUND # define NSS_STATUS_UNAVAIL NSS_UNAVAIL # define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN #else # error "No nsswitch support detected" #endif #ifndef discard_const #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) #endif #ifndef discard_const_p #define discard_const_p(type, ptr) ((type *)discard_const(ptr)) #endif NSS_STATUS _nss_nwrap_setpwent(void); NSS_STATUS _nss_nwrap_endpwent(void); NSS_STATUS _nss_nwrap_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop); NSS_STATUS _nss_nwrap_setgrent(void); NSS_STATUS _nss_nwrap_endgrent(void); NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, char *buffer, size_t buflen, struct group **grdstp); NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, struct group **grdstp); NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, struct group **grdstp); NSS_STATUS _nss_nwrap_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); #ifndef PTR_DIFF #define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) #endif static int pw_copy_r(const struct passwd *src, struct passwd *dst, char *buf, size_t buflen, struct passwd **dstp) { char *first; char *last; off_t ofs; first = src->pw_name; last = src->pw_shell; while (*last) last++; ofs = PTR_DIFF(last + 1, first); if (ofs > (off_t) buflen) { return ERANGE; } memcpy(buf, first, ofs); ofs = PTR_DIFF(src->pw_name, first); dst->pw_name = buf + ofs; ofs = PTR_DIFF(src->pw_passwd, first); dst->pw_passwd = buf + ofs; dst->pw_uid = src->pw_uid; dst->pw_gid = src->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_CLASS ofs = PTR_DIFF(src->pw_class, first); dst->pw_class = buf + ofs; #endif /* HAVE_STRUCT_PASSWD_PW_CLASS */ #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE dst->pw_change = 0; #endif /* HAVE_STRUCT_PASSWD_PW_CHANGE */ #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE dst->pw_expire = 0; #endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE */ ofs = PTR_DIFF(src->pw_gecos, first); dst->pw_gecos = buf + ofs; ofs = PTR_DIFF(src->pw_dir, first); dst->pw_dir = buf + ofs; ofs = PTR_DIFF(src->pw_shell, first); dst->pw_shell = buf + ofs; if (dstp) { *dstp = dst; } return 0; } NSS_STATUS _nss_nwrap_setpwent(void) { return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_endpwent(void) { return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { (void) result; (void) buffer; (void) buflen; (void) errnop; return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { (void)errnop; /* unused */ if (uid == 424242) { char buf[] = "hanswurst\0secret\0\0/home/hanswurst\0/bin/false"; const struct passwd src = { .pw_name = &buf[0], .pw_passwd = &buf[10], .pw_uid = 424242, .pw_gid = 424242, .pw_gecos = &buf[17], .pw_dir = &buf[18], .pw_shell = &buf[34], }; memset(buffer, '\0', buflen); pw_copy_r(&src, result, buffer, buflen, NULL); errnop = 0; return NSS_STATUS_SUCCESS; } return NSS_STATUS_UNAVAIL; } NSS_STATUS _nss_nwrap_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop) { (void) name; (void) result; (void) buffer; (void) buflen; (void) errnop; return NSS_STATUS_UNAVAIL; } static int grent_idx = 0; NSS_STATUS _nss_nwrap_setgrent(void) { grent_idx = 0; return NSS_STATUS_SUCCESS; } NSS_STATUS _nss_nwrap_endgrent(void) { grent_idx = 0; return NSS_STATUS_SUCCESS; } static const struct group gr0 = { .gr_name = discard_const_p(char, "wb_group_0"), .gr_passwd = discard_const_p(char, "x"), .gr_gid = 100010, .gr_mem = (char *[]) { discard_const_p(char, "alice"), discard_const_p(char, "bob"), NULL }, }; static const struct group gr1 = { .gr_name = discard_const_p(char, "wb_group_1"), .gr_passwd = discard_const_p(char, "x"), .gr_gid = 100011, .gr_mem = (char *[]) { discard_const_p(char, "alice"), discard_const_p(char, "bob"), NULL }, }; static const struct group gr2 = { .gr_name = discard_const_p(char, "wb_group_2"), .gr_passwd = discard_const_p(char, "x"), .gr_gid = 100012, .gr_mem = (char *[]) { discard_const_p(char, "alice"), NULL }, }; NSS_STATUS _nss_nwrap_getgrent_r(struct group *result, char *buffer, size_t buflen, struct group **grdstp) { switch (grent_idx) { int ret; case 0: ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); grent_idx++; return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; case 1: ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); grent_idx++; return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; case 2: ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); grent_idx++; return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; default: return NSS_STATUS_NOTFOUND; } } NSS_STATUS _nss_nwrap_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, struct group **grdstp) { int ret; if (strcmp(name, "wb_group_0") == 0) { ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; } else if (strcmp(name, "wb_group_1") == 0) { ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; } else if (strcmp(name, "wb_group_2") == 0) { ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; } else { return NSS_STATUS_NOTFOUND; } } NSS_STATUS _nss_nwrap_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, struct group **grdstp) { int ret; switch (gid) { case 100010: ret = nwrap_gr_copy_r(&gr0, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; case 100011: ret = nwrap_gr_copy_r(&gr1, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; case 100012: ret = nwrap_gr_copy_r(&gr2, result, buffer, buflen, grdstp); return ret == 0 ? NSS_STATUS_SUCCESS : NSS_STATUS_TRYAGAIN; default: return NSS_STATUS_NOTFOUND; } } NSS_STATUS _nss_nwrap_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) { (void) user; (void)group; (void) limit; (void) errnop; if (!(strcmp(user, "alice") == 0 || strcmp(user, "bob") == 0)) { return NSS_STATUS_SUCCESS; } if (*start + 4 >= *size) { long int newsize; gid_t *newgroups; newsize = *size + 4; if (limit > 0) { if (newsize > limit) { return NSS_STATUS_NOTFOUND; } } newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups)); if (!newgroups) { *errnop = ENOMEM; return NSS_STATUS_NOTFOUND; } *groups = newgroups; *size = newsize; } (*groups)[(*start)++] = 100010; (*groups)[(*start)++] = 100011; if (strcmp(user, "alice") == 0) { (*groups)[(*start)++] = 100012; } return NSS_STATUS_SUCCESS; } nss_wrapper-1.1.15/tests/test_getaddrinfo.c000644 001750 000144 00000045461 13634203624 020772 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_getaddrinfo(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char ip6[INET6_ADDRSTRLEN]; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); assert_int_equal(res->ai_family, AF_INET); addr.sa = res->ai_addr; assert_int_equal(addr.in->sin_family, AF_INET); ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); res = NULL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("::13", NULL, &hints, &res); assert_non_null(res); assert_int_equal(rc, 0); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "beteigeuze.galaxy.site"); assert_int_equal(res->ai_family, AF_INET6); addr.sa = res->ai_addr; assert_int_equal(addr.in6->sin6_family, AF_INET6); inet_ntop(AF_INET6, (void *)&addr.in6->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::13"); freeaddrinfo(res); } /* * The purpose of this test is to verify that reloading of the hosts * file (triggered by a timestamp change) correctly frees and re-creates * the internal data structures, so we do not end up using invalid memory. */ static void test_nwrap_getaddrinfo_reload(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; const char *env; char touch_cmd[1024]; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; env = getenv("NSS_WRAPPER_HOSTS"); assert_non_null(env); snprintf(touch_cmd, sizeof(touch_cmd), "touch %s", env); rc = system(touch_cmd); assert_return_code(rc, errno); rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_samba(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_STREAM; /* Stream socket */ hints.ai_flags = 0; /* For wildcard IP address */ hints.ai_protocol = IPPROTO_TCP; /* Any protocol */ hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; rc = getaddrinfo("127.0.0.21", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("samba.example.com", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("localdc", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("localdc.samba.example.com", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); res = NULL; rc = getaddrinfo("fd00:0000:0000:0000:0000:0000:5357:5f15", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_any(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char ip6[INET6_ADDRSTRLEN]; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; rc = getaddrinfo("0.0.0.0", "389", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); #ifdef HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES assert_string_equal(res->ai_canonname, "0.0.0.0"); #else /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ assert_null(res->ai_canonname); #endif /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ addr.sa = res->ai_addr; assert_int_equal(389, htons(addr.in->sin_port)); ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "0.0.0.0"); freeaddrinfo(res); res = NULL; /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; rc = getaddrinfo("::", "389", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET6); assert_int_equal(res->ai_socktype, SOCK_STREAM); #ifdef HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES assert_string_equal(res->ai_canonname, "::"); #else /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ assert_null(res->ai_canonname); #endif /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ addr.sa = res->ai_addr; assert_int_equal(389, htons(addr.in6->sin6_port)); inet_ntop(AF_INET6, (void *)&addr.in6->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_local(void **state) { struct addrinfo hints; struct addrinfo *res; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("127.0.0.1", NULL, &hints, &res); assert_int_equal(rc, 0); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); #ifdef HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES assert_string_equal(res->ai_canonname, "127.0.0.1"); #else /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ assert_null(res->ai_canonname); #endif /* HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES */ addr.sa = res->ai_addr; ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "127.0.0.1"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_name(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("maximegalon.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "maximegalon.galaxy.site"); addr.sa = res->ai_addr; ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "127.0.0.12"); freeaddrinfo(res); res = NULL; /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("MAGRATHEA", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); addr.sa = res->ai_addr; ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_service(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char *ip; int rc; (void) state; /* unused */ /* IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; rc = getaddrinfo("magrathea", "wurst", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* Check ldap port */ rc = getaddrinfo("magrathea", "ldap", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_int_equal(res->ai_family, AF_INET); assert_int_equal(res->ai_socktype, SOCK_STREAM); assert_non_null(res->ai_canonname); assert_string_equal(res->ai_canonname, "magrathea.galaxy.site"); assert_non_null(res->ai_addr); addr.sa = res->ai_addr; ip = inet_ntoa(addr.in->sin_addr); assert_string_equal(ip, "127.0.0.11"); assert_int_equal(ntohs(addr.in->sin_port), 389); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_null(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char ip6[INET6_ADDRSTRLEN]; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 17; hints.ai_flags = 0; rc = getaddrinfo(NULL, NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); /* Check dns service */ rc = getaddrinfo(NULL, "domain", &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_null(res->ai_canonname); assert_int_equal(res->ai_family, AF_INET6); assert_int_equal(res->ai_socktype, SOCK_DGRAM); assert_non_null(res->ai_addr); addr.sa = res->ai_addr; inet_ntop(AF_INET6, (void *)&addr.in6->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::1"); freeaddrinfo(res); res = NULL; /* Check dns service */ rc = getaddrinfo("magrathea", "domain", NULL, &res); assert_non_null(res); assert_int_equal(rc, 0); assert_non_null(res->ai_canonname); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_dot(void **state) { struct addrinfo hints = { .ai_family = AF_INET, }; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char ip[INET_ADDRSTRLEN]; int rc; (void) state; /* unused */ /* Check with a dot at the end */ rc = getaddrinfo("magrathea.galaxy.site.", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_next); assert_int_equal(res->ai_family, AF_INET); addr.sa = res->ai_addr; assert_int_equal(addr.in->sin_family, AF_INET); inet_ntop(AF_INET, (void *)&addr.in->sin_addr, ip, sizeof(ip)); assert_string_equal(ip, "127.0.0.11"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_ipv6(void **state) { struct addrinfo hints; struct addrinfo *res = NULL; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; char ip6[INET6_ADDRSTRLEN]; int rc; (void) state; /* unused */ /* * krikkit.galaxy has an IPv4 and IPv6 address, this should only * return the IPv6 address. */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; rc = getaddrinfo("krikkit.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, 0); assert_non_null(res); assert_non_null(res->ai_next); assert_int_equal(res->ai_family, AF_INET6); addr.sa = res->ai_addr; assert_int_equal(addr.in6->sin6_family, AF_INET6); inet_ntop(AF_INET6, (void *)&addr.in6->sin6_addr, ip6, sizeof(ip6)); assert_string_equal(ip6, "::14"); freeaddrinfo(res); } static void test_nwrap_getaddrinfo_multiple_mixed(void **state) { struct addrinfo *res, *res_head; struct addrinfo hints; unsigned int ipv6_count = 0; unsigned int ipv4_count = 0; int rc; int p; union { struct sockaddr *sa; struct sockaddr_in *in; struct sockaddr_in6 *in6; } r_addr; const char *result = NULL; const char *value = NULL; /* For inet_ntop call */ char buf[4096]; /* 2 - ipv4 and 3 ipv6 addresses */ const char *ipvX_results[] = {"127.1.1.1", "127.0.0.66", "2666::22", "B00B:5::4", "DEAD:BEEF:1:2:3::4", NULL}; (void) state; /* unused */ memset(&hints, '\0', sizeof(struct addrinfo)); hints.ai_protocol = IPPROTO_TCP; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo("pumpkin.bunny.net", NULL, &hints, &res_head); assert_return_code(rc, 0); assert_non_null(res_head); for (res = res_head; res != NULL; res = res->ai_next) { if (res->ai_family == AF_INET) { r_addr.sa = res->ai_addr; assert_non_null(r_addr.sa); ++ipv4_count; result = inet_ntop(AF_INET, &r_addr.in->sin_addr, buf, 4096); } else if (res->ai_family == AF_INET6) { r_addr.sa = res->ai_addr; assert_non_null(r_addr.sa); ++ipv6_count; result = inet_ntop(AF_INET6, &r_addr.in6->sin6_addr, buf, 4096); } else { /* Unknown family type */ assert_int_equal(1,0); } /* Important part */ assert_non_null(result); /* This could be part of cmocka library */ for (value = ipvX_results[0], p = 0; value != NULL; value = ipvX_results[++p]) { if (strcasecmp(value, result) == 0) { break; } } assert_non_null(value); } assert_int_equal(ipv6_count, 3); assert_int_equal(ipv4_count, 2); freeaddrinfo(res_head); } static void test_nwrap_getaddrinfo_flags_ai_numericserv(void **state) { struct addrinfo hints; struct addrinfo *res; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; /* * Calls with NULL name are handled by libc, * even if nss_wrapper is enabled */ rc = getaddrinfo(NULL, "echo", &hints, &res); #ifdef HAVE_GETADDRINFO_USES_EAI_SERVICE assert_int_equal(rc, EAI_SERVICE); #else /* HAVE_GETADDRINFO_USES_EAI_SERVICE */ assert_int_equal(rc, EAI_NONAME); #endif /* HAVE_GETADDRINFO_USES_EAI_SERVICE */ rc = getaddrinfo(NULL, "80", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); res = NULL; /* Crippled input */ rc = getaddrinfo(NULL, "80a1", &hints, &res); #ifdef HAVE_GETADDRINFO_USES_EAI_SERVICE assert_int_equal(rc, EAI_SERVICE); #else /* HAVE_GETADDRINFO_USES_EAI_SERVICE */ assert_int_equal(rc, EAI_NONAME); #endif /* HAVE_GETADDRINFO_USES_EAI_SERVICE */ /* * Calls with non-NULL name are handled by nwrap */ rc = getaddrinfo("magrathea.galaxy.site", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("magrathea.galaxy.site", "80", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); res = NULL; /* Crippled input */ rc = getaddrinfo("magrathea.galaxy.site", "80a1", &hints, &res); assert_int_equal(rc, EAI_NONAME); } static void test_nwrap_getaddrinfo_flags_ai_numerichost(void **state) { struct addrinfo hints; struct addrinfo *res; int rc; (void) state; /* unused */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; /* IPv4 or IPv6 */ hints.ai_family = AF_UNSPEC; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("::1", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* IPv4 */ hints.ai_family = AF_INET; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("::1", NULL, &hints, &res); #ifdef EAI_ADDRFAMILY assert_int_equal(rc, EAI_ADDRFAMILY); #else assert_int_equal(rc, EAI_FAMILY); #endif rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); /* IPv6 */ hints.ai_family = AF_INET6; rc = getaddrinfo("127.0.0.11", NULL, &hints, &res); #ifdef EAI_ADDRFAMILY assert_int_equal(rc, EAI_ADDRFAMILY); #else assert_int_equal(rc, EAI_FAMILY); #endif rc = getaddrinfo("::1", NULL, &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo(NULL, "echo", &hints, &res); assert_int_equal(rc, 0); freeaddrinfo(res); rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("", NULL, &hints, &res); assert_int_equal(rc, EAI_NONAME); rc = getaddrinfo("fail.me", "echo", &hints, &res); assert_int_equal(rc, EAI_NONAME); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_getaddrinfo), cmocka_unit_test(test_nwrap_getaddrinfo_reload), cmocka_unit_test(test_nwrap_getaddrinfo_any), cmocka_unit_test(test_nwrap_getaddrinfo_local), cmocka_unit_test(test_nwrap_getaddrinfo_name), cmocka_unit_test(test_nwrap_getaddrinfo_service), cmocka_unit_test(test_nwrap_getaddrinfo_null), cmocka_unit_test(test_nwrap_getaddrinfo_dot), cmocka_unit_test(test_nwrap_getaddrinfo_ipv6), cmocka_unit_test(test_nwrap_getaddrinfo_multiple_mixed), cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numericserv), cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numerichost), cmocka_unit_test(test_nwrap_getaddrinfo_samba), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/test_gethostent.c000644 001750 000144 00000002051 13634203624 020654 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include static void test_nwrap_gethostent(void **state) { struct hostent *he; uint32_t i; (void)state; /* unused */ sethostent(0); for (he = gethostent(); he != NULL; he = gethostent()) { assert_non_null(he->h_addr_list); assert_non_null(he->h_aliases); for (i = 0; he->h_addr_list[i] != NULL; i++) { char buf[INET6_ADDRSTRLEN]; uint32_t j; const char *ip; ip = inet_ntop(he->h_addrtype, he->h_addr_list[i], buf, sizeof(buf)); printf("ip: %s\n", ip); for (j = 0; he->h_aliases[j] != NULL; j++) { printf("alias: %s\n", he->h_aliases[j]); } } } endhostent(); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_gethostent), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/hosts.in000644 001750 000144 00000013004 13634203624 016755 0ustar00asnusers000000 000000 127.0.0.11 magrathea.galaxy.site magrathea 127.0.0.12 magrathea.galaxy.site magrathea ::29a magrathea.galaxy.site magrathea 127.0.0.12 maximegalon.galaxy.site ::13 beteigeuze.galaxy.site beteigeuze mail 127.0.0.14 krikkit.galaxy.site ::14 krikkit.galaxy.site 127.1.1.1 pumpkin.bunny.net pumpkin.bunny.net 127.0.0.66 pumpkin.bunny.net 2666::22 pumpkin.bunny.net DEAD:BEEF:1:2:3::4 pumpkin.bunny.net B00B:5::4 pumpkin.bunny.net 127.0.0.21 localdc.samba.example.com samba.example.com localdc fd00:0000:0000:0000:0000:0000:5357:5f15 localdc.samba.example.com samba.example.com localdc 127.0.0.3 localnt4dc2.samba.example.com localnt4dc2 fd00:0000:0000:0000:0000:0000:5357:5f03 localnt4dc2.samba.example.com localnt4dc2 127.0.0.5 localshare4.samba.example.com localshare4 fd00:0000:0000:0000:0000:0000:5357:5f05 localshare4.samba.example.com localshare4 127.0.0.4 localnt4member3.samba.example.com localnt4member3 fd00:0000:0000:0000:0000:0000:5357:5f04 localnt4member3.samba.example.com localnt4member3 127.0.0.29 localadmember.samba.example.com localadmember fd00:0000:0000:0000:0000:0000:5357:5f1d localadmember.samba.example.com localadmember 127.0.0.23 s4member.samba.example.com s4member fd00:0000:0000:0000:0000:0000:5357:5f17 s4member.samba.example.com s4member 127.0.0.7 localktest6.samba.example.com localktest6 fd00:0000:0000:0000:0000:0000:5357:5f07 localktest6.samba.example.com localktest6 127.0.0.8 maptoguest.samba.example.com maptoguest fd00:0000:0000:0000:0000:0000:5357:5f08 maptoguest.samba.example.com maptoguest 127.0.0.35 fileserver.samba.example.com fileserver fd00:0000:0000:0000:0000:0000:5357:5f23 fileserver.samba.example.com fileserver 127.0.0.30 addc.addc.samba.example.com addc fd00:0000:0000:0000:0000:0000:5357:5f1e addc.addc.samba.example.com addc 127.0.0.9 localnt4dc9.samba.example.com localnt4dc9 fd00:0000:0000:0000:0000:0000:5357:5f09 localnt4dc9.samba.example.com localnt4dc9 127.0.0.34 rfc2307member.samba.example.com rfc2307member fd00:0000:0000:0000:0000:0000:5357:5f22 rfc2307member.samba.example.com rfc2307member 127.0.0.25 dc5.samba2000.example.com dc5 fd00:0000:0000:0000:0000:0000:5357:5f19 dc5.samba2000.example.com dc5 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 127.0.0.26 dc6.samba2003.example.com dc6 fd00:0000:0000:0000:0000:0000:5357:5f1a dc6.samba2003.example.com dc6 nss_wrapper-1.1.15/tests/test_gethostby_name_addr.c000644 001750 000144 00000023261 13634640264 022505 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NSS_WRAPPER_HOSTNAME_ENV "NSS_WRAPPER_HOSTNAME" static void test_nwrap_gethostname(void **state) { const char *hostname = "milliways"; char sys_host[256] = {0}; char host[16] = {0}; int rc; (void) state; /* unused */ rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, hostname, 1); assert_int_equal(rc, 0); rc = gethostname(host, sizeof(host)); assert_int_equal(rc, 0); assert_string_equal(host, hostname); rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, "this_hostname_is_too_long", 1); assert_int_equal(rc, 0); rc = gethostname(host, sizeof(host)); assert_int_equal(rc, -1); assert_int_equal(errno, ENAMETOOLONG); unsetenv(NSS_WRAPPER_HOSTNAME_ENV); rc = gethostname(sys_host, sizeof(sys_host)); assert_int_equal(rc, 0); } static void *thread_test_gethostbyname(void *u) { struct hostent *he; (void) u; /* unused */ he = gethostbyname("magrathea"); assert_non_null(he); assert_non_null(he->h_name); assert_string_equal(he->h_name, "magrathea.galaxy.site"); pthread_exit(NULL); } static void test_nwrap_gethostbyname_thread(void **state) { struct hostent *he; pthread_t th; (void) state; /* unused */ he = gethostbyname("maximegalon.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_string_equal(he->h_name, "maximegalon.galaxy.site"); pthread_create(&th, NULL, &thread_test_gethostbyname, NULL); pthread_join(th, NULL); assert_non_null(he); assert_non_null(he->h_name); #ifdef BSD /* * On *BSD (and Mac OS X) systems, * data is stored in thread local storage. */ assert_string_equal(he->h_name, "maximegalon.galaxy.site"); #else /* * Glibc doesn't store data in thread local storage, so calling * gethostbyname from a thread overwrites the parent thread's data. */ assert_string_equal(he->h_name, "magrathea.galaxy.site"); #endif } static void test_nwrap_gethostbyname(void **state) { char ip[INET_ADDRSTRLEN]; struct hostent *he; const char *a; (void) state; /* unused */ he = gethostbyname("magrathea.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.11"); } static void test_nwrap_gethostbyname_multiple(void **state) { struct hostent *he; char **list; /* For inet_ntop call */ char buf[4096]; const char *result; char *p = buf; /* List of ips in hosts file - order matters */ const char *const result_ips[] = { "127.0.0.11", "127.0.0.12", NULL }; const char *actual_ip = result_ips[0]; unsigned int ac; (void) state; /* unused */ he = gethostbyname("magrathea.galaxy.site"); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); list = he->h_addr_list; for (ac = 0; *list != NULL; ++ac, ++list) { actual_ip = result_ips[ac]; /* When test fails here more records are returned */ assert_non_null(actual_ip); result = inet_ntop(AF_INET, *list, p, 4096); assert_non_null(p); assert_string_equal(actual_ip, result); } } #ifdef HAVE_GETHOSTBYNAME2 static void test_nwrap_gethostbyname2(void **state) { char ip[INET6_ADDRSTRLEN]; struct hostent *he; const char *a; (void) state; /* unused */ he = gethostbyname2("magrathea.galaxy.site", AF_INET6); assert_non_null(he); he = gethostbyname2("magrathea.galaxy.site", AF_INET); assert_non_null(he); /* Check ipv6 he */ he = gethostbyname2("krikkit.galaxy.site", AF_INET6); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "krikkit.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET6); a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "::14"); /* Check ipv4 he */ he = gethostbyname2("krikkit.galaxy.site", AF_INET); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "krikkit.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.14"); } #endif /* HAVE_GETHOSTBYNAME2 */ static void test_nwrap_gethostbyaddr(void **state) { struct hostent *he; struct in_addr in; int rc; (void) state; /* unused */ rc = inet_aton("127.0.0.11", &in); assert_int_equal(rc, 1); he = gethostbyaddr(&in, sizeof(struct in_addr), AF_INET); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); assert_memory_equal(&in, he->h_addr_list[0], he->h_length); } #ifdef HAVE_GETHOSTBYNAME_R static void test_nwrap_gethostbyname_r(void **state) { char buf[1024] = {0}; char ip[INET_ADDRSTRLEN]; struct hostent hb, *he; const char *a; int herr = 0; int rc; (void) state; /* unused */ rc = gethostbyname_r("magrathea.galaxy.site", &hb, buf, sizeof(buf), &he, &herr); assert_int_equal(rc, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(ip, "127.0.0.11"); } static void test_nwrap_gethostbyname_r_null(void **state) { char buf[2]; struct hostent hb, *he; int herr = 0; int rc; (void) state; /* unused */ buf[0] = 'A'; buf[1] = '\0'; /* Check that the returned buffer is zeroed */ rc = gethostbyname_r("wurst", &hb, buf, sizeof(buf), &he, &herr); assert_int_equal(rc, ENOENT); assert_null(he); assert_null(hb.h_name); assert_null(hb.h_addr_list); assert_string_equal(buf, ""); } #endif #ifdef HAVE_GETHOSTBYNAME2_R static void test_nwrap_gethostbyname2_r_v4(void **state) { char *buf = NULL; size_t buflen = 2; char ip[INET_ADDRSTRLEN]; struct hostent hb, *he; const char *a; int herr = 0; int rc; (void) state; /* unused */ for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) { if (buf != NULL) { free(buf); } buf = calloc(1, buflen); assert_non_null(buf); rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET, &hb, buf, buflen, &he, &herr); } assert_int_equal(rc, 0); assert_int_equal(herr, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); assert_non_null(he->h_addr_list[0]); a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(a, "127.0.0.11"); assert_non_null(he->h_addr_list[1]); a = inet_ntop(AF_INET, he->h_addr_list[1], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(a, "127.0.0.12"); assert_null(he->h_addr_list[2]); free(buf); } static void test_nwrap_gethostbyname2_r_v6(void **state) { char *buf = NULL; size_t buflen = 2; char ip[INET6_ADDRSTRLEN]; struct hostent hb, *he; const char *a; int herr = 0; int rc; (void) state; /* unused */ for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) { if (buf != NULL) { free(buf); } buf = calloc(1, buflen); assert_non_null(buf); rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET6, &hb, buf, buflen, &he, &herr); } assert_int_equal(rc, 0); assert_int_equal(herr, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET6); assert_non_null(he->h_addr_list[0]); a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip)); assert_non_null(a); assert_string_equal(a, "::29a"); assert_null(he->h_addr_list[1]); free(buf); } #endif #ifdef HAVE_GETHOSTBYADDR_R static void test_nwrap_gethostbyaddr_r(void **state) { char buf[1024] = {0}; struct hostent hb, *he; struct in_addr in; int herr = 0; int rc; (void) state; /* unused */ rc = inet_aton("127.0.0.11", &in); assert_int_equal(rc, 1); rc = gethostbyaddr_r(&in, sizeof(struct in_addr), AF_INET, &hb, buf, sizeof(buf), &he, &herr); assert_int_equal(rc, 0); assert_non_null(he); assert_non_null(he->h_name); assert_non_null(he->h_addr_list); assert_string_equal(he->h_name, "magrathea.galaxy.site"); assert_int_equal(he->h_addrtype, AF_INET); assert_memory_equal(&in, he->h_addr_list[0], he->h_length); } #endif int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_gethostname), cmocka_unit_test(test_nwrap_gethostbyname), cmocka_unit_test(test_nwrap_gethostbyname_thread), #ifdef HAVE_GETHOSTBYNAME2 cmocka_unit_test(test_nwrap_gethostbyname2), #endif cmocka_unit_test(test_nwrap_gethostbyaddr), #ifdef HAVE_GETHOSTBYNAME_R cmocka_unit_test(test_nwrap_gethostbyname_r), cmocka_unit_test(test_nwrap_gethostbyname_r_null), #endif #ifdef HAVE_GETHOSTBYNAME2_R cmocka_unit_test(test_nwrap_gethostbyname2_r_v4), cmocka_unit_test(test_nwrap_gethostbyname2_r_v6), #endif #ifdef HAVE_GETHOSTBYADDR_R cmocka_unit_test(test_nwrap_gethostbyaddr_r), #endif cmocka_unit_test(test_nwrap_gethostbyname_multiple), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/test_initgroups.c000644 001750 000144 00000002320 14364246632 020701 0ustar00asnusers000000 000000 #include #include #include #include #include #include #include #include static void test_nwrap_initgroups(void **state) { gid_t gid = 10000; int ret, i; int ngroups; const char *env = getenv("UID_WRAPPER"); (void)state; /* unused */ /* initgroups() sets {10000, 1000, 1002, 100010, 100011, 100012} */ ret = initgroups("alice", gid); assert_return_code(ret, errno); /* * nss_wrapper() in nwrap_initgroups() makes early return if UID_WRAPPER * is not present. The reason is that we need privilege for setgroups() * called from initgroups() and we get it only with UID_WRAPPER */ if (env != NULL && env[0] == '1') { gid_t groups1[6] = {10000, 1000, 1002, 100010, 100011, 100012}; gid_t *groups2 = malloc(10 * sizeof(gid_t)); assert_non_null(groups2); ngroups = getgroups(10, groups2); /* room for 10, expect 6 */ assert_int_equal(ngroups, 6); for (i = 0; i < 6; i++) { assert_int_equal(groups1[i], groups2[i]); } free(groups2); } } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_initgroups) }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/test_getpwuid_module.c000644 001750 000144 00000001766 14142230333 021671 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include #include static void test_nwrap_passwd(void **state) { struct passwd *pwd; uid_t id = 424242; (void) state; /* unused */ pwd = getpwuid(id); assert_non_null(pwd); assert_string_equal(pwd->pw_name, "hanswurst"); assert_int_equal(pwd->pw_uid, id); assert_int_equal(pwd->pw_gid, id); } static void test_nwrap_passwd_closed_handles(void **state) { struct passwd *pwd; uid_t id = 424242; long maxfd; (void) state; /* unused */ pwd = getpwuid(id); assert_non_null(pwd); maxfd = sysconf(_SC_OPEN_MAX); if (maxfd < 0) { maxfd = 1024; } for (long fd = 3; fd < maxfd; fd++) { close(fd); } pwd = getpwuid(id); assert_non_null(pwd); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_passwd), cmocka_unit_test(test_nwrap_passwd_closed_handles), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/tests/group.in000644 001750 000144 00000000155 14364206715 016761 0ustar00asnusers000000 000000 users:x:1000:alice,bob all:x:1002:alice,bob,nobody,root nobody:x:65533: nogroup:x:65534:nobody root:x:65532: nss_wrapper-1.1.15/tests/passwd.in000644 001750 000144 00000000311 13634203624 017113 0ustar00asnusers000000 000000 bob:x:1000:1000:bob gecos:@HOMEDIR@:/bin/false alice:x:1001:1000:alice gecos:@HOMEDIR@:/bin/false nobody:x:65533:65534:bob gecos:@HOMEDIR@:/bin/false root:x:65534:65532:root gecos:@HOMEDIR@:/bin/false nss_wrapper-1.1.15/tests/test_nwrap_vector.c000644 001750 000144 00000007055 13634203624 021212 0ustar00asnusers000000 000000 #include "config.h" #include #include #include #include #include "../src/nss_wrapper.c" static void test_nwrap_vector_basic_add(void **state) { struct nwrap_vector v; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v); assert_non_null(v.items); nwrap_vector_add_item(&v, string); assert_null(v.items[1]); assert_int_equal(v.count, 1); assert_string_equal(v.items[0], string); assert_int_equal(v.capacity, DEFAULT_VECTOR_CAPACITY); assert_string_equal(v.items[0], "string!"); nwrap_vector_add_item(&v, string2); assert_null(v.items[2]); assert_int_equal(v.count, 2); assert_string_equal(v.items[0], string); assert_string_equal(v.items[1], string2); free(v.items); } static void test_nwrap_vector_merge_empty(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); assert_int_equal(v1.count, 0); nwrap_vector_init(&v2); assert_non_null(v2.items); assert_int_equal(v2.count, 0); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 0); assert_null(v1.items[0]); nwrap_vector_add_item(&v1, string); nwrap_vector_add_item(&v1, string2); assert_int_equal(v1.count, 2); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 2); assert_string_equal(v1.items[0], string); assert_string_equal(v1.items[1], string2); assert_null(v1.items[2]); nwrap_vector_merge(&v2, &v1); assert_int_equal(v2.count, 2); assert_string_equal(v2.items[0], string); assert_string_equal(v2.items[1], string2); assert_null(v2.items[2]); free(v1.items); free(v2.items); } static void test_nwrap_vector_merge(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); nwrap_vector_add_item(&v1, string); nwrap_vector_add_item(&v1, string2); assert_int_equal(v1.count, 2); nwrap_vector_init(&v2); assert_non_null(v2.items); nwrap_vector_add_item(&v2, string2); nwrap_vector_add_item(&v2, string); assert_int_equal(v2.count, 2); nwrap_vector_merge(&v1, &v2); assert_int_equal(v1.count, 4); assert_string_equal(v1.items[0], string); assert_string_equal(v1.items[1], string2); assert_string_equal(v1.items[2], string2); assert_string_equal(v1.items[3], string); assert_null(v1.items[4]); free(v1.items); free(v2.items); } static void test_nwrap_vector_merge_max(void **state) { struct nwrap_vector v1; struct nwrap_vector v2; char string[] = "string!"; char string2[] = "2string!"; int p; (void) state; /* unused */ nwrap_vector_init(&v1); assert_non_null(v1.items); for (p = 0; p < 64; ++p) { nwrap_vector_add_item(&v1, string); } assert_int_equal(v1.count, 64); nwrap_vector_init(&v2); assert_non_null(v2.items); nwrap_vector_merge(&v2, &v1); assert_int_equal(v2.count, 64); for (p = 0; p < 64; ++p) { assert_string_equal(v2.items[p], string); } nwrap_vector_add_item(&v2, string2); assert_string_equal(v2.items[64], string2); assert_int_equal(v2.count, 65); assert_null(v2.items[65]); free(v1.items); free(v2.items); } int main(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_nwrap_vector_basic_add), cmocka_unit_test(test_nwrap_vector_merge_empty), cmocka_unit_test(test_nwrap_vector_merge), cmocka_unit_test(test_nwrap_vector_merge_max), }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } nss_wrapper-1.1.15/doc/000755 001750 000144 00000000000 14364246777 014713 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/doc/nss_wrapper.1000644 001750 000144 00000013340 13634203634 017321 0ustar00asnusers000000 000000 '\" t .\" Title: nss_wrapper .\" Author: Samba Team .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2019-05-21 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" .TH "NSS_WRAPPER" "1" "2019\-05\-21" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" nss_wrapper \- A wrapper for the user, group and hosts NSS API .SH "SYNOPSIS" .sp LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_PASSWD=/path/to/passwd NSS_WRAPPER_GROUP=/path/to/group NSS_WRAPPER_HOSTS=/path/to/host \fB\&./myapplication\fR .SH "DESCRIPTION" .sp There are projects which provide daemons needing to be able to create, modify and delete Unix users\&. Or just switch user ids to interact with the system e\&.g\&. a user space file server\&. To be able to test that you need the privilege to modify the passwd and groups file\&. With nss_wrapper it is possible to define your own passwd and groups file which will be used by software to act correctly while under test\&. .sp If you have a client and server under test they normally use functions to resolve network names to addresses (dns) or vice versa\&. The nss_wrappers allow you to create a hosts file to setup name resolution for the addresses you use with socket_wrapper\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Provides information for user and group accounts\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Network name resolution using a hosts file\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Loading and testing of NSS modules\&. .RE .SH "LIMITATIONS" .sp Some calls in nss_wrapper will only work if uid_wrapper is loaded and active\&. One of this functions is initgroups() which needs to run setgroups() to set the groups for the user\&. setgroups() is wrapped by uid_wrapper\&. .SH "ENVIRONMENT VARIABLES" .PP \fBNSS_WRAPPER_PASSWD\fR, \fBNSS_WRAPPER_GROUP\fR .RS 4 For user and group accounts you need to create two files: \fIpasswd\fR and \fIgroup\fR\&. The format of the passwd file is described in \fIman 5 passwd\fR and the group file in \fIman 5 group\fR\&. So you can fill these files with made up accounts\&. You point nss_wrapper to them using the two variables NSS_WRAPPER_PASSWD=/path/to/your/passwd and NSS_WRAPPER_GROUP=/path/to/your/group\&. .RE .PP \fBNSS_WRAPPER_HOSTS\fR .RS 4 If you also need to emulate network name resolution in your enviornment, especially with socket_wrapper, you can write a hosts file\&. The format is described in \fIman 5 hosts\fR\&. Then you can point nss_wrapper to your hosts file using: NSS_WRAPPER_HOSTS=/path/to/your/hosts .RE .PP \fBNSS_WRAPPER_HOSTNAME\fR .RS 4 If you need to return a hostname which is different from the one of your machine is using you can use: NSS_WRAPPER_HOSTNAME=test\&.example\&.org .RE .PP \fBNSS_WRAPPER_MODULE_SO_PATH\fR, \fBNSS_WRAPPER_MODULE_FN_PREFIX\fR .RS 4 If you have a project which also provides user and group information out of a database, you normally write your own nss modules\&. nss_wrapper is able to load nss modules and ask them first before looking into the faked passwd and group file\&. To point nss_wrapper to the module you can do that using NSS_WRAPPER_MODULE_SO_PATH=/path/to/libnss_yourmodule\&.so\&. As each nss module has a special prefix like _nss_winbind_getpwnam() you need to set the prefix too so nss_wrapper can load the functions with NSS_WRAPPER_MODULE_FN_PREFIX=\&. .RE .sp For _nss_winbind_getpwnam() this would be: .sp .if n \{\ .RS 4 .\} .nf NSS_WRAPPER_MODULE_FN_PREFIX=winbind .fi .if n \{\ .RE .\} .PP \fBNSS_WRAPPER_DEBUGLEVEL\fR .RS 4 If you need to see what is going on in nss_wrapper itself or try to find a bug, you can enable logging support in nss_wrapper if you built it with debug symbols\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 0 = ERROR .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 1 = WARNING .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 2 = DEBUG .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} 3 = TRACE .RE .RE .PP \fBNSS_WRAPPER_DISABLE_DEEPBIND\fR .RS 4 This allows you to disable deep binding in nss_wrapper\&. This is useful for running valgrind tools or sanitizers like (address, undefined, thread)\&. .RE .SH "EXAMPLE" .sp .if n \{\ .RS 4 .\} .nf $ echo "bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false" > passwd $ echo "root:x:65534:65532:root gecos:/home/test/root:/bin/false" >> passwd $ echo "users:x:1000:" > group $ echo "root:x:65532:" >> group $ LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_PASSWD=passwd \e NSS_WRAPPER_GROUP=group getent passwd bob bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false $ LD_PRELOAD=libnss_wrapper\&.so NSS_WRAPPER_HOSTNAME=test\&.example\&.org hostname test\&.example\&.org .fi .if n \{\ .RE .\} .SH "AUTHOR" .PP \fBSamba Team\fR .RS 4 Author. .RE nss_wrapper-1.1.15/doc/CMakeLists.txt000644 001750 000144 00000000146 13634203624 017433 0ustar00asnusers000000 000000 install(FILES nss_wrapper.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) nss_wrapper-1.1.15/doc/nss_wrapper.1.txt000644 001750 000144 00000007504 13634203634 020144 0ustar00asnusers000000 000000 nss_wrapper(1) ============== :revdate: 2019-05-21 :author: Samba Team NAME ---- nss_wrapper - A wrapper for the user, group and hosts NSS API SYNOPSIS -------- LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=/path/to/passwd NSS_WRAPPER_GROUP=/path/to/group NSS_WRAPPER_HOSTS=/path/to/host *./myapplication* DESCRIPTION ----------- There are projects which provide daemons needing to be able to create, modify and delete Unix users. Or just switch user ids to interact with the system e.g. a user space file server. To be able to test that you need the privilege to modify the passwd and groups file. With nss_wrapper it is possible to define your own passwd and groups file which will be used by software to act correctly while under test. If you have a client and server under test they normally use functions to resolve network names to addresses (dns) or vice versa. The nss_wrappers allow you to create a hosts file to setup name resolution for the addresses you use with socket_wrapper. - Provides information for user and group accounts. - Network name resolution using a hosts file. - Loading and testing of NSS modules. LIMITATIONS ----------- Some calls in nss_wrapper will only work if uid_wrapper is loaded and active. One of this functions is initgroups() which needs to run setgroups() to set the groups for the user. setgroups() is wrapped by uid_wrapper. ENVIRONMENT VARIABLES --------------------- *NSS_WRAPPER_PASSWD*:: *NSS_WRAPPER_GROUP*:: For user and group accounts you need to create two files: 'passwd' and 'group'. The format of the passwd file is described in 'man 5 passwd' and the group file in 'man 5 group'. So you can fill these files with made up accounts. You point nss_wrapper to them using the two variables NSS_WRAPPER_PASSWD=/path/to/your/passwd and NSS_WRAPPER_GROUP=/path/to/your/group. *NSS_WRAPPER_HOSTS*:: If you also need to emulate network name resolution in your enviornment, especially with socket_wrapper, you can write a hosts file. The format is described in 'man 5 hosts'. Then you can point nss_wrapper to your hosts file using: NSS_WRAPPER_HOSTS=/path/to/your/hosts *NSS_WRAPPER_HOSTNAME*:: If you need to return a hostname which is different from the one of your machine is using you can use: NSS_WRAPPER_HOSTNAME=test.example.org *NSS_WRAPPER_MODULE_SO_PATH*:: *NSS_WRAPPER_MODULE_FN_PREFIX*:: If you have a project which also provides user and group information out of a database, you normally write your own nss modules. nss_wrapper is able to load nss modules and ask them first before looking into the faked passwd and group file. To point nss_wrapper to the module you can do that using NSS_WRAPPER_MODULE_SO_PATH=/path/to/libnss_yourmodule.so. As each nss module has a special prefix like _nss_winbind_getpwnam() you need to set the prefix too so nss_wrapper can load the functions with NSS_WRAPPER_MODULE_FN_PREFIX=. For _nss_winbind_getpwnam() this would be: NSS_WRAPPER_MODULE_FN_PREFIX=winbind *NSS_WRAPPER_DEBUGLEVEL*:: If you need to see what is going on in nss_wrapper itself or try to find a bug, you can enable logging support in nss_wrapper if you built it with debug symbols. - 0 = ERROR - 1 = WARNING - 2 = DEBUG - 3 = TRACE *NSS_WRAPPER_DISABLE_DEEPBIND*:: This allows you to disable deep binding in nss_wrapper. This is useful for running valgrind tools or sanitizers like (address, undefined, thread). EXAMPLE ------- $ echo "bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false" > passwd $ echo "root:x:65534:65532:root gecos:/home/test/root:/bin/false" >> passwd $ echo "users:x:1000:" > group $ echo "root:x:65532:" >> group $ LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_PASSWD=passwd \ NSS_WRAPPER_GROUP=group getent passwd bob bob:x:1000:1000:bob gecos:/home/test/bob:/bin/false $ LD_PRELOAD=libnss_wrapper.so NSS_WRAPPER_HOSTNAME=test.example.org hostname test.example.org nss_wrapper-1.1.15/doc/README000644 001750 000144 00000000201 12415432734 015545 0ustar00asnusers000000 000000 The manpage is written with asciidoc. To generate the manpage use: a2x --doctype manpage --format manpage doc/nss_wrapper.1.txt nss_wrapper-1.1.15/CMakeLists.txt000644 001750 000144 00000006734 14364246635 016711 0ustar00asnusers000000 000000 # Required cmake version cmake_minimum_required(VERSION 3.5.0) cmake_policy(SET CMP0048 NEW) # Specify search path for CMake modules to be loaded by include() # and find_package() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") # Add defaults for cmake # Those need to be set before the project() call. include(DefineCMakeDefaults) include(DefineCompilerFlags) project(nss_wrapper VERSION 1.1.15 LANGUAGES C) # global needed variables set(APPLICATION_NAME ${PROJECT_NAME}) # SOVERSION scheme: MAJOR.MINOR.PATCH # If there was an incompatible interface change: # Increment MAJOR. Set MINOR and PATCH to 0 # If there was a compatible interface change: # Increment MINOR. Set PATCH to 0 # If the source code was changed, but there were no interface changes: # Increment PATCH. set(LIBRARY_VERSION_MAJOR 0) set(LIBRARY_VERSION_MINOR 3) set(LIBRARY_VERSION_PATCH 4) set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) # add definitions include(DefineCMakeDefaults) include(DefinePlatformDefaults) include(DefineOptions.cmake) include(CPackConfig.cmake) include(CompilerChecks.cmake) include(GNUInstallDirs) # disallow in-source build include(MacroEnsureOutOfSourceBuild) macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") # Find out if we have threading available set(CMAKE_THREAD_PREFER_PTHREADS ON) find_package(Threads) # config.h checks include(ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) # check subdirectories add_subdirectory(src) install(PROGRAMS nss_wrapper.pl DESTINATION ${CMAKE_INSTALL_BINDIR}) if (UNIT_TESTING) find_package(cmocka 1.1.0 REQUIRED) file(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" VALGRIND_SUPPRESSION_FILE) # add the valgrind suppressions set(MEMORYCHECK_SUPPRESSIONS_FILE ${VALGRIND_SUPPRESSION_FILE} CACHE FILEPATH "Path to the memory checking command, used for memory error detection.") include(AddCMockaTest) add_subdirectory(tests) endif (UNIT_TESTING) # pkg-config file get_filename_component(NSS_WRAPPER_LIB ${NSS_WRAPPER_LOCATION} NAME) configure_file(nss_wrapper.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper.pc @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT pkgconfig ) # cmake config files set(PACKAGE_NAME nss_wrapper) set(PACKAGE_NAME_UPPER NSS_WRAPPER) configure_file(nss_wrapper-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config-version.cmake @ONLY) configure_file(nss_wrapper-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config.cmake @ONLY) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config-version.cmake ${CMAKE_CURRENT_BINARY_DIR}/nss_wrapper-config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nss_wrapper COMPONENT devel ) add_subdirectory(doc) # Add 'make dist' target which makes sure to invoke cmake before add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) # Link combile database for clangd execute_process(COMMAND cmake -E create_symlink "${CMAKE_BINARY_DIR}/compile_commands.json" "${CMAKE_SOURCE_DIR}/compile_commands.json") nss_wrapper-1.1.15/ConfigureChecks.cmake000644 001750 000144 00000025202 14142230333 020162 0ustar00asnusers000000 000000 include(CheckIncludeFile) include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) include(CheckStructHasMember) include(CheckPrototypeDefinition) include(TestBigEndian) include(CheckCSourceRuns) set(PACKAGE ${PROJECT_NAME}) set(VERSION ${PROJECT_VERSION}) set(DATADIR ${DATA_INSTALL_DIR}) set(LIBDIR ${LIB_INSTALL_DIR}) set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}") set(SYSCONFDIR ${SYSCONF_INSTALL_DIR}) set(BINARYDIR ${CMAKE_BINARY_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR}) function(COMPILER_DUMPVERSION _OUTPUT_VERSION) # Remove whitespaces from the argument. # This is needed for CC="ccache gcc" cmake .. string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}") execute_process( COMMAND ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion OUTPUT_VARIABLE _COMPILER_VERSION ) string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" _COMPILER_VERSION "${_COMPILER_VERSION}") set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) endfunction() if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) compiler_dumpversion(GNUCC_VERSION) if (NOT GNUCC_VERSION EQUAL 34) set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden") check_c_source_compiles( "void __attribute__((visibility(\"default\"))) test() {} int main(void){ return 0; } " WITH_VISIBILITY_HIDDEN) set(CMAKE_REQUIRED_FLAGS "") endif (NOT GNUCC_VERSION EQUAL 34) endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) # HEADERS check_include_file(sys/types.h HAVE_SYS_TYPES_H) check_include_file(pwd.h HAVE_PWD_H) check_include_file(shadow.h HAVE_SHADOW_H) check_include_file(grp.h HAVE_GRP_H) check_include_file(nss.h HAVE_NSS_H) check_include_file(nss_common.h HAVE_NSS_COMMON_H) # FUNCTIONS check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF) check_function_exists(getpwnam_r HAVE_GETPWNAM_R) check_function_exists(getpwuid_r HAVE_GETPWUID_R) check_function_exists(getpwent_r HAVE_GETPWENT_R) check_function_exists(setspent HAVE_SETSPENT) check_function_exists(getspnam HAVE_GETSPNAM) check_function_exists(getgrnam_r HAVE_GETGRNAM_R) check_function_exists(getgrgid_r HAVE_GETGRGID_R) check_function_exists(getgrent_r HAVE_GETGRENT_R) check_function_exists(getgrouplist HAVE_GETGROUPLIST) check_function_exists(gethostbyaddr_r HAVE_GETHOSTBYADDR_R) check_function_exists(gethostbyname_r HAVE_GETHOSTBYNAME_R) check_function_exists(gethostbyname2 HAVE_GETHOSTBYNAME2) check_function_exists(gethostbyname2_r HAVE_GETHOSTBYNAME2_R) check_function_exists(getprogname HAVE_GETPROGNAME) check_function_exists(getexecname HAVE_GETEXECNAME) if (WIN32) check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) check_function_exists(_vsnprintf HAVE__VSNPRINTF) check_function_exists(_snprintf HAVE__SNPRINTF) check_function_exists(_snprintf_s HAVE__SNPRINTF_S) endif (WIN32) if (UNIX) if (NOT LINUX) # libsocket (Solaris) check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET) if (HAVE_LIBSOCKET) list(APPEND _REQUIRED_LIBRARIES socket) endif (HAVE_LIBSOCKET) # libnsl/inet_pton (Solaris) check_library_exists(nsl inet_pton "" HAVE_LIBNSL) if (HAVE_LIBNSL) list(APPEND _REQUIRED_LIBRARIES nsl) endif (HAVE_LIBNSL) endif (NOT LINUX) check_function_exists(getaddrinfo HAVE_GETADDRINFO) endif (UNIX) if (SOLARIS) check_function_exists(__posix_getpwnam_r HAVE___POSIX_GETPWNAM_R) check_function_exists(__posix_getpwuid_r HAVE___POSIX_GETPWUID_R) check_function_exists(__posix_getgrgid_r HAVE___POSIX_GETGRGID_R) check_function_exists(__posix_getgrnam_r HAVE___POSIX_GETGRNAM_R) endif (SOLARIS) check_function_exists(asprintf HAVE_ASPRINTF) if (UNIX AND HAVE_ASPRINTF) add_definitions(-D_GNU_SOURCE) endif (UNIX AND HAVE_ASPRINTF) set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_PTHREAD_SEMANTICS) check_prototype_definition(getpwent_r "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)" "NULL" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWENT_R) check_prototype_definition(getpwnam_r "int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)" "-1" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWNAM_R) check_prototype_definition(getpwuid_r "int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)" "-1" "unistd.h;pwd.h" HAVE_SOLARIS_GETPWUID_R) check_prototype_definition(getgrent_r "struct group *getgrent_r(struct group *src, char *buf, int buflen)" "NULL" "unistd.h;grp.h" HAVE_SOLARIS_GETGRENT_R) check_prototype_definition(getgrnam_r "int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)" "-1" "unistd.h;grp.h" HAVE_SOLARIS_GETGRNAM_R) check_prototype_definition(getgrgid_r "int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)" "-1" "unistd.h;grp.h" HAVE_SOLARIS_GETGRGID_R) check_prototype_definition(sethostent "int sethostent(int stayopen)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_SETHOSTENT) check_prototype_definition(endhostent "int endhostent(void)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_ENDHOSTENT) check_prototype_definition(gethostname "int gethostname(char *name, int len)" "-1" "unistd.h;netdb.h" HAVE_SOLARIS_GETHOSTNAME) set(CMAKE_REQUIRED_DEFINITIONS) check_prototype_definition(setgrent "int setgrent(void)" "-1" "unistd.h;grp.h" HAVE_BSD_SETGRENT) check_prototype_definition(getnameinfo "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)" "-1" "unistd.h;netdb.h" HAVE_LINUX_GETNAMEINFO) check_prototype_definition(getnameinfo "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)" "-1" "unistd.h;netdb.h" HAVE_LINUX_GETNAMEINFO_UNSIGNED) # STRUCT MEMBERS check_struct_has_member("struct sockaddr" sa_len "sys/socket.h netinet/in.h" HAVE_STRUCT_SOCKADDR_SA_LEN) check_struct_has_member("struct passwd" pw_class "pwd.h" HAVE_STRUCT_PASSWD_PW_CLASS) check_struct_has_member("struct passwd" pw_change "pwd.h" HAVE_STRUCT_PASSWD_PW_CHANGE) check_struct_has_member("struct passwd" pw_expire "pwd.h" HAVE_STRUCT_PASSWD_PW_EXPIRE) # IPV6 check_c_source_compiles(" #include #include #include #include #include int main(void) { struct sockaddr_storage sa_store; struct addrinfo *ai = NULL; struct in6_addr in6addr; int idx = if_nametoindex(\"iface1\"); int s = socket(AF_INET6, SOCK_STREAM, 0); int ret = getaddrinfo(NULL, NULL, NULL, &ai); if (ret != 0) { const char *es = gai_strerror(ret); } freeaddrinfo(ai); { int val = 1; #ifdef HAVE_LINUX_IPV6_V6ONLY_26 #define IPV6_V6ONLY 26 #endif ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&val, sizeof(val)); } return 0; }" HAVE_IPV6) check_c_source_compiles(" void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2))); int main(void) { return 0; }" HAVE_ATTRIBUTE_PRINTF_FORMAT) check_c_source_compiles(" void test_constructor_attribute(void) __attribute__ ((constructor)); void test_constructor_attribute(void) { return; } int main(void) { return 0; }" HAVE_CONSTRUCTOR_ATTRIBUTE) check_c_source_compiles(" void test_destructor_attribute(void) __attribute__ ((destructor)); void test_destructor_attribute(void) { return; } int main(void) { return 0; }" HAVE_DESTRUCTOR_ATTRIBUTE) check_c_source_compiles(" #pragma init (test_constructor) void test_constructor(void); void test_constructor(void) { return; } int main(void) { return 0; }" HAVE_PRAGMA_INIT) check_c_source_compiles(" #pragma fini (test_destructor) void test_destructor(void); void test_destructor(void) { return; } int main(void) { return 0; }" HAVE_PRAGMA_FINI) find_library(DLFCN_LIBRARY dl) if (DLFCN_LIBRARY) list(APPEND _REQUIRED_LIBRARIES ${DLFCN_LIBRARY}) else() check_function_exists(dlopen HAVE_DLOPEN) if (NOT HAVE_DLOPEN) message(FATAL_ERROR "FATAL: No dlopen() function detected") endif() endif() # ENDIAN if (NOT WIN32) test_big_endian(WORDS_BIGENDIAN) endif (NOT WIN32) if (NOT CMAKE_CROSSCOMPILING) # check whether getaddrinfo() returns "node" in "ai_canonname" for IP-addresses check_c_source_runs("#include #include #include #include #include int main(void) { struct addrinfo hints; struct addrinfo *res = NULL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; if (getaddrinfo(\"0.0.0.0\", \"389\", &hints, &res) != 0) { return 2; } if (res == NULL) { return 3; } return strncmp(res->ai_canonname, \"0.0.0.0\", sizeof(\"0.0.0.0\")) != 0; }" HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES) # Check whether getaddrinfo() returns EAI_SERVICE when the requested # service is not available for the requested socket type. check_c_source_runs("#include #include #include #include #include int main(void) { struct addrinfo hints; struct addrinfo *res = NULL; int rc; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* For wildcard IP address */ hints.ai_protocol = 0; /* Any protocol */ hints.ai_canonname = NULL; rc = getaddrinfo(NULL, \"echo\", &hints, &res); return rc != EAI_SERVICE; }" HAVE_GETADDRINFO_USES_EAI_SERVICE) # Check for non-NULL gethostent() check_c_source_runs("#include #include int main(void) { struct hostent *hostent = NULL; sethostent(0); hostent = gethostent(); endhostent(); return hostent == NULL; }" HAVE_NONNULL_GETHOSTENT) endif (NOT CMAKE_CROSSCOMPILING) set(NWRAP_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "nss_wrapper required system libraries") nss_wrapper-1.1.15/nss_wrapper-config.cmake.in000644 001750 000144 00000001174 14364206715 021352 0ustar00asnusers000000 000000 set(@PACKAGE_NAME_UPPER@_LIBRARY @CMAKE_INSTALL_FULL_LIBDIR@/@NSS_WRAPPER_LIB@) # Load information for each installed configuration. file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/@PACKAGE_NAME@-config-*.cmake") foreach(_cmake_config_file IN LISTS _cmake_config_files) include("${_cmake_config_file}") endforeach() unset(_cmake_config_files) unset(_cmake_config_file) include(FindPackageMessage) find_package_message(@PACKAGE_NAME@ "Found @PACKAGE_NAME@: ${@PACKAGE_NAME_UPPER@_LIBRARY} (version \"${PACKAGE_VERSION}\")" "[${@PACKAGE_NAME_UPPER@_LIBRARY}][${PACKAGE_VERSION}]") nss_wrapper-1.1.15/.clang_complete000644 001750 000144 00000000067 12254017317 017104 0ustar00asnusers000000 000000 -DHAVE_IPV6 -DHAVE_LIBNSL -DHAVE_LIBSOCKET -Isrc -Iobj nss_wrapper-1.1.15/.cache/000750 001750 000144 00000000000 14364246777 015262 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/.cache/clangd/000750 001750 000144 00000000000 14364246777 016512 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/.cache/clangd/index/000750 001750 000144 00000000000 14364246777 017621 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/.cache/clangd/index/test_nwrap_vector.c.6DA36926E43E358A.idx000644 001750 000144 00000010330 14255266245 026216 0ustar00asnusers000000 000000 RIFFCdIxmetastrixTn0 )ڊ`@emWa!أд Jn~h7q4myLYiݷ彼d͝"`ěX@0R4!l˶i M˜Ҏt[r+,rڲMEB1لC(2v.=cg-l38?â 6вK/ސ  Z (cj9g䢦).$]mp%'Fb>[ u elxK>Kò 4DDKò 4ccL& 4yV=Jl63P` 4m L 4m L 4::Kò 4;;Kò 4YYL& 4ZZL& 4__L& 4``L& 4}}yV=J 4yV=Jm L 4 ' 4.W{c>@ 4m LŊ; 4  m L 4''Kò 4((Kò 4PPL& 4QQL& 4qqyV=J 4rryV=Jז+V4m L4 m L4 m L4//Kò433Kò488 Kò4BB Kò4HH Kò4XXL&4^^L&4ii L&4zzyV=J4yV=J4 yV=J  4m L 4m L 400Kò 444Kò 477Kò 4<<Kò 4??Kò 4EEKò 4[[L& 4aaL& 4ddL& 4yV=J 4yV=J 4yV=JY0 4m L 4..Kò 422Kò 4WWL& 4]]L& 4yyyV=J 4yV=J[% <4m L4m L4m L4  m L4@@Kò4AAKò4FFKò4GGKò4eeL&4ffL&4ggL&4hhL&4yV=J4yV=JѢF  4 4// 433 4XX 4^^ 4zz 4AZ  4 4 4 400 444 477 4<< 4?? 4EE 4[[ 4aa 4dd 4 4 4Ђ X,4m L4 m L4 m L4//Kò433Kò488 Kò4BB Kò4HH Kò4XXL&4^^L&4ii L&4zzyV=J4yV=J4 yV=JL& 4N N# 4*W{VF  4W{yV=J 4o o' 4.W{Kò 4% %) 40W{SĆ4m L4m L4m L400Kò444Kò477Kò4<<Kò4??Kò4EEKò4[[L&4aaL&4ddL&4yV=J4yV=J4yV=JW{ 4relasrcsS248q{Y27865375386cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/test_shadow.c.85DFA55943F2551B.idx000644 001750 000144 00000003600 14255266245 024774 0ustar00asnusers000000 000000 RIFFxCdIxmetastrixT]o0 RڮaC@i[,  O{-00dO'Jk,ez|^~,=(djliu`gs^Ȧdpn2)#F_6ͬmU\dcԶd 24Y@tzkߤg]+)ka ?TXHey1%}3cʀ1.0v6ًPѝTݱb'/v\U9 yX2>쿸6o¶e Xygv$Kp5ޓGCwrmގ][\i@تINt~)EpuC)Z~5p69v@+Aw%0m&B2Nb{{L;:8s8-|I|H*%1:fd[Okt}t-^iX4Ai%9Q,ƅjR~|>XUoYl\U9u1m)symb]wՃol >3! !3! !; =3 3 W{ <3==3==refs+}E3EEW{ < 3 ;g`Bf 3"; 3"; 3++ wՃol 355 wՃoljzk% 3 3 3++ 300 355 3::}pʹ 3$( 3E$E( 3E*E.3DܖPG 3EE4= yZ3))wՃol3..wՃol333wՃol388wՃol6Nȭf 3 ; 3/7;9)'` 3AA 3BB>nG 3((wՃol 322wՃolNX)`U 3-*-1wՃol 30-04wՃol 37*71wՃol 3:-:4wՃolލ_z 3--wՃol 377wՃolޖ+V3))wՃol3..wՃol333wՃol388wՃolmb 3 ;[% <3;3;3++wՃol300wՃol355wՃol3::wՃolѢF  3)) 3.. 333 388Ђ X,3))wՃol3..wՃol333wՃol388wՃol։3eel 3 ; 3$$ wՃol`ګ 3 ;VF  3@@W{wՃol 3! ! 3BB&W{; 3  3AA&W{W{ 3==relasrcsw283Z7Zף 29:647;8594;:657cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/test_nwrap_disabled.c.59E63F9B2D58E517.idx000644 001750 000144 00000005600 14255266245 026502 0ustar00asnusers000000 000000 RIFFx CdIxmetastriSxT]o0 RڮaCGCh[, :^],Ǻ#㙒R/R?V?\yZ@i6"THڒHp!tN>B_{~5פ ud:C!3 DHqY}0C(t\Y&0=|#P24%=#ə,7Pq;ٚ%UW\pٱ/`wYBSbwʎ/cv%웢s)qH`;6$$>.jChOZm;Fp[]b؉U;5LC_l$ڡݘ=eC#$PHɀVO[Z*.qX α&?NyggxV`uI=؅ qMov0wv>+uVCE{v{j\0\^cth6zl(0\Ю繲!g0 S7nX2h  'rB=#5VTj bu#_Ŕ` \#(ꔶj|symbc3;e C3< <"3< <"t4 E3 #3 #qK D3& &3& &{5B B3I I(3I I(W{ A3nn3nnrefsb8S袹 3-- qK+}E3xxW{cr 3t4_> 3[[{5B ĵ 3t4}pʹ 3[[# 3x$x( 3x*x.'"KB 3FF 3_x] 3VV{5B 3DܖPG 3xx46MQ 3//qK4= yZ3t43t43t43""t4300qK3dd {5B 9)'` 3rr 3ss 3tt 3uuDqUh 3dd G!' 3))qKOA_ض 3CCc3;eQ fF 3XX 3_$_/Qd P\ 3XX{5B 3__"{5B c3;e 3< <" 3tt)W{d[ #h3i3iB{5B gݍY 3KK{5B 3LL{5B 3V!V){5B l:BΤӉ 3kk {5B m\܂ 3t4q_3? 3WWt4 3 # 3rr*W{{O0 /A 3gg{5B ~zƚl 3!!t43k"  3t4j6 3YY/gGŨ 3t4I، 3i3iB\S  3t4+V3t43t43t43""t4300qK3FF c3;e3dd {5B lC 3WW{5B 3^^ {5B G  3i!i){5B d\x 3XX {5B 3_$_/{5B qK 3& & 3ss%W{mE 3i*i0{5B {5B  3I I( 3uu/W{öJ$G&, 3dd{5B _Ú  3O O{5B JD 3F Fc3;eѢF  3 3 3 3"" 300AZ  3DD 3\\ 3^^ 3__ 3iiԽO? 3^"^)Ђ X,3t43t43t43""t4300qK3dd {5B ȉ9T 3t4 r 3iiVF  3qqW{ߐ$# 3 t4l1} 3((X]I 3YY{5B * Ob 3N N{5B 7 M̦ 322 qKv 3!!t4SĆ3DDc3;e3\\{5B 3^^{5B 3__{5B 3ii{5B W{ 3nnrelasrcs26975@:<;>?83aPsN 2?@:5=<48796;>4=cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/nss_utils.c.D245051A87648149.idx000644 001750 000144 00000002770 14364212160 024404 0ustar00asnusers000000 000000 RIFFCdIxmetastri9xSn0Cf&b'@GVc$d 'ȿw%۲ @%pGKvzt9UΆIŬB|vP=_d'OWcOU-1;__O~# Q V G*aC(n H[(]/i JȥѕMHQ;ey2B6R\7h#/UcgdQ ¬t:nz;m[$QcdV߀q1NDVGMFEm„B)6"WIR<$LS+)k*??~[* 4Tֽп6||ٝA~AcH2+̕Asymb!_li 81--2** 702refs}pʹ 10 0 1<<# 1dd 1} }4= yZ 1.._li 144_li 155_li 166_li 1ii_li 1vv_li4z, 1GG 1qqlVB͚ 1G G 1q q~zƚl 15"5)_li 1SS _li 1_ __li 1__"_li21B 1]] _li 1]]_li!QH 1___li 1aa_li 1xx_li='ҏ 16$6-_li 1WW_li 1a a_li 1aa&_liJD 155_li 166_li 1ii_li 1vv_liЂ X, 111 _liߐ$# 1-!-&_li 1-4-9_li 1.'.,_li*,1 1<<_li 1OO _li 1dd _li 1ii!_li 1kk _li 1vv!_li 1xx_li 1yy_li_li 1--relasrcsG541EP34562623cmdl.,,.($ + "  !%'&)/#*-nss_wrapper-1.1.15/.cache/clangd/index/test_gethostent.c.FDE119456A174D8F.idx000644 001750 000144 00000003126 14255266245 025717 0ustar00asnusers000000 000000 RIFFNCdIxmetastri(KxSn0 )ڊ`@emWa!cȴD ^~h'qcxD+~|}||rmISbƦhvHT[&܀dbJٺ2ܘn[HG۝ҿlt6Q`ɲǨm@:e @t׾wuD1SfAJ:,rʲN52D>J EXb5q%u5G^x6Jsymb>\Sc! @3 !3 !W{ ?322322refs8S袹 3 \Sc!+}E399W{ < 3 \Sc! 3 \Sc!N(og 3\Sc! 3))\Sc! 3**'\Sc!}pʹ 3# 3$( 3)#)' 39$9( 39*9.3DܖPG 39946MQ 3 \Sc! 3*4\Sc!4= yZ3\Sc!3\Sc!9)'` 366:w 3'' \Sc! 3** \Sc!G!' 3\Sc!Nb{O 3 Y?N"X 3"" \Sc!Z,g@w 3""\Sc!\Sc! 3 ! 366(W{+V3\Sc!3\Sc!ѢF  3 3Ђ X,3\Sc!3\Sc!VF  355W{3n7xĐ 3!\Sc! 3\Sc! 3##\Sc!7 M̦ 3// \Sc!W{ 322relasrcs23: I 2=>859:<;74665>8:<;=749cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/test_getpwuid_module.c.13413495523E694E.idx000644 001750 000144 00000003222 14255266245 026622 0ustar00asnusers000000 000000 RIFFCdIxmetastrixSn0 )ڊ`@emWa!أHDJ~h'qlyD )~y]|Y{I؀)i6"LN*TtcRLWRNsHˍU7פ ud:C!soqYm0c>f)8aU"5:%_G< =C3Z(An)aR&g@gk26c#h'YsƏēk ۪ظ|~d@yt#N;KɺrF{i`?hxB!T'jm;Fp9aGӦؙK.L2BߟxKȂ~Jebj`cr ǁ0TBB`KuRm"RqPŇR0Ǯފ{;ZTc:[4h[ #m1WJ6rEɼJj`(]gұXߙ Ʒii0vJ$A6J/"OŲTʷPr~]C7:ξG 1-j,_7J"symb]R( ;3 3 c`L@ <3 ,3 ,W{ :300300refs;+}E399W{cr 3R( jzk% 3ĵ 3R( 3!!c`L@ 3,,c`L@R(  3  355$W{}pʹ 39$9( 39*9.3DܖPG 3994= yZ3R( 3""c`L@3--c`L@9)'` 355 366VUO6+ 3  R( 3c`L@_2g} 3$$c`L@ 3 , 3663W{m\܂ 3  R( 3c`L@/gGŨ 3!R( +V3R( 3""c`L@3--c`L@92 3$ $c`L@[% <3R( ѢF  3 3"" 3--9@-V 3R( AZ  3 3Ђ X,3R( 3""c`L@3--c`L@ ϛE 3))c`L@VF  344W{SĆ3R( 3R( W{ 300relasrcs_275843@'>}289647596cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/nss_utils.h.BFE4622C993130F2.idx000644 001750 000144 00000000660 14364212160 024457 0ustar00asnusers000000 000000 RIFFCdIxmetastriDxuK0 Ds, 8EJىTܝ#'fոT<'ɉ2&QQLxod5'o9V>J(v7`}aۯss1#l䏫/Ծ@7X}8[0ѠHh11xf}!%%^}fqȭ8tGCjqsymb!_li ** refsx4= yZ ++_li~s檆 ''ߐ$# *!*&_li *4*9_li +'+,_li_li **relasrcs\i/yinss_wrapper-1.1.15/.cache/clangd/index/test_getnameinfo.c.779E41D17A149E05.idx000644 001750 000144 00000013324 14255266245 025766 0ustar00asnusers000000 000000 RIFFCdIxmetastriCxTn0 )ڊ`@emWa!cȴD& J^~h7I.cxDXkݗ,狟O7w> ۲lR]#F[Aq\_2.! OW!e 1T},Ŧ k(m|ȶl5Lf%K &;1@cT0B6LF9ŬE@%Ou-97L MHg*C5Y]LmP&m]`l4}~#Ҋ8֕HB¼10Gn]rI%6ígn| ,5@?Nfx#n *##c 6ը symb;{*` A3l l&3l l&2-ز D3 '3 '(P{G E3< <*3< <*T 7 @3 "3 "8vx B3 (3 (Χz C3 (3 (W{ ?33refs$ЌZ.8# 3 +}E3W{;{*` 3l l& 3-W{jzk% 3(( 3)) 388 399 3VV 3WW 3hh 3ii 3 3 3 3 3 3 3 3 3 3 3 3 3 32-ز 3 ' 3.W{}pʹ 3 3 3 3 3 3 3 3$( 3*."L(, 3_ _(P{G 3< <* 31W{0Eru 3 T 7 3II (P{G 3yy ;{*` 3 Χz 3 2-ز 3 8vx 3 8vx3/&(3 3 3DܖPG 39)'` 3 3 3 3 3 3np)({ 3T 7 322T 7 3AA(P{G 3bb(P{G 3qq;{*` 3;{*` 3Χz 3Χz 32-ز 32-ز 32-ز{6_d 3.(.1T 7 3\(\1(P{G 3&/;{*` 3'0Χz 3(12-ز 3(12-ز4'2[ 3 m 3 T 7 3 " 3)W{̓c 3 8vx 3 ( 3/W{@Mb 3,, 3.. 3ZZ 3\\ 3 3 3 3 3 3 3 3 G  3,4T 7 3J,J4(P{G 3z)z1;{*` 3+3Χz 3,42-ز 3,48vx 3,48vx(WS# 3T 7 3HH(P{G 3xx;{*` 3Χz 32-ز 38vx 38vxJ!( 3 3-- 3II 3[[ 3yy 3 3 3 3 3 3 3 3 _Ú  3T 7 3""T 7 3@@(P{G 3PP(P{G 3pp;{*` 3~~;{*` 3Χz 3Χz 32-ز 32-ز 38vx 38vx 38vx 38vx 38vx[% <3((T 73))T 7388T 7399T 73VV(P{G3WW(P{G3hh(P{G3ii(P{G3;{*`3;{*`3;{*`3;{*`3Χz3Χz3Χz3Χz32-ز32-ز32-ز38vx38vx38vxAZ  3 3&& 3// 366 3KK 3TT 3]] 3ff 3{{ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3ԽO? 3 3 3HH 3JJ 3xx 3zz 3 3 3 3 3 3 3 3Χz 3 ( 3/W{mLT 3T 7 3..T 7 3JJ(P{G 3\\(P{G 3zz;{*` 3;{*` 3Χz 3Χz 32-ز 32-ز 32-ز 38vx 38vx:{ݦPQ 3M MVF  3W{_5S 3!!T 7 311T 7 3OO(P{G 3aa(P{G 3}};{*` 3;{*` 3Χz 3Χz 32-ز 32-ز 32-ز 32-ز 38vx 38vx 38vx 38vx* Ob 3! !(T 7 31 1(T 7 3O O((P{G 3a a((P{G 3} }(;{*` 3 (;{*` 3 (Χz 3 (Χz 3 (2-ز 3 (2-ز 3 (2-ز 3 (8vx 3 (8vx 3 (8vx 3 (8vxF%@ 3,,T 7 3ZZ(P{G 3;{*` 3Χz 32-ز 32-زSĆ3T 73&&T 73//T 7366T 73KK(P{G3TT(P{G3]](P{G3ff(P{G3{{;{*`3;{*`3;{*`3;{*`3Χz3Χz3Χz3Χz32-ز32-ز32-ز32-ز32-ز32-ز32-ز38vx38vx38vx38vx38vx38vxW{ 3Ҁ 3--T 7 3[[(P{G 3;{*` 3Χz 32-ز 32-زrelasrcs2653,0\d 2=>859:<;746>8:<;7=94cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/test_thread_getaddrinfo.c.17665B73698D65D5.idx000644 001750 000144 00000004526 14332201737 027300 0ustar00asnusers000000 000000 RIFFN CdIxmetastri.xSn0 )Zw: O6a밡cH ^|h<<Ͼ~z|yī܀G0-Kv)ٚi͗V2p`| sOx1JXb  $RP5&Q6M}[5s>ô AlFr1PL48Fde1K֗qF#t)(Qb8F mJeSv|J<١ʂ-;uY-ك мV2zװE&[a*{O.=:w'/ v\4}{)olAP=*nTjB"~eu-؇[T?2V7ZhCk3*?wZ(QN5|l7۬DV<&197XX8A/6!S(s׏),9cU,7A!k+u`Z2DZG4,f { du\A|Y ͯ!&3<J=^symb]Rf @2 2 i ?2F F$2F F$W{ >2^^2^^refs3Oນ 2,,Rf+}E2eeW{jzk% 255 2>>_> 211Rf}pʹ 2 2$ $ 2-- 2.. 2// 21!1% 2CC 2T T 2XX 2e+e/ 2e1e53_x] 2((Rf3DܖPG 2ee4= yZ244Rf9)'` 2bbFRdX. 2NNi Qd P\ 2Rf 2**RfejLmF 2[[i gݍY 2 Rf 2 Rf 2("(*Rfl:BΤӉ 2@@Rfnp)({ 2" "RfoY\V 2II i q_3? 2 2)){O0 /A 2..Rf 299Rf멁Rf 2  2S Si +V244Rf멟W҆3 2HHi lC 2 Rf 2))Rf 277!Rf멢 G  2<<"Rf멥"F 2 2** (WS# 2;;&Rf며e輚(s 2XXi ז|0 2QQi j-7 2<<RföJ$G&, 2--Rf 244#Rf 255'Rfi 2 2++i  2F F$ 2bb+W{ _Ú  2! !Rf[% <255Rf2>>RfѢF  244AZ  222 277 2;;ԽO? 27#7* 2;(;/Ђ X,244RfVF  2aaW{X]I 2 Rf 2++Rf* Ob 2 Rfq m! 2//Rf~]s5" 2Rf 2** RfSĆ222Rf277Rf2;;RfW{ 2^^relasrcs8164=9;:7<2_D 1<=9435678:;35cmdl1-//)&$ , "  !%('*0#+.nss_wrapper-1.1.15/.cache/clangd/index/test_getaddrinfo.c.641BB471F444137A.idx000644 001750 000144 00000037554 14255266245 025756 0ustar00asnusers000000 000000 RIFFd?CdIxmetastri}xTmO0rMI2`i\Sw)mI;LI_O;d2yj-_m Ȥ=vɱF[!]˛zD?H$tV&0NC#lZZL&ڗ1[[!evh`v<7CbHؚg3%>Ņsټ8.64jSEcK<pj٘κmݸhPKr N3 *3 *yt5S L3_ _)3_ _)}Zg F3 73 7%  K3 '3 'xA):n I3 13 1ІO C3 &3 &[e G3 '3 'W{ A33refs93Oນ 3&& =@ 3BB =@ 3nnyt5S 37* 3%  3xA):n 3}Zg 3 +}E3W{  3 7 3>W{ =@ 3 " 3)W{jzk% 300 399 3LL 3UU 3 3 3 3 3 3 3 3 3 3 3 3F* 3 7* 3'xA):n_>. 3++ =@ 3GG =@ 3ssyt5S 3yt5S 37* 37* 37* 37* 37* 3ІO 3ІO 3&~Ƃ 3%*C/ 3%*C/ 3n})>r 3n})>r 3%  3%  3%  3eU_l 3[e 3xA):n 3}Zg 3}Zg 3}Zg 3}Zg 3}Zg 3}Zg 3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3 7* 3 ( 3/W{}pʹN 3 3'' 3(( 3)) 3+ +$ 3<< 3CC 3DD 3EE 3GG 3bb 3oo 3pp 3qq 3s s$ 3xx 3 $ 3 3 3 3 3 $ 3 3'+ 3 3! 3 3/3 3 3=A 3 3 3# 3 3-1 3 3# 3 3 3 3 3 3 3)- 3 3,0 3 3)- 3 3 3im 3'+ 3! 304 3 3 3 3 3 3 3 3 $ 3 3 3+/ 3 3 $ 3 3 3+/ 3 3 $ 3 3 3+/ 3 3$( 3*. # 3 3$ 3 3$"A d 3%*C/ 3 ' 3.W{&~Ƃ 3 ( 3/W{&  3 3'(ai3yt5S3xA):n0Eru 3&.ІO 3!)n})>r3_x] 3"" =@ 3>> =@ 3jjyt5S 37* 3ІO 3ІO 3&~Ƃ 3%*C/ 3%*C/ 3n})>r 3%  3[e 3xA):n 3}Zg 3 3DܖPG 34= yZ'3-- =@3// =@3HH =@3KK =@3uuyt5S3{{yt5S3yt5S37*37*37*37*37*3ІO3 ІO3ІO3 ІO3 &~Ƃ3%*C/3%*C/3%*C/3%*C/3%*C/3n})>r3n})>r3n})>r3% 3 % 3% 3% 3% 3eU_l3eU_l3[e3[e3xA):n3xA):n3xA):n3xA):n3xA):n4z, 39)'` 3 3 3 3 3 3 3 3 3 3 3 3 3DqUh 3 3 3 3 Nb{O 3  3  3  3 Q fF 3 3 3$/ 3 3$/ 3 3$/ 3 3$/ 3 3$/ 3 3$/ 3'Qd P\ 3$$ =@ 3@@ =@ 3llyt5S 37* 3ІO 3"ІO 3ІO 3"ІO 3&~Ƃ 3"&~Ƃ 3%*C/ 3"%*C/ 3%*C/ 3"%*C/ 3n})>r 3"n})>r 3%  3"%  3xA):n 3}Zg 3 Z,g@w 3SS =@ 3 ІO 3 %  3 eU_l 3 [e 3 xA):n 3 xA):neU_l 3 & 3-W{gݍY) 3 =@ 3 =@ 3"!") =@ 3>!>) =@ 3aayt5S 3bbyt5S 3j!j)yt5S 37* 37* 3!)7* 3ІO 3ІO 3!)ІO 3!)ІO 3&~Ƃ 3&~Ƃ 3!)&~Ƃ 3%*C/ 3%*C/ 3!)%*C/ 3!)%*C/ 3n})>r 3n})>r 3!)n})>r 3%  3%  3!)%  3eU_l 3eU_l 3[e 3[e 3!)[e 3xA):n 3xA):n 3%-xA):n 3}Zg 3}Zg 3!)}Zg 3  3  3!) l:BΤӉ 3;; =@ 3WW =@ 3ww yt5S 3 yt5S 3 7* 3 7* 3 7* 3 7* 3 7* 3 ІO 3 ІO 3 &~Ƃ 3 %*C/ 3 %*C/ 3 n})>r 3 %  3 %  3 eU_l 3 [e 3 xA):n 3 }Zg 3 }Zg 3  3  3  3  3  3  3 np)({ 3  =@ 3 ІO 3 &~Ƃ 3 %*C/ 3 n})>r 3 %  3 eU_l 3 [e 3 xA):nn})>r 3 * 31W{q_3? 3## 3?? 3kk 3 3 3 3 3 3# 3 3yt5S 3_ _) 30W{{O0 /A 3(( =@ 344 =@ 3DD =@ 3PP =@ 3ppyt5S 37* 3ІO 3ІO 3&~Ƃ 3%*C/ 3%*C/ 3n})>r 3n})>r 3%  3%  3eU_l 3[e 3xA):n 3xA):n{6_d 3S(S1 =@ 3(1ІO 3(1%  3(1[e 3xA):n}Zg 3 7 3>W{6)rf` 3 m 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +V'3-- =@3// =@3HH =@3KK =@3uuyt5S3{{yt5S3yt5S37*37*37*37*37*3ІO3 ІO3ІO3 ІO3 &~Ƃ3%*C/3%*C/3%*C/3%*C/3%*C/3n})>r3n})>r3n})>r3% 3 % 3% 3% 3% 3eU_l3eU_l3[e3[e3xA):n3xA):n3xA):n3xA):n3xA):n![ 3#1 3#1 3-HoQp 3zz yt5SlC 3## =@ 322 =@ 3?? =@ 3NN =@ 3kkyt5S 37* 3ІO 3 ІO 3ІO 3 ІO 3&~Ƃ 3 &~Ƃ 3%*C/ 3 %*C/ 3%*C/ 3 %*C/ 3n})>r 3 n})>r 3%  3 %  3 eU_l 3 eU_l 3[e 3 [e 3xA):n 3 xA):n 3xA):n 3}Zg 3  3  3 Kǁ 3 3 3-@Mb 3N"N* 3R)R1 3S S 3 3"* 3  3 3"* 3  3 3"* 3)1 3  3' 3 3 G  377! =@ 3!ІO 3!&~Ƃ 3!%*C/ 3!%*C/ 3!n})>r 3&.eU_l 3xA):n"F 3$$ 3@@ 3ll 3 3$. 3 3(WS# 366% =@ 3%eU_l¨%  3 ' 3.W{d\x 3 7* 3 ІO 3$/ІO 3 ІO 3$/ІO 3 &~Ƃ 3$/&~Ƃ 3 %*C/ 3$/%*C/ 3 %*C/ 3$/%*C/ 3 n})>r 3$/n})>r 3'xA):nãL'f 3 yt5SJ!( 3 3xA):n 3 1 38W{j-7 377 =@ 3ІO 3&~Ƃ 3%*C/ 3%*C/ 3n})>r- 3}} yt5SöJ$G&, 3'' =@ 3//" =@ 300& =@ 3CC =@ 3KK" =@ 3LL& =@ 3ooyt5S 37* 3ІO 3ІO 3&~Ƃ 3"%*C/ 3&%*C/ 3"%*C/ 3&%*C/ 3"n})>r 3&n})>r 3%  3"%  3}Zg 3 ІO 3 & 3-W{[e 3 ' 3.W{i 3%% 3AA 3mm 3 3 _Ú 3  =@ 3 ІO 3 &~Ƃ 3 %*C/ 3 n})>r 3 %  3 eU_l 3 [e 3 xA):n[% <300 =@399 =@3LL =@3UU =@3ІO3ІO3&~Ƃ3%*C/3%*C/3%*C/3%*C/3n})>r3n})>r3% 3eU_l3[eѢF # 3-- 3// 3HH 3KK 3uu 3{{ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3AZ I 3,, 322 366 3II 3NN 3RR 3tt 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3ԽO? 32"2) 36'6. 3 3") 3") 3") 3") 3") 3 3") 3'. 3  3 3 3Ђ X,'3-- =@3// =@3HH =@3KK =@3uuyt5S3{{yt5S3yt5S37*37*37*37*37*3ІO3 ІO3ІO3 ІO3 &~Ƃ3%*C/3%*C/3%*C/3%*C/3%*C/3n})>r3n})>r3n})>r3% 3 % 3% 3% 3% 3eU_l3eU_l3[e3[e3xA):n3xA):n3xA):n3xA):n3xA):nVF  3W{X]I 3%% =@ 3AA =@ 3mmyt5S 37* 3ІO 3ІO 3&~Ƃ 3%*C/ 3%*C/ 3n})>r 3%  3}Zg 3 * Ob 3  =@ 3 ІO 3 &~Ƃ 3 %*C/ 3 n})>r 3 %  3 eU_l 3 [e 3 xA):nq m! 3)) =@ 3EE =@ 3qqyt5S 37* 3eU_l 3[e 3.5xA):n&Sw 3xA):nF%@ 3RR' =@ 3'[e~]s5" 3$$ =@ 3@@ =@ 3llyt5S 3%  3$.%  3}Zg 3 ;I1g=$ 3 3SĆI3,, =@322 =@366 =@3II =@3NN =@3RR =@3ttyt5S3yt5S37*37*37*37*37*3ІO3ІO3ІO3ІO3ІO3ІO3ІO3ІO3&~Ƃ3&~Ƃ3&~Ƃ3%*C/3%*C/3%*C/3%*C/3%*C/3%*C/3n})>r3n})>r3n})>r3n})>r3n})>r3% 3% 3% 3% 3% 3eU_l3eU_l3eU_l3[e3[e3[e3xA):n3xA):n3xA):n3}Zg3}Zg3}Zg3}Zg3}Zg3}Zg3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 W{ 3Ҁ 3'0ІOrelasrcs23+J2?@956:<;>=84775@9<=>?8;:46cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/testsuite.c.AF64C06B860D31A7.idx000644 001750 000144 00000031554 14255266245 024515 0ustar00asnusers000000 000000 RIFFd3CdIxmetastri xUo "ަjR'ڮꇵӦj-gva;2)ύ|9㷏wi?>?1ULx C2x(,!?E]S uih@EpQ@Ѐ ÛZhd1>DmR¶؈=Ȉ:qgI"WG2pm;ɚ`SIW4Ɉ7PG,S^q0x| X&ϗ4p杅m=?hxSvL=:wWBuv FvEp3S&&IƋoi$Mꆂsڢj 6КqYƩwlD \ifcVǫ 2{yb?NegFFNNLJvUዮaB ˄!/?\wLZÞdeRZSrS]0 e7 (7 (s=> O7 !7 !tv gl Y7 #7 #u{,> d7 7 |u 57G G7G Gt Z7 7 ~*| 275 575 5>s0Z f7 7 3zp X7 !7 !8 H7 7 qVd\ \7 7 ju N7s s7s s&w! c7 &7 &DŽM i7 87 8I_FC J7] ]7] ]Ҟ?7 K7i i7i iҾc P7 !7 !swS_+A 47 7 ,Oe R7 #7 #ITc#N T7 "7 "oԾ V7 !7 !=m  j7 $7 $W{ L77refs)+}E7W{8Ay 7 ! 7(W{cr 7// s PD 7/"/( s PD 7LL |u 7LL|u 7 &w! 7"(&w! vK"y 7 ' 7s=> =  700! s PD 70'0/ s PD 7VV |u 7VV#|u 7ddI_FC s PD 7) ) 7u{,> 7u{,> 7u{,> 7>s0Z 7>s0Z 7>s0Z 7f^wd 7f^wd 7f^wd 7f^wd 7f^wd 7f^wd } 7"%/rjzk% 7,, 7-- 700 711 722 7:: 7;; 7CCĵ 7qVd\r"^B 7  7 Ru? 7 K 7 ?.A 7 8Ay 7 vK"y#5U5 7  7Ru? 7?.A 7&w!K 7  7HT}pʹ( 7== 7=2=6 7>> 7>2>6 7?? 7?)?- 7 7  7 7 7  7 7  7 76: 7 7 7" 7 7 7  7 7 7  7 7 7" 7 7 7" 7 7 7# 7 76: 7 7&* 7 7$( 7*.ޕ>+ 7swS_+A 724`DH 7cl5 7Ҿc 7,Oe"%/r 7 ! 7>s0Z 7f^wd$SG 7Ҿc'"KB 7 7 7 7 24`DH 7 " 7u{,> 78Ay 7m>03A 7__ I_FC7`` I_FC7dd I_FC7ee I_FC7ff I_FC 7ppҞ?77 87 87 87 8 7r"^B 7&w!3DܖPG 74= yZ% 7i.i4Ҟ?7 7kkҞ?77"%/r7U6~7swS_+A7swS_+A 7,2r"^B 7r"^B73zp7oԾ 7 24`DH 724`DH724`DH 7 cl5 7cl57cl5 7u{,> 7>s0Z 7f^wd 7 Ҿc 7Ҿc7Ҿc 7,Oe 7,Oe7,Oe 7Ru? 7K 7?.A7tv gl 7 &w! 7&w! 7&w! 78Ay 78Ay 78Ay 7m>0 7 vK"y9)'` 7 7 7 7 7?.A 7 $ 7DŽMFciɂ 7  7Ru? 7?.A 7&w!HxO'8 7 24`DH 7 cl5HT 7 , 73W{I.K@ 7II|u 7JJ|u 7VV|u 7W W|u 7XX|u 7swS_+A 7swS_+A 7swS_+ARu? 7  7ITc#NT0tv؁+ 7  7 #5U5 7 3zp 7 Fciɂ 7 oԾ 7 Ҿc 7 ,Oe 7 vK"y 7 vK"yU6~ 7 ! 7>s0Z 7f^wdVUO6+ 7 %qVd\ 7"'U6~XTl 7U6~YJW 722! s PD 72'2/ s PD 7XX |u 7XX#|u 7ffI_FC\t:9 7\⟇ 7 tv gl]â吴  7GG 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 ^0a 7 Ҿc 7 ,Oecl5 7 $ 7>s0Z 7f^wde7ҢE 7 =m  7 m>0 7 vK"yf^wd 7 % 7DŽMk< go 711 s PD 71%1+ s PD 7WW |u 7WW|u 7eeI_FCm>0 7 ( 7s=>m\܂ 7)-)3 s PD 7** s PD 7G%G+|u 7G9G?|u 7]]%I_FC 7i i&Ҟ?7 7s s&ju 79?t 7t 7 "%/r 7"%/r 7 qVd\ 7qVd\ 7 U6~ 7U6~ 7*024`DH 724`DH 724`DH 70624`DH 7,2cl5 7cl5 7cl5 706cl5 7u{,> 7>s0Z 7f^wd 728=m  74:&w! 78Ay 7m>0pH䕴U 7cl5s=> 7 ! 7(W{sߢE/Hv 7ZZ 7  7  7 7 7  7 7  7 7 7 7 7 7 7 7 7 7 7 7  7$( 7 7 7 tv gl 7 # 7&w!u8 pt 7u{,> 7  7ITc#N|u 7G G 7t 7 "%/r 7qVd\ 7 U6~ 724`DH 7cl5~#^n{` 724`DH~zƚl 7:: ~*| 7:&:-~*| 7 swS_+A 7!swS_+A 78 7$Ru? 7&K 7&?.A 7$?.A 7 &w! 7"&w! 7$+ vK"y 7!( vK"y{ 7,Oet 7  7u{,> 7f^wd21B 7<<~*| 7<"<(~*| 7 swS_+A 7swS_+A 7#Ru? 7%K 7%?.A 7#?.A 7&w!3k"  7t~*| 75 5 7Ru? 7Ru? 7Ru? 7K 7K 7K 7?.A 7?.A 7?.A 7?.A 7?.A 7?.AOW 7== 7>> 7 7 7 /gGŨ 7,, s PD 7,&,- s PD 7II |u 7II!|u 7__I_FC 7$u{,> 7&>s0Z 7&f^wd 7$f^wd 7")=m  7%&w! 7$+m>0 7!(m>0 7 24`DH 7 cl5>s0Z 7  7HT3zp 7 ! 7K 7?.A+V7== ~*|7>> ~*|7 "%/r7 U6~7swS_+A7swS_+A7 3zp7 oԾ724`DH7cl57Ҿc7,Oe7tv gl7 tv gl7 m>07 vK"yHoQp 78Ay 78Ay 7ITc#N 7ITc#N 7HT 7HT 7DŽM 7DŽM 7s=> 7s=>0㰬~O 7 78 7  7 r"^B 7 Ru? 7 Ru? 7 K 7 K 7 ?.A 7 ?.A 7 ?.A 7 ?.A 7 &w!}s5|B 7 %Fciɂ 7"'oԾ 7 tv gl 7 tv gl 7tv gl 7tv gl 7&w!b">G 73zpӰ='ҏ 7;;"~*| 7;(;1~*| 7 swS_+A 7%swS_+A 78{6~, 7 Ҿc 7 ,Oe?7 7  7  7  7  7 7&+qVd\ 7  7u{,> 7f^wdju 7s s 7 t 7 "%/r 7 qVd\ 7 U6~ 724`DH 7cl5 7m>0 7m>0si#z 7oԾս&w! 7 & 78AyX$ 7  7  7  7  7 79YBy 7--" s PD 7-(-1 s PD 7JJ |u 7JJ%|u 7``I_FCDŽM 7 8 7?W{I_FC 7] ] 7nn Ҟ?7 7 u{,> 7 u{,> 7 >s0Z 7 >s0Z 7 f^wd 7 f^wd 7 f^wd 7 f^wd[% <7,, s PD7-- s PD700 s PD711 s PD722 s PD7::~*|7;;~*|7CC~*|ѢF  7 7 7 7 7 7 79@-V 7.. s PD 7.".( s PD 7KK |u 7KK|u 7#u{,> 7%>s0Z 7%f^wd 7#f^wdҞ?7 7i i 7 u{,> 7 >s0Z 7 f^wd 7 8Ay 7 m>0Ҿc 7 ! 7Ru? 78Ay 7 vK"yAZ  7.. 7// 7<< 7du? 7tv gl 7tv glЂ X, 7"%/r7U6~7swS_+A7swS_+A73zp7oԾ724`DH7cl57Ҿc7,Oe7tv glȉ9T 7FciɂswS_+A 7  7#5U5 7 3zp 7Fciɂ 7 oԾ 7 Ҿc 7 ,Oe,Oe 7 # 7K 7?.AITc#N 7 " 7)W{VF  7W{ߐ$# 75,51~*| 766~*| 7$)swS_+A 7swS_+A 7#8 7$r"^B 7$T0tv؁+ 7 #5U5 7 #5U5 7 3zp 7 3zp 7 Fciɂ 7 Fciɂ 7 oԾ 7 oԾ 7).Ҿc 7 Ҿc 7 Ҿc 705Ҿc 7+0,Oe 7 ,Oe 7 ,Oe 705,Oe 7 Ru? 7 K 7 ?.A 7=m  7&w! 7 &w! 7 &w! 7 8Ay 7 vK"y*,1 7==~*| 7=(=.~*| 7>>~*| 7>(>.~*| 7? ?~*| 7??%~*| 7BB~*| 7B B&~*| 7CC ~*| 7C)C/~*| 7 swS_+A 7swS_+A 7)/swS_+A 7swS_+A 7 swS_+A 7 swS_+A 7#swS_+A 7swS_+A 7 swS_+A 78 78 78 78 7 T0tv؁+ 7$*T0tv؁+ 7T0tv؁+ 7=m  7)/=m  7=m oԾ 7 ! 7K 7?.Aeq 7 =m  7 $ 7&w!v 7#5U5SĆ7.. s PD7// s PD7<<~*|7"%/r7U6~73zp7oԾ7&w!W{ 7-S 7 7 7 7relasrcs6;><7k»n<6EG?9:A@BFDC>;<=89FG?BDE=8AC@:cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/test_gethostby_name_addr.c.C9C460E7372D7C61.idx000644 001750 000144 00000023466 14255266245 027524 0ustar00asnusers000000 000000 RIFF.'CdIxmetastritxUn0 )ڊ@emWaأHD n~(U #.(ח~)^_/?o (ЂTUeaX(} U0_\. "KWVr|0BE6x*A ĀaYmITC(z5S ĸ?CYU$"-.X"[zmjraujgi([oɲo`W||7/c9XWj0u9bF3ȅTOjm6`|=hrѱ:Qfc+ml;b*ՉHՏG926MCŷ[͐ fL8`u! z ř#JgSɉ|-?O'&ӂc̬Ms ϲjB2 DRZ7Lt&$t'mo0uiv)> qT܇ )<|8tL@ˁdlc<}Y0\GYNS|?c* O7P/KW.9 Ci:U)|plϰԾ^L-d@JsymbmYm D3 &3 &$kR H3 *3 *Rݩ0 I3x x-3x x-]> M M3 "3 "zHd4܊ J3 &3 &}Nk u G3 *3 *AC E3b b$3b b$K|# N35 5&35 5&G9 C3 $3 $>e? L3B B+3B B+d{Xxk F3 %3 %?N9 K3 +3 +W{ B33refs!+}E3W{ j-3G93mYmjzk% 3%% 3>> 3LL 3^^ 3oo 3uu 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3mYm 3 & 3-W{}pʹ 3?? 3NN 3N7N; 3OO 3@D 3 3  3  3  3  3$( 3*.$kR 3 * 31W{ b, 3mYm#ԥ 3}Nk u 3$kR&k b 3zHd4܊ 3?N93A 3}Nk u 3}Nk u 3$kR 3$kR3DܖPG 34= yZ83<<K|#3==K|#3JJ>e?3KK>e?3QQ>e?3RR>e?3kkAC 3llAC 3mmAC 3ssAC 3Rݩ03Rݩ03Rݩ03Rݩ03Rݩ03d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3G93G93G93zHd4܊3zHd4܊3zHd4܊3zHd4܊3 ?N93 ?N93 ?N9 3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3 }Nk u 3$kR3$kR3$kR3$kR3$kR3$kR3$kR3 $kR3mYm3mYm3mYm4z, 3,,9)'` 3 3 3 3 3 3 3 3 3 3 3DqUh 3 3 3 3 3 G!' 377K|# 3DD>e? 3eeAC 3zzRݩ0 3d{Xxk 3G9 3zHd4܊ 3?N9 3}Nk u 3$kR 3mYmNb{O 3  3 Nzf 3?? K|#OA_ض 3""]> M 3**]> M 300]> MRݩ0 3x x- 34W{TH 3==K|# 3>>K|# 3KK>e? 3LL>e? 3RR>e? 3^^>e? 3llAC 3ooAC 3Rݩ0 3d{Xxk 3d{Xxk 3d{Xxk 3d{Xxk 3G9 3G9 3zHd4܊ 3zHd4܊ 3?N9 3}Nk u 3}Nk u 3$kR 3$kR 3mYm 3mYmUxt 3G9 3mYmVX5W 3;;K|# 3II>e? 3jjAC 3Rݩ0Y?N"X 3pp AC 3 d{Xxk 3 d{Xxk 3 G9 3 zHd4܊ 3 }Nk u 3 $kR 3 mYmZ,g@w 3rrAC 3 Rݩ0 3d{Xxk 3d{Xxk 3zHd4܊ 3}Nk u 3}Nk u 3$kR]> M 3 " 3)W{_[Cx 32:G9 32:mYmeRM 3 3kCn 3.. ]> MlVB͚ 3  3%+ 3  3%+oY\V 3EE >e?zHd4܊ 3 & 3-W{}Nk u 3 * 31W{ڇ< 3G96)rf` 3d d 3  3 AC  3b b$ 3+W{K|# 35 5& 3NN5>e?e]’ 3}Nk u 3$kRs Aе 3 3+V63<<K|#3==K|#3JJ>e?3KK>e?3QQ>e?3RR>e?3kkAC 3llAC 3mmAC 3ssAC 3Rݩ03Rݩ03Rݩ03Rݩ03Rݩ03d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3G93G93G93zHd4܊3zHd4܊3zHd4܊3zHd4܊3 ?N93 ?N93 ?N93}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3 }Nk u3$kR3$kR3$kR3$kR3$kR3$kR3 $kR3mYm3mYm3mYmG9 3 $ 3+W{@Mb 3.6 3,4 3"* 3 319 3"* 3p 3,,%epQE 3 3e輚(s 3OO >e?𷳥ז|0 3NN>e?X$ 3ɴ/ 3 3 3G9 3'.G9 3mYm 3)0mYm[% <3%%]> M3>>K|#3LL>e?3^^>e?3ooAC 3uuAC 3Rݩ03d{Xxk3d{Xxk3d{Xxk3d{Xxk3G93zHd4܊3zHd4܊3?N93}Nk u3}Nk u3}Nk u3$kR3$kR3mYmѢF 1 3<< 3== 3JJ 3KK 3QQ 3RR 3kk 3ll 3mm 3ss 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3>e? 3B B+ 32W{AZ  3   3## 3(( 3++ 3,, 311 3pp 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3ԽO? 3p"p) 3rr 3 3.5 3,3 3") 3 318 3") 3") 3 318 3") 3 3 3 3")Ђ X,63<<K|#3==K|#3JJ>e?3KK>e?3QQ>e?3RR>e?3kkAC 3llAC 3mmAC 3ssAC 3Rݩ03Rݩ03Rݩ03Rݩ03Rݩ03d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3d{Xxk3G93G93G93zHd4܊3zHd4܊3zHd4܊3zHd4܊3 ?N93 ?N93 ?N93}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3}Nk u3 }Nk u3$kR3$kR3$kR3$kR3$kR3$kR3 $kR3mYm3mYm3mYmd{Xxk 3 % 3,W{X:; 3 3*'9w_ 3 ]> M 3'' ]> MVF  3W{3n7xĐ 3mm AC 3rr'AC 3 Rݩ0 3 Rݩ0 3 d{Xxk 3(d{Xxk 3 d{Xxk 3'd{Xxk 3 G9 3)G9 3 zHd4܊ 3'zHd4܊ 3?N9 3 }Nk u 3 }Nk u 3'}Nk u 3 }Nk u 3'}Nk u 3}Nk u 3 $kR 3 $kR 3($kR 3$kR 3 mYm 3)mYm?N9 3 + 32W{SĆ3  ]> M3##]> M3((]> M3++]> M3,,]> M311]> M3ppAC 3d{Xxk3d{Xxk3G93G93zHd4܊3zHd4܊3?N93}Nk u3}Nk u3}Nk u3$kR3$kR3$kR3mYm3mYm3mYmW{ 3혩 3d{Xxk 3d{Xxk 3d{Xxk 3d{Xxkrelasrcs2975A:3j fi29@A:56;=847=>?@8<;46cmdl2.00*& - "$  #! ')(+1%,/nss_wrapper-1.1.15/.cache/clangd/index/nss_wrapper.c.496306141B70693D.idx000644 001750 000144 00000325000 14364212160 024712 0ustar00asnusers000000 000000 RIFFCdIxmetastriV Bx[moFg ~6W&nθ6,i?+r%ݥ~3%)wS\sg^+̊G]ÃXmŞ*P;Ujk/!dōG @}@;CߜeEV7. 8[:4YqUtkܵI2dM5.>bҨLOû;I5QgP?хA3/`A#tL_efW/OAȶ4 /Wdz6[ Q϶ wK1{ gT̉SRD| 'p妩ʼe[j7ێzYJpvxd|CTм9aO0v(saeŶ1A 'tvuY@|Czce7 U!3Wh&[ljp`$d[994S76|M!WW*&q5)T888,Q@ g/'mp)#j50 1O`NbU~!LEse==h0'eM "ɂz8\K sͰpezy1?%%u5Η4KH,RMrR紪TVEKSɠtm ~na%J%;a-RYuDHFtC{Z荲W1 v~K r,(T߰'Pq(0v=Ad=jS4:%GK5G?%gA i& lW29P|^@t<\NjC'#|秋*|S:?s83o[ 3lt\<od"F zno =Y+]:};?nf;MO*ټj x{9|>'oُ/N_鵕/^gN|ړO.<Hq';:O7<49[9?!qIP0}T~=!)l %\@7L.)߯鹎XhK)-o`6\C߀i/a.f0GRFU56ez݁[QH]X؜ڹ orr Ap 2}*?bW4l0Xl`UbJgZafLC;);;?B-uvy,-pH* zuVꪸ8`|ٖJ> oG4׍Y/dA xz58@Jc>=Wvn <$ۚגMa~I.[RAp9MaL,Dmv\s_coSuYKW~s+rR dk7 z]tӼ|d,q[FR|G:T~؆!e=Q9un}D.u#t`t*bGx}|ȗrx;K@:劃G5QnWRzg<9TWlAغnjsq9k'^},mQlz 3R$E m5Y4} m+Q,_UB$q~__7ԣZpjQqq!D3ȆM/E<="I"i(UOIl'~S0a?DR?H¿DZ$++(L7a_P #-B3%WQHfd6symbB׮ŬILz $$**eE#8Jj  r4?y,  0 01y:   Ś    'Gdh8S袹 ,,r r 'jjDž$h=   Z_>_ ))#))#CSA""tk   ~ //Kĥ!  Q dW 2 22 2   i`  ** y   ($Ag  ''$''$ } ''  !  Sy#Ӳ{   E && A0j % ̞  p +Α~GɈjm'p;ў * ** *6y.1*gbrY% ' '' '>< _> 00  zĵ ''mm nx a    ms'y ) )) )&<@Y)   E[?}  ժQh   4s剕   V     !%d.k &&$&&$09B # #" ":*Mz //EM ((x`   &  &դ\ % %( (pr   ` U}@  siUs\ - -- -p=/հnߗ   1K<   ! !1Ǐ1ڱU 1X5 * ** *2O'z{K " "! !3R\<a3l + ++ +46MQ --! ^44t:  6Nȭf , ,QQ ]7f@ 8V?'A 2 22 29O@,f;92x-;FԵm , ,, ,<‗   >nG , ,YY _B`^ US     C ?'$   D;q , ,, ,F$a.Y  Gc:  G߻0HxO'8 (( G G tH&6    J&#ӼIJ J   JA. &&11L>(N    Lث1  LDY  M+J#M99M5C  MȋLTN&v=h  Oh7 --*--*OA_ض 22  kPHtՕ  Qv3   R5yYeRC$S[>ĖUw*VX5W --$ pVX,sVtW-,   WElarWNPEPXTl ''  Y_  YwwZx,Ͼ    Zkx  ZN5T[;4   [g7\Tx \op  ]f/4]iȤ7;  ^/OIU ----^0a ++ B B [^35dT`6lU> ,,",,"` } " "" "a9D  a-{aY + + b}=JESX   b5Zq # #& &cWGk c^]z-  d9h˜  eRxU+  ! !eD  fY0a  ! !fwTg#ՁZ !!gB l ((g>Mg%eyV%@   iDFQC   jɑ^k ?hro     k"   l@v  l63P`  ! !n #}l ##**n4  " "oz<+ p}pH䕴U ((  )xqb=`q47   q)/~y   rws !F  tQY  tT ( ..*..*u']^4   u z%Q   u%k( >  uu,   u2\M  vVLvv#y(O ( (( (wn.xMwr   xq`e  y#D'u  y}&[(  z 2   |Gt5`| aYY"YY"}=Gс   )  )~#^n{` ((SS m~fͱr  $ $~:Hm  oP{ ++  (ظ rX  c>@h'i 2 2 2 2 ӄ1v    3k" ''ss oZIN> ,,?   "  "b5###njB2  s  $ $8w(5n>K  .  ;fp   ''x%  ' '^8N  ! ! (( M M \<\A-Q\   A Yu ""++E㦰L'oI.iu=   #  #ц,4  z!]a45u     kw --(--(Fc[x  MO _   #  #lm$ --'--'|f#UٮzRuy$^F  e]’    *ĴIaw  ! !?8,)a       ٞsM 0 00 0k  Q=Wݷ,FsRq/;  kb׫   00ZG/^ $$**v * ,,D@1׀x__ Vm+b  &ݒTߐ}4;^   )  )J39v   *Q ,,%  Wѓ 22f<N 22k( ! !"! !"*7w'  v?ƻ  f ))6CxJ $ $" "uKHl  & -R$$'drì],N9vZ(  b">G ))   vRɼM  Z   mY  G|=  ɵ7   φ눛  |~   G{6~, ** < < sPՎYyXGLh:؞a ; aP  b݉5#R    lij< / // /MX>Ci'rF  ybBٯ0 $ $" "+##0::j %%11dK;c ' '' '^)|8hS   6%h.\0si#z **  u蘣i  9qx~U --11e [>mb ,, A A iqEf] **" !!++-?$     (r r    E8  ʿR˙2!wk  ˲~fNF ,,{vX"  * *̆E;G ))gLxU   ͋x?  " "t-@Y0 $$my/Y~ 3 !!-!!-ѝok<  HgUe # #! !ߘ~  du? ,,  #wE^    u E     ȉ9T **dd u&zzFB --00qY>  % %؇$ , ,, ,أx/B --)--)@   `ګ ,, I I Yj^_we:dOl  qL . .  p ,,",,"GPیֹrP % %! !(<E   ܦ&Q ))(TWi9?* 1 11 1Vh# **ݡ &ݦ{% ! !"! !"dq}  ߡS6Gߙ(ev dfZ^ ( (( (oeWa   i   *  *Ibx  }f    6?4(     蒐~-꒺fCM ++Ӭ@#  ۑˆ$|ɭ7% c0e&    w#K_z:MS`    7 M̦ --x x ZVEsUf  vUhz~;? # #" "Mdd~   6D  } *q  X?Q   #  #I~  l    nz@ + ++ +򚰅gRpz:  " "̤/##WQ] ))mjC  3! --+--+,՞*j   9x譗   "  "sڑf8KcE   X i  ~  ( (~ ]Ys) $ $! !gev ))jj v߆n    h: ---- W]  혩 ..% qHar@refsX׮ŬI r7 {vX" {vX"  ؞a pr 2 2f<N 22f<N$ЌZ.8# 11Lz * %g#ՁZ $$*M%Z eE#  &ݒT #hs  #hs  #hs  #hs  #hs  #hs  #hs   -  - 05EM /4gB l 33f<N 3*3/f<N8Jj_ ))# **ȉ9T !f  B`^ US%ľS? scr  (<E -3(<E (<E  z 2 z 2CSA= "z!]  ! (X?Q  ! (b}=JESX  ! (.iu=  ! (q47   !@  ! ( _  ! (u z%Q   !t  ! (xMwr  ! (9x譗  ! (Qv3  ! (J  ! (ɵ7   !<‗  ! (?  ! ('j b1   !!+,q  ! (,՞*j   !ժQh  ! (x`   !'kw g  ! (4;^  ! (g>i  ! (jDž$h=  ! (}=Gс  ! (KcE  ! (C ?'$  ! (iDFQC  ! (fp  ! (4s剕                                                            tk   >  >  >  ''$ ''ĵ } '' RKaM ~ YǶ 8<YǶ 1k X (,1k X   ͋x?  ( ,͋x? Sy#Ӳ!M~ 3 !!ݦ{% 33f<N 33)f<N 33f<N A0jcWGk ؞a $$ ]Ys) $ $ ]Ys) % ̞(N  L>(N ~GɈj w#K_z: #> (,>  > >  |~  |~  |~ !̆E;G ̆E;G ̆E;G f f f ܦ&Q 33 f<Nm'p ~ u']^4 g#ՁZ ''g`Bf  gLxU .5gLxU EM %,gB l $gB l;ў * * **{6~,6y.1  &ݒT #gLxU '+gLxU  gLxU gLxU J39v EM !gB l gB l gB lN(og  oeWa oeWa !oeWa <\A-Q\  <\A-Q\ <\A-Q\ $<\A-Q\  <\A-Q\ 1y:*g .14| 9q<  # F* .. qL 00)lij< 00%lij<ID$b gLxU gLxU_> 00ĵ ''x acWGk  #%#&b5Zq #(#)b5ZqZ  'z     k"   (O`,&ms'y ) ) ))b">G&<@Y)   1k X   ͋x?E[?}x`   & - -46MQդ\  ( 5g#ՁZ % %(pr      ` U+ l63P` [;4  pr (<E gLxU > >  <\A-Q\ "qY> ##n #}l $$ZG/^ $$Lz %%0::j &&JA. && 4Ӝ  gLxU  gLxU # vv    0 0gL|   &k b b, !! -   ,, mb ,, 6Nȭf ,, `ګ ,, >nG 8"ZV > >  ~!vo= 22 f<N 22 f<N 22 f<N 22 f<N"L(, 11#hs      J J    ׀x__  -  Vm+b  : 22 N>#ԥ  ؞a  W-,  ''x%$SG **$Zܰ> rr%szB ! ! !! b,% B. ")r7  pr  pr !!" ! !" ""` } " "` } ""A Yu " "A Yu ""(߷!dU " "(߷!dU ""2O'z{K "" 2O'z{K """ `C " "" `C ##;? # #;? ##HgUe ## HgUe ##b5Zq # #b5Zq ##n #}l # #n #}l ##09B # #09B $$ZG/^ $ $ZG/^ $$ybBٯ0 $ $ybBٯ0 $$ ]Ys) $$ ]Ys) $$Lz $ $Lz %%xJ % %xJ %%یֹrP %% یֹrP %%0::j % %0::j %%դ\ % %դ\ &&JA. & &JA. && 4 & & 4 22f<N&k b &7';TK (($ ((~#^n{`&  .. 00) 00%'.   $u']^4 qY>   'j b1   + +{'kw g   --7 M̦'r@ʫ  ~  u']^4  g#ՁZ * *;ў(O`,&  #hs #hs #hs #hs #hs #hs #hs 228V?'A33f<N)OqD 22Wѓ)|Pd **# **$SG*$|/ //qL //#qL*vG   +++b}} YǶ 1k X   ͋x?+,w228V?'A22Q dW22Wѓ22f<N33f<N.14|  &/9qp=cWGk ؞a "" " `C ""%" `C ## ;? ##";?.lvy5 !!!" ""` } ""!A Yu ""(߷!dU ""!" `C ##;? ##!n #}l ##09B $$!ZG/^ $$ybBٯ0 $$!Lz %%xJ %%!0::j %%դ\ &&!JA. &&! 4/հnߗ (N  J39v |~ |~ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ 1y: 1y: 1y: 1y: 1y: 1y: 1k X 1k X ''x% ''x% ''x% ''x% ''x% ''x%  ͋x?  ͋x?## n #}l## n #}l$$ ZG/^$$ ZG/^$$ Lz$$ Lz%% 0::j%% 0::j%% 0::j&& JA.&& JA.&& JA.&& 4&& 4&& 4 ))ÿnX ,,du?22 f<N22 f<N22 f<N22 f<N33 f<N 33f<N 33f<N3R\<a p +Α 25(<E  #(<E  (<E  L>(N   i`   qEf] ,/Vh# 22f<N 33f<N3_x]  Y0 Y0  ?8,)a s s <\A-Q\ 1k X !!%szB // qL // qL // qL3/&(3 11 113l + + ++^0a4 ˊ         ̤/ kb׫ 0::j   }=Gс   iDFQC   4s剕   kb׫ !3!<%szB !&!/ b, %%0::j ..tT ( . .ڇ< .. qL 080AٞsM 00 ٞsM 1+14_5S 11_5S 11_5S46MQ --4= yZ           .4                    M+J# m'p  ݷ, 򚰅gR [g7  |Gt5` wn. (T F H$  fY0a 1K<  ^8N  eRxU+ ''x%  ;? ` } (߷!dU  xJ 09B ybBٯ0 դ\ ;92x-   c>@ [;4  \Tx   ?8,)a   b}=JESX   q47   u z%Q   Qv3   ɵ7   'j b1   jDž$h=  ( .KcE   C ?'$   iDFQC   4s剕   4s剕  pr pr #hs  #hs  q)/~y (<E z 2 gLxU > > 1y: (T F H$  fY0a 1K<  ^8N  eRxU+ 1k X ''x% gL| gL| &k b aw aw e]’   ͋x?   kb׫ !!%szB !!%szB !! b, ""` } ""(߷!dU ## ;? ##09B $$ybBٯ0 %% xJ %%0::j %%դ\ &&JA. && 4 &&!%d.k ''rY% ''rY% '' } ''  '' '' ''XTl ''dK;c ((&7';TK (( fZ^ ((fZ^ ((pH䕴U ((v#y(O ))D@e ))ms'y ))ms'y ))b">G **Z_>_ **1X5 **1X5 **si#z **;ў **)|Pd ++ nz@ ++nz@ ++{ ++3l ++aY --Oh7 ..3! ..tT ( 00ٞsM 00ٞsM 11ٞsM 1)1/9?* 22"OA_ض 22f<N4 p +Α #hs  #hs  #hs  #hs  #hs  #hs  #hs  ׀x__ ׀x__ /4 i`  /4qEf] 05Vh# 22f<N 2*2/f<N4t:  >  >  >  >  >  >  >  >  :*Mz  :*Mz  ~  ~  ~  r4?y,  oeWa  <\A-Q\  <\A-Q\  <\A-Q\  <\A-Q\  <\A-Q\  <\A-Q\  <\A-Q\  1y:   i`   qEf]  Vh#  EM  gB l  ̆E;G  f  ܦ&Q  1k X  ''x%  ͋x?  ͋x?  kb׫ ! !~ 3:.29 / /lij<:w W-,;92x- ^)|8hS       ".gL| ".aw !"!.%szB &"&.!%d.k '"'.rY% '"'.  '"'. '"'.dK;c ("(.&7';TK ("(.fZ^ ("(.v#y(O )").D@e )").ms'y *"*.Z_>_ *"*.1X5 *"*.;ў *"*.)|Pd +"+.nz@ +"+.3l +$+0aY -"-.Oh7 ."..3! ."..tT ( 1$10ٞsM 22"f<N;FԵm , , ,,`ګ;Xhlo# #;eS!_7 Y Y| ++aY<‗   **{6~,<Ƭ gLxU gLxU>nG , ,?"w^2   k"   (O`,&?G$F< gLxU gLxUA:?v  B`^ US      &<@Y)  <\A-Q\  <\A-Q\B6|A 00 ٞsMC ?'$    &k bD;q , , ,,mbF$a.Y}=GсGc:x~U  ''x%  ''x% 0::j JA.  4  դ\  դ\ ,3qL ],N9   x`   4;^   g>i  jDž$h=  jDž$h=   }=Gс  C ?'$  C ?'$  iDFQC  iDFQC 1k X 1k X $+1k X  ''x%  ''x%  gL|  gL|  &k b  &k b  aw  aw e]’ e]’   ͋x?   kb׫   kb׫ ! !%szB ! !%szB ! ! b, ! ! b, !!~ 3 !!~ 3 %%0::j %%0::j % %դ\ % %դ\ &&JA. &&JA. && 4 && 4 --lm$ --46MQ -- h: --&zzFB --Oh7 --Oh7 --VX5W --^/OIU -->x~U --3! ..3! ..혩 ..tT ( ..tT ( ..ڇ< .,.3qL 00ٞsMG߻0  ) ) H8EBo KK           , , 3 3HxO'8 (( H&6cWGk  $!$"ZG/^ $&$'ZG/^ $!$"ybBٯ0 $#$$ybBٯ0I.K@   &<@Y) //qL 00 lij(N    !0#hs   Lث1cWGk ؞aLDY4;^L% 5n>K q)/~y <\A-Q\LU; 11M+J# ~ u']^4 g#ՁZ ''rY%M99M5CcWGk ؞aMȋLT p +Α #(<E )-(<E  (<E (<E L>(N  ! i`   i`   i`  qEf] qEf] qEf] Vh# 22 f<NN&v=hGQd P\ .. yY ..qL ..%qL . .qL ..qL . .qL ..qL 0 0lij< 00lij< 0 0lij< 00!lij< 0 0lij  YǶ  YǶ  YǶ  oeWa   i`    i`    i`    i`   qEf]  qEf]  qEf]  Vh#  EM  gB l  gB l  gB l  gB l  qY> qY>  ̆E;G  ̆E;G  ̆E;G  f  f  f  ܦ&Q  1k X  1k X  1k X  1k X  1k X  1k X  ͋x?  ͋x?  ͋x?  ͋x?  ͋x? ! !~ 3 + +aYRC$Ė $:*Mz  <\A-Q\ <\A-Q\ ##n #}l $$ZG/^ $$Lz %%0::j &&JA. && 4 ))ÿnX ,,du? ..qL 0 0lij<\op ?g>i]â吴 6                                                             !! . .^/OIU -- -5-=>x~U - ->x~U^0a ++ ^35dT ,," ,,6Nȭf` }  " )g#ՁZ " ""a9D  ̆E;GeRxU+  ! (u']^4  !eD  r7  {vX"  preRM         !!fY0a  ! (u']^4  !fwTMiDFQC  g%eyV%@   "prgݍY    qL qL   fp   fp   ͋x?   ͋x?   ͋x?   ͋x?  ͋x? ..yY ..qL ..qL ..qL ..qL ...6qL //lij< //lij< //lij< / /lij< 0 0lij< 0 0lij< 0 0lij< 0!0)lij< 0(00lij< 00_> 0 0_>iDFQC   ! ! b,jɑ^ 蒐~- :*Mz r4?y,  r4?y,  1k X %'1k X  ͋x?jVی //$k ?hro   $u']^4 qY>   k"  #hs #hs #hs #hs #hs #hs 22N>22f<Nk< go  (<E +1(<E (<E z 2  z 2l:BΤӉ   ͋x? //qL 00lijCi'  ݷ, "ݷ,  i`  %(T F '-(T F qEf] H$ '-H$ Vh#  fY0a "fY0a " `C ;? #;? "  &` } (.` } A Yu (߷!dU (.(߷!dU MȋLT   X?Q  b}=JESX  b}=JESX   .iu=  q47  q47    _  " (u z%Q  u z%Q (<E (<E (.z 2 <Bz 2 '-z 2  i`  %(T F '-(T F (T F qEf] H$ '-H$ H$ Vh# Vh#  fY0a "fY0a fY0a !!" !!" " "&` } "(".` } ""A Yu ""A Yu ""(߷!dU "(".(߷!dU """ `C """ `C ##;? ###;? &&!%d.k &&!%d.k '' 3k" '5';rY% '('.rY% '('. } ')'/ } ''  ''  '' ĵ '.'4 '('. '!''XTl ')'/XTl ((&7';TK ((&7';TK (( ~#^n{` (#()fZ^ ((#fZ^ ((pH䕴U (($pH䕴Un #}l * %g#ՁZ ##*np)({ ..'qL / /qL /%/1qL 11ٞsM 11(ٞsMnw<  n4   "  J JoAb| 1 1ٞsMoz<+  oP (/<\A-Q\ %,1y: 1y:  1y: %,1y: !*!1kb׫ !0!7~ 3p} ֟l6 "#hs  "#hs  "#hs  "#hs  q)/~ypŰ{^y  ~  YǶ 1k X   ͋x?pH䕴U ((qFf/: (@*ל:uqb=`C ?'$  s !FcWGk ؞as o|e *7w'sD k  q)/~ysߢE/Hv                                           tQY  ~  u']^4  g#ՁZ ( (v#y(OtZߴh {vX"t{-      t\P;o     ! ! % % % % & & & &tT ( ..* ..ڇ ,3> >  qY>  qY> %,̆E;G $̆E;G ܦ&Q~C3 s s s 22 f<N 33 f<N 33 f<N 33 f<N~:Hm  ~  u']^4  g#ՁZ ( (dK;c$oNz 2z 2z 2z 2z 2z 2oP     E <\A-Q\ %-<\A-Q\ 1y:  1y:{ ++ظ rX@ ;  Y0 &l63P` CKl63P`  l63P`  [;4 [;4 -51y: )11y:h'i +1> $*> qY> #qY> $f #f ܦ&QӄN> 2 2 22%Wѓ貄ӄ1vcWGk  "!""" `C "&"'" `C #!#";? ###$;?8qp   Θp8 ""` } ""(߷!dU ##;? ##"n #}l ##09B $$"ZG/^ $$ybBٯ0 $$"Lz %%xJ %%"0::j %%դ\ &&"JA. &&" 4҆}ג1J-aLL,EWQ]/Hv */HZIN>/H*Q/HNF0*ל:u4'2[ . . 1 1 1 1 1 1 1 13k"  '',i V      22 22& 22 2!2* 22 2"2+ZIN> , (#hs  *#hs 22N>228V?'A22Q dW22Wѓ22f<N33f<NꈠmR .. yY ..qL?   " * *$SGb5# #6%h.\0 "0<\A-Q\ -;<\A-Q\ 1y: )71k XnjB2K  6%h.\0 <\A-Q\.Ċ''x%  ' 4u']^4  '^8N  ! (u']^4  !%^O   k"/gGŨ  (<E .5(<E (<E z 2 z 2  z 2 %, i`  $ i`  Vh# (( <\A-Q\   %8#hs   A Yu + %g#ՁZ ""+E㦰 .. 00% 0%00m        / / / / 0 0 0 0 1 1 1 1.iu=   # ' 'ĵц,4_8 11ٞsM 1*10ٞsMaw  ! e]’?8,)a   ~fͱr    #hs s Aе         ̓c 11ٞsM 0 0 11_5Sk_ *0*81X5 *0*8;ў *0*8)|Pd +0+8nz@ +0+83l +0+8aY -0-8Oh7 .0.83! .0.8tT ( 121:ٞsM 2 2f<N 2#2+f<N 22f<NuggF 5Eݷ, ~ u']^4 g#ՁZ ((fZ^Fs ֟l6  # (?8,)a   ?8,)a   ?8,)a &+q)/~yKHQ  *ל:uRq/;228V?'A22Q dW22Wѓ22f<N33f<NꚘK  gLxU  gLxUD@1cWGk ؞a $$ Lz $$%Lz %% xJ %%"xJ׀x__   ''3k" '' } ''ĵ ''XTl ((HxO'8 ((~#^n{` ((pH䕴U (( )) ꡛm8 ))v ))b">G **ȉ9T **si#z **{6~, **$SG ++{ ++^0a ,,du?𱲛Vm+b   &k b e]’ !! b, ,,8S袹 --46MQ --7 M̦ --VX5W ..혩 ..ڇ< 00_> 11_5S &ݒT  φ눛 gLxU gLxU J39v J39v![ //-ߐ}cWGk ؞a "" A Yu ""%A Yu "" (߷!dU """(߷!dU4;^   ) - -VX5WHoQp   !n4 "n4 $  $   #hs  %#hs  %#hs  %#hs  %#hs   : ))ÿnX 119?*J39v   !0#hs   92 ) )ÿnX!QH [;4 z 2 1k X  1k X ''x%   ͋x? ,,du? // qL // qL 00 lij<*Q , (#hs  *#hs 22N>228V?'A22Q dW22Wѓ22f<N33f<N%  qY>  f  ^8N  ZG/^  ybBٯ0  b5Zq  b5Zq  aY  aY  - 2xMwr  # (J   ɵ7   ,՞*j   ,՞*j (<E >  qY>  qY>  qY> qY>  f  ^8N # #b5Zq # #b5Zq $$ ZG/^ $$ ybBٯ0 (.(3ÿnX ))ÿnX ) )ÿnX )()-ÿnX )!)& ꡛm8 )$))Z_>_ **ȉ9T **!1X5 **si#z + +aY + +aY ,#,(du? ,0,5du? ,,du? ,,du? ,+,0du? ,:,?du?𱲤7Qt/ # #b5Zq ++,aYդK   "F .. ..# 00( 00$p 1 1f ) $u']^4 ) ^8Nzd n4 ħ(WS# / /qL䧣6CG ))RɼMcWGk ؞aƮ Z   #hs  #hs mYcWGk ؞aƮw )) G|=cWGk ؞aƯɵ7   * *si#zφ눛  #hs  #hs  #hs  #hs  #hs  (7#hs  #hs  #hs   -  - 6?4( EM  /EM EM +EM EM +EM u E .gB l  gB l  gB l  gB l gB l 33f<N 33)f<N 33f<N |~   !0#hs   J^~6  sְ='ҏ > 09> >ݰG r7 pr   gL|   aw !!%szB & &!%d.k ' 'rY% ' '  ' ' ((dK;c ( (&7';TK ( (fZ^ ((v#y(O ) )D@e ) )ms'y * *Z_>_ * *1X5 **;ў * *)|Pd + +nz@ ++3l ++aY - - Oh7 . . 3! . . tT ( 1 1ٞsM{6~, ** PՎY oP  1y: !!k( !!~ 3 !!~ 3 !N!Q~ 3 !!ݦ{%yXGLh:O ^)|8hS   "n4   n4   "n4   "n4   "n4   X?Q   b}=JESX   .iu=   q47   @    _   u z%Q   t   xMwr   9x譗   Qv3   J   ɵ7   <‗   ?   'j b1   !+,q   ,՞*j   ժQh   x`   'kw g   4;^   g>i   jDž$h=   }=Gс   KcE   C ?'$   iDFQC   fp   4s剕                                                             W-,  W-, 2 2 f<N 2 2f<N 2 2f<N 22f<N 2 2f<N 2 2f<N 22f<N 2 2f<N 2 2f<N 22f<N 22f<N겝؞a  ,pr?7d  %                                         .3                                                                                                                                                    ; aPĶMX>Ci' ~  u']^4  g#ՁZ ((&7';TKrFcWGk ؞aƶybBٯ0  " )g#ՁZ $ $"y1% 1 1ٞsM䶐+ #~ u']^4 g#ՁZ --Oh75Q 0 0lij< 1 1ٞsM 1 1ٞsM0::j 1 0g#ՁZ %%1dK;c ' ' ((HxO'8Ps&sss sָ^)|8hS  ꒺fCM  #-W-, &0  2 2f<N   %8#hs   "ʿ $#hs  (<E (<E >ݻ ֟l6 $#hs  $#hs  $#hs  $#hs  &2(<E &2L>(N  &2gLxU &2J39v &2> &2 |~ 7C<\A-Q\ (1y:H 6%h.\0  jɑ^ 7D:*Mz  ~ 8Er4?y,  YǶ #0oeWa <\A-Q\ $1<\A-Q\ )<\A-Q\ 1y:   kb׫ !!~ 3si#z **-   n4 11 ٞsM 11 ٞsM 11ٞsM 22 9?*蘣ii   jDž$h=   }=Gс   KcE   C ?'$   iDFQC   fp   4s剕  !֟l6#  &p} "L'oI 4  '2(<E #.L>(N  eE#  '2gLxU #.J39v )0  '2<\A-Q\ #.1y: ge  '2> #. |~  & 1?8,)a $/q)/~y ,7~fͱr ,7s '2(<E #.L>(N  '2gLxU #.J39v '2> #. |~ '2<\A-Q\ #.1y: 2 2f<N 2 2f<N 3 3f<N 3 3f<N"*  #hs   1y:_-ix%d *ל:uè_qr4?y,   r4?y, 1y: CG1k X  C G͋x?VUCi' +ݷ, *tQY "/ &3Uw* +򚰅gR &3*ĴI +[g7 *'r@ʫ &38w( +|Gt5` *-?$ ,9̤/ ,9+ -:& -R $1wn. 2? i`  )6(T F 2?qEf] )6H$ (5a45u 2?Vh# )6fY0a (5V -:qY> 1>̆E;G )61K<  1>f )6^8N (5'. 1>ܦ&Q )6eRxU+ (5k ?hro 8Ekb׫ 8E&zzFB 9F>x~U /<''x% 3@" `C *7;? 3@" *7` } 3@A Yu *7(߷!dU )62O'z{K )6HgUe 2?Lz *7xJ 2?n #}l *709B 2?ZG/^ *7ybBٯ0 )6 ]Ys) )6یֹrP .;b5Zq 9F0::j 9FJA. :G 4 0=դ\ Q=W 2?{vX" %2؞a pr pr &3pr pr 2? i`  )6(T F 2?qEf] )6H$ (5a45u 2?Vh# )6fY0a (5V -:qY> 1>̆E;G )61K<  1>f )6^8N (5'. 1>ܦ&Q )6eRxU+ (5k ?hro /<''x%  gL|  aw  8 Ekb׫ ! !%szB !3!@" "*"7` } "3"@A Yu "*"7(߷!dU ")"62O'z{K "3"@" `C #*#7;? #)#6HgUe #.#;b5Zq #2#?n #}l #*#709B $2$?ZG/^ $*$7ybBٯ0 $)$6 ]Ys) $2$?Lz $*$7xJ %)%6یֹrP %9%F0::j %0%=դ\ &9&FJA. &:&G 4 & &!%d.k ' 'rY% ' '  ' ' ' 'dK;c ( (&7';TK ( (fZ^ ( (v#y(O ) )D@e ) )ms'y * *Z_>_ * *1X5 * *;ў * *)|Pd + +nz@ + +3l + +aY -8-E&zzFB - -Oh7 -9-F>x~U . .3! . .tT ( 1 1ٞsM 2 2f<N9YBy (<E 2;(<E (<E z 2 z 2>x~U 1 0u']^4 --1\ c| $s=m2  "*ל:ue [>228V?'A22Q dW22Wѓ22f<N33f<NBeX   J J  {vX"{vX"  *؞a؞a؞a؞a؞a؞a؞a؞a؞a؞a؞a؞a؞ăE;G ) $u']^4 ) 1K< 减    ..&gLxU   %8#hs   ͋x?  " 00lij<ɞi  J JehKw   k"   (O`,&t-@  ~ /Ёxl%    _Ú  ..&qL . .qL /$//qL 11ٞsM 11'ٞsM=7  ,,JD "n4 #n4 g%eyV%@  >  1k X  ͋x? 11 ٞsM 11 ٞsM 11 9?*Y0 $ l63P` 1k Xmy/Y ,, 6Nȭf ,, p ,, >nGȉ9T **&zzFB 0 .u']^4 --0ׂԻz //qL //qL 11 ٞsMqY>  % 0u']^4  %؇$ , , --8S袹أx/B --) -->x~U 33f<N@   ((HxO'8`ګ ,, j^_we  &ݒT 25gLxU  #gLxU  gLxU  J39v ,/EM  gB l 33f<N X]  00 ٞsM 1"1-ٞsMmLT <\A-Q\  <\A-Q\ 00lij< 00lij<:dOlnGGPcWGk ؞a ## n #}l ##%n #}l ## 09B ##"09Bۅ׾   J J W-, #hs  1y:22Q dW22WѓیֹrP  ! %g#ՁZ % %!(<E   %8#hs   fr2p` -aLL WQ] v * ZIN> *Q NF   -k"  /(O`,& #2*ל:u *ל:ux["׿ zzܦ&Q ) $u']^4 #qY> ) eRxU+(TWi  >  >  >ݡ &  #>  >  |~   |~  ̆E;G  f ,/ܦ&Q:{ݦPQ 11ev  .14| 9q >  qY> ̆E;G $1K<  ',1K<   1K<  f ^8N ',^8N  ^8N ܦ&Q  ܦ&Q  eRxU+ !eRxU+  eRxU+ ##n #}l ##n #}l # #%09B #(#-09B $$ZG/^ $$ZG/^ $$ybBٯ0 $($-ybBٯ0 $$Lz $$Lz %%xJ %%"xJ ))D@e )) D@e )) v )5):ms'y )()-ms'y )()-b">G ))).b">G ))Z_>_ ** Z_>_ ** ȉ9T *.*31X5 *(*-1X5 *!*&si#z *)*.si#z **)|Pd ** )|Pd ** $SG +#+(nz@ ++"nz@ ++{ ++#{i  G4z  u5̦  r7 $({vX" pr ++ aYt   (([  U U 4 2 1g#ՁZ &&2*,1  >  >  > !>  >  >  > > % |~ qY>  &qY>  qY>(߷!dU  " )g#ՁZ " ""_5S 11 ,E'x~U) i   * . .혩Ibxi   jDž$h=   }=Gс   KcE   C ?'$   iDFQC   fp   4s剕                                                             #hs  "#hs  %#hs   gL| .gL|  aw .aw !! %szB !!.%szB && !%d.k &&.!%d.k '' rY% ''.rY% ''  ''.  ''  ''. '' dK;c ''.dK;c (( &7';TK ((.&7';TK (( fZ^ ((.fZ^ (( v#y(O ((.v#y(O )) D@e )).D@e )) ms'y )).ms'y ** Z_>_ **.Z_>_ ** 1X5 **.1X5 ** ;ў **.;ў ** )|Pd **.)|Pd ++ nz@ ++.nz@ ++ 3l ++.3l ++"aY ++.aY -- Oh7 --.Oh7 .. 3! ...3! .. tT ( ...tT ( 11"ٞsM 110ٞsM 22f<N 22*f<NӬ@# >  |~  |~q m!  ͋x? .. yY // qL 050(N  a45u Vh# Vh# ,/Vh# V Uf > > > > > > > > > > > > > :*Mz :*Mz ~ ~ ~ r4?y, YǶ YǶ YǶ oeWa oeWa <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ <\A-Q\ 1y: i`  i`  i`  i`  i`  qEf] qEf] qEf] qEf] Vh# Vh# EM EM gB l gB l gB l gB l gB l qY> qY> ̆E;G ̆E;G ̆E;G ̆E;G f f f f ܦ&Q ܦ&Q 1k X 1k X 1k X 1k X 1k X 1k X 1k X ''x%  ͋x?  ͋x?  ͋x?  ͋x?  ͋x?  ͋x?  ͋x?  kb׫!! ~ 3!! ~ 3)) ÿnX++ aY!   .. // // 00 116D228V?'A22Q dW22Wѓ22f<N33f<NmjC?7NPOBCRXLS*Vnss_wrapper-1.1.15/.cache/clangd/index/test_initgroups.c.96654DF285FBEEBF.idx000644 001750 000144 00000002554 14364212160 025777 0ustar00asnusers000000 000000 RIFFdCdIxmetastrixS]o0 R ]S}6{ Ȣ@ _?Iie ӑRZ+qiӏOJ?[0$AZlLŤR9\L7 5ᗍQVg kOS,L [ DHmu8b涪JbyZ\GxƐzh3F 9+L@u4.0.8/Pэg%nvv؆R|eBw#89ulI ێ1F͖`4ԣSwJcAw؉ҩ-CGZ􈸶|-uk-)P v$v.} WZTZ;r@s21,ooJ޼}?{3U©>uwwnuwdX^ڙ̩A2$㜺b9D8Ogj`ՄbWq-52K /`ڋ Wҟ ̍,+%!ԛvd6symb>'k 9/ !/ !W{ 8/((/((refsS+}E/00W{'k / ! /--(W{}pʹ /  /0$0( /0*0.(ai/'k3DܖPG /004= yZ/'k4z, /9)'` /--\⟇ /'k ꡛm8 /'k얼+V/'kHoQp /'k}s5|B /  'k /'k /'k /&+'kѢF  /AZ  /!! /##Ђ X,/'kVF  /,,W{@ / 'k;I1g=$ /SĆ/!!'k/##'kW{ /((relasrcsk/$76730542152064371cmdl/+--'# * !    $&%(."),nss_wrapper-1.1.15/.cache/clangd/index/nss_nwrap.c.6CD8D6240BEF45A7.idx000644 001750 000144 00000012372 14364212160 024510 0ustar00asnusers000000 000000 RIFFCdIxmetastri_xTn0 )j@a躡k&f(%_?Iio:䡨CҌsƿ?q|{G+R<1~/V!M1I?|9]dH9C~Id\:k<-4('QfAP,\0VIUDط9NFꤕԝ#W{ ӱ,#A-=)Jj+_RE+U Ԧ%-cq'F\[:pvyIP oGOon(OZZ/b?+|.0 a6+fŌxmmC,6#@  >* * ]Hi? 0>">"1v4d% 7>  >0 0 2 $>B B$4ex#+ I>>:G 1> >3 3Df8eT 2> >+ +wt 6>  >, , 8lR 8>  >. . Ǧ H>>e 5>  >8 8 zLI, J>> 2 K> > =%# 4>  >= = !*w L>J J>J J#mlh 3>  >4 4  b4 :> >2 2refs\M%Z > cr >ff !*w >ff!*w > 8lR =  >tt!*w >uu!*w > 8lR B%؎S >* * >  ]Hi? >" >** B%؎S >++ Df8eT >,, wt >.. 8lR >00 1v4d% >22  b4 >33 :G >44 #mlh >88 e >== =%# >BB 2 B%؎S > Df8eT > wt > 8lR > 1v4d% >  b4 > :G > #mlh > e > =%# > 2*. > > >ޕ>+ > 2 8lR > b4 >:G >&#mlh >&#mlh >&#mlh >&e >&e >&e >&=%# >&=%# >&=%# > 220 0 >  2B B$ > $3_x] >8lR4= yZ >-- wt >//8lR >111v4d% >66 #mlh >;; e >@@ =%# >MM !*w > wt >8lR >1v4d% > #mlh > e > =%#4ex#+ > >#mlh >e >=%#:G >3 3 > ;eS!_7 >  ]Hi?Df8eT >+ + > QF  >RR!*w >[ [!*wVUO6+ >.!.&8lR >!&8lRXBWl~ > #mlh > e > =%# > 2 2V V!*w >xx!*w >yy!*w > 8lRe7ҢE > e > e > e > 2%+2 2vv!*w >ww !*w > 8lRlVB͚ >\ \m\܂ >,(,.wt >.3.98lR >0:0@1v4d% >J"J(!*w >KK!*w >NN!*w >(.wt >398lR >8lR >:@1v4d%wt >, , >  ~zƚl > Ǧ > 4ex#+ > zLI,$oN>YY!*w>aa!*w>cc!*w>tt!*w>vv!*w>xx!*w8lR >. . >  21B >Ǧ >4ex#+ >zLI,Ǧ > >#mlh >e >=%#Θp8 >)<#mlh >)<#mlh >)<#mlh >)<e >)<e >)<e >)<=%# >)<=%# >)<=%#e >8 8 >  /gGŨ >TT!*w >aa!*w >bb !*w > 8lRzLI, > >#mlh >e >=%#!QH >__!*w}s5|B >=!=&=%# >B1B62CC2!&=%# >16222 2 B%؎S >Df8eT >wt >8lR >1v4d% 2 >  >  b4 > :G > #mlh > #mlh > #mlh > #mlh='ҏ > Ǧ > 4ex#+ > zLI,=%# >= = >  9YBy >cc!*w >dd!*w > 8lR!*w >J J > 8lR9@-V >ee !*w >ee!*w > 8lRЂ X, > Ǧ>Ǧ>Ǧ>Ǧ> 4ex#+>4ex#+>4ex#+>4ex#+> zLI,>zLI,>zLI,ߐ$# >4(4-#mlh >7 7#mlh >9 9e >< <e >> >=%# >A A=%# >Ǧ >4ex#+ >zLI, >(-#mlh > #mlh > e > e > =%# > =%#[  > *,1 >Ǧ >4ex#+ >zLI,#mlh >4 4 >  _li >#mlh >#mlh >#mlh >e >e >e >=%# >=%# >=%# b4 >2 2 > relasrcs<@AEC>X # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(CheckCCompilerFlag) macro(add_c_compiler_flag _COMPILER_FLAG _OUTPUT_VARIABLE) string(TOUPPER ${_COMPILER_FLAG} _COMPILER_FLAG_NAME) string(REGEX REPLACE "^-" "" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}") string(REGEX REPLACE "(-|=|\ )" "_" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}") check_c_compiler_flag("${_COMPILER_FLAG}" WITH_${_COMPILER_FLAG_NAME}_FLAG) if (WITH_${_COMPILER_FLAG_NAME}_FLAG) #string(APPEND ${_OUTPUT_VARIABLE} "${_COMPILER_FLAG} ") list(APPEND ${_OUTPUT_VARIABLE} ${_COMPILER_FLAG}) endif() endmacro() nss_wrapper-1.1.15/cmake/Modules/AddCMockaTest.cmake000644 001750 000144 00000006250 13634203624 022230 0ustar00asnusers000000 000000 # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2018 Andreas Schneider # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. #.rst: # AddCMockaTest # ------------- # # This file provides a function to add a test # # Functions provided # ------------------ # # :: # # add_cmocka_test(target_name # SOURCES src1 src2 ... srcN # [COMPILE_OPTIONS opt1 opt2 ... optN] # [LINK_LIBRARIES lib1 lib2 ... libN] # [LINK_OPTIONS lopt1 lop2 .. loptN] # ) # # ``target_name``: # Required, expects the name of the test which will be used to define a target # # ``SOURCES``: # Required, expects one or more source files names # # ``COMPILE_OPTIONS``: # Optional, expects one or more options to be passed to the compiler # # ``LINK_LIBRARIES``: # Optional, expects one or more libraries to be linked with the test # executable. # # ``LINK_OPTIONS``: # Optional, expects one or more options to be passed to the linker # # # Example: # # .. code-block:: cmake # # add_cmocka_test(my_test # SOURCES my_test.c other_source.c # COMPILE_OPTIONS -g -Wall # LINK_LIBRARIES mylib # LINK_OPTIONS -Wl,--enable-syscall-fixup # ) # # Where ``my_test`` is the name of the test, ``my_test.c`` and # ``other_source.c`` are sources for the binary, ``-g -Wall`` are compiler # options to be used, ``mylib`` is a target of a library to be linked, and # ``-Wl,--enable-syscall-fixup`` is an option passed to the linker. # enable_testing() include(CTest) if (CMAKE_CROSSCOMPILING) if (WIN32) find_program(WINE_EXECUTABLE NAMES wine) set(TARGET_SYSTEM_EMULATOR ${WINE_EXECUTABLE} CACHE INTERNAL "") endif() endif() function(ADD_CMOCKA_TEST _TARGET_NAME) set(one_value_arguments ) set(multi_value_arguments SOURCES COMPILE_OPTIONS LINK_LIBRARIES LINK_OPTIONS ) cmake_parse_arguments(_add_cmocka_test "" "${one_value_arguments}" "${multi_value_arguments}" ${ARGN} ) if (NOT DEFINED _add_cmocka_test_SOURCES) message(FATAL_ERROR "No sources provided for target ${_TARGET_NAME}") endif() add_executable(${_TARGET_NAME} ${_add_cmocka_test_SOURCES}) if (DEFINED _add_cmocka_test_COMPILE_OPTIONS) target_compile_options(${_TARGET_NAME} PRIVATE ${_add_cmocka_test_COMPILE_OPTIONS} ) endif() if (DEFINED _add_cmocka_test_LINK_LIBRARIES) target_link_libraries(${_TARGET_NAME} PRIVATE ${_add_cmocka_test_LINK_LIBRARIES} ) endif() if (DEFINED _add_cmocka_test_LINK_OPTIONS) set_target_properties(${_TARGET_NAME} PROPERTIES LINK_FLAGS ${_add_cmocka_test_LINK_OPTIONS} ) endif() add_test(${_TARGET_NAME} ${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME} ) endfunction (ADD_CMOCKA_TEST) nss_wrapper-1.1.15/cmake/Modules/DefinePlatformDefaults.cmake000644 001750 000144 00000001312 12247646107 024211 0ustar00asnusers000000 000000 # Set system vars if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(LINUX TRUE) endif(CMAKE_SYSTEM_NAME MATCHES "Linux") if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(FREEBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") set(OPENBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") set(NETBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") set(SOLARIS TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") if (CMAKE_SYSTEM_NAME MATCHES "OS2") set(OS2 TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OS2") nss_wrapper-1.1.15/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake000644 001750 000144 00000001227 12247646107 025170 0ustar00asnusers000000 000000 # - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) if (_insource) message(SEND_ERROR "${_errorMessage}") message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") endif (_insource) endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) nss_wrapper-1.1.15/cmake/Modules/CheckCCompilerFlagSSP.cmake000644 001750 000144 00000003560 13634203624 023616 0ustar00asnusers000000 000000 # - Check whether the C compiler supports a given flag in the # context of a stack checking compiler option. # CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE) # # FLAG - the compiler flag # VARIABLE - variable to store the result # # This actually calls check_c_source_compiles. # See help for CheckCSourceCompiles for a listing of variables # that can modify the build. # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # Requires cmake 3.10 #include_guard(GLOBAL) include(CheckCSourceCompiles) include(CMakeCheckCompilerFlagCommonPatterns) macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") set(CMAKE_REQUIRED_FLAGS "${_FLAG}") # Normalize locale during test compilation. set(_CheckCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG) foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) set(_CheckCCompilerFlag_SAVED_${v} "$ENV{${v}}") set(ENV{${v}} C) endforeach() CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCCompilerFlag_COMMON_PATTERNS) check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT} # Some compilers do not fail with a bad flag FAIL_REGEX "command line option .* is valid for .* but not for C" # GNU ${_CheckCCompilerFlag_COMMON_PATTERNS}) foreach(v ${_CheckCCompilerFlag_LOCALE_VARS}) set(ENV{${v}} ${_CheckCCompilerFlag_SAVED_${v}}) unset(_CheckCCompilerFlag_SAVED_${v}) endforeach() unset(_CheckCCompilerFlag_LOCALE_VARS) unset(_CheckCCompilerFlag_COMMON_PATTERNS) set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") endmacro(CHECK_C_COMPILER_FLAG_SSP) nss_wrapper-1.1.15/cmake/Modules/DefineCompilerFlags.cmake000644 001750 000144 00000007340 14332646173 023473 0ustar00asnusers000000 000000 if (UNIX AND NOT WIN32) # Activate with: -DCMAKE_BUILD_TYPE=Profiling set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C compiler during PROFILING builds.") set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the CXX compiler during PROFILING builds.") set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.") set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.") set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during PROFILING builds.") # Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.") set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.") # Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover" CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.") set(CMAKE_CXX_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover" CACHE STRING "Flags used by the CXX compiler during UNDEFINEDSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.") # Activate with: -DCMAKE_BUILD_TYPE=ThreadSanitizer set(CMAKE_C_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" CACHE STRING "Flags used by the C compiler during THREADSANITIZER builds.") set(CMAKE_CXX_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" CACHE STRING "Flags used by the CXX compiler during THREADSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" CACHE STRING "Flags used by the linker during THREADSANITIZER builds.") endif() nss_wrapper-1.1.15/.clang-format000644 001750 000144 00000001275 14364206715 016512 0ustar00asnusers000000 000000 # https://clang.llvm.org/docs/ClangFormatStyleOptions.html BasedOnStyle: LLVM IndentWidth: 8 ContinuationIndentWidth: 8 UseTab: true BreakBeforeBraces: Custom BraceWrapping: AfterEnum: false AfterFunction: true AfterStruct: false AfterUnion: false AfterExternBlock: true BeforeElse: false BeforeWhile: false AllowShortIfStatementsOnASingleLine: false ColumnLimit: 80 IndentCaseLabels: false AlignAfterOpenBracket: Align BinPackParameters: false BinPackArguments: false AllowAllParametersOfDeclarationOnNextLine: false AllowAllArgumentsOnNextLine: false AllowShortFunctionsOnASingleLine: Empty AlwaysBreakAfterReturnType: None AlignEscapedNewlines: Left SortIncludes: false nss_wrapper-1.1.15/config.h.cmake000644 001750 000144 00000007004 14142230333 016613 0ustar00asnusers000000 000000 /* Name of package */ #cmakedefine PACKAGE "${PROJECT_NAME}" /* Version number of package */ #cmakedefine VERSION "${PROJECT_VERSION}" #cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}" #cmakedefine DATADIR "${DATADIR}" #cmakedefine LIBDIR "${LIBDIR}" #cmakedefine PLUGINDIR "${PLUGINDIR}" #cmakedefine SYSCONFDIR "${SYSCONFDIR}" #cmakedefine BINARYDIR "${BINARYDIR}" #cmakedefine SOURCEDIR "${SOURCEDIR}" /************************** HEADER FILES *************************/ #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_PWD_H 1 #cmakedefine HAVE_SHADOW_H 1 #cmakedefine HAVE_GRP_H 1 #cmakedefine HAVE_NSS_H 1 #cmakedefine HAVE_NSS_COMMON_H 1 /*************************** FUNCTIONS ***************************/ /* Define to 1 if you have the `getpwnam_r' function. */ #cmakedefine HAVE_GETPWNAM_R 1 /* Define to 1 if you have the `getpwuid_r' function. */ #cmakedefine HAVE_GETPWUID_R 1 /* Define to 1 if you have the `getpwent_r' function. */ #cmakedefine HAVE_GETPWENT_R 1 /* Define to 1 if you have the `setspent' function. */ #cmakedefine HAVE_SETSPENT 1 /* Define to 1 if you have the `getspnam' function. */ #cmakedefine HAVE_GETSPNAM 1 /* Define to 1 if you have the `getgrnam_r' function. */ #cmakedefine HAVE_GETGRNAM_R 1 /* Define to 1 if you have the `getgrgid_r' function. */ #cmakedefine HAVE_GETGRGID_R 1 /* Define to 1 if you have the `getgrent_r' function. */ #cmakedefine HAVE_GETGRENT_R 1 /* Define to 1 if you have the `getgrouplist' function. */ #cmakedefine HAVE_GETGROUPLIST 1 /* Define to 1 if you have the `gethostbyaddr_r' function. */ #cmakedefine HAVE_GETHOSTBYADDR_R 1 /* Define to 1 if you have the `gethostbyname_r' function. */ #cmakedefine HAVE_GETHOSTBYNAME_R 1 /* Define to 1 if you have the `gethostbyname2' function. */ #cmakedefine HAVE_GETHOSTBYNAME2 1 /* Define to 1 if you have the `gethostbyname2_r' function. */ #cmakedefine HAVE_GETHOSTBYNAME2_R 1 #cmakedefine HAVE_GETPROGNAME 1 #cmakedefine HAVE_GETEXECNAME 1 #cmakedefine HAVE___POSIX_GETPWNAM_R 1 #cmakedefine HAVE___POSIX_GETPWUID_R 1 #cmakedefine HAVE___POSIX_GETGRGID_R 1 #cmakedefine HAVE___POSIX_GETGRNAM_R 1 /*************************** LIBRARIES ***************************/ #cmakedefine HAVE_LIBNSL 1 #cmakedefine HAVE_LIBSOCKET 1 /**************************** OPTIONS ****************************/ #cmakedefine HAVE_SOLARIS_GETPWENT_R 1 #cmakedefine HAVE_SOLARIS_GETPWNAM_R 1 #cmakedefine HAVE_SOLARIS_GETPWUID_R 1 #cmakedefine HAVE_SOLARIS_GETGRENT_R 1 #cmakedefine HAVE_SOLARIS_GETGRNAM_R 1 #cmakedefine HAVE_SOLARIS_GETGRGID_R 1 #cmakedefine HAVE_SOLARIS_SETHOSTENT 1 #cmakedefine HAVE_SOLARIS_ENDHOSTENT 1 #cmakedefine HAVE_SOLARIS_GETHOSTNAME 1 #cmakedefine HAVE_BSD_SETGRENT 1 #cmakedefine HAVE_LINUX_GETNAMEINFO 1 #cmakedefine HAVE_LINUX_GETNAMEINFO_UNSIGNED 1 #cmakedefine HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES 1 #cmakedefine HAVE_GETADDRINFO_USES_EAI_SERVICE 1 #cmakedefine HAVE_NONNULL_GETHOSTENT 1 #cmakedefine HAVE_STRUCT_SOCKADDR_SA_LEN 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_CLASS 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_CHANGE 1 #cmakedefine HAVE_STRUCT_PASSWD_PW_EXPIRE 1 #cmakedefine HAVE_IPV6 1 #cmakedefine HAVE_ATTRIBUTE_PRINTF_FORMAT 1 #cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_PRAGMA_INIT 1 #cmakedefine HAVE_PRAGMA_FINI 1 /*************************** ENDIAN *****************************/ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #cmakedefine WORDS_BIGENDIAN 1 nss_wrapper-1.1.15/.editorconfig000644 001750 000144 00000000472 14332646173 016613 0ustar00asnusers000000 000000 root = true [*] charset = utf-8 max_line_length = 80 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true [*.{c,h}] indent_style = tab indent_size = 8 tab_width = 8 [*.cmake] indent_style = space indent_size = 4 tab_width = 4 [CMake*] indent_style = space indent_size = 4 tab_width = 4 nss_wrapper-1.1.15/.gitlab-ci.yml000644 001750 000144 00000013714 14332646173 016575 0ustar00asnusers000000 000000 --- variables: BUILD_IMAGES_PROJECT: cmocka/gitlab-build-images FEDORA_BUILD: buildenv-fedora CENTOS7_BUILD: buildenv-centos7 TUMBLEWEED_BUILD: buildenv-tumbleweed MINGW_BUILD: buildenv-mingw UBUNTU_BUILD: buildenv-ubuntu stages: - build - test - analysis centos7/x86_64: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD script: - mkdir -p obj && cd obj && cmake3 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/x86_64: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/address-sanitizer: stage: build image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=AddressSanitizer -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/undefined-sanitizer: stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=UndefinedSanitizer -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/thread-sanitizer: stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - export TSAN_OPTIONS=second_deadlock_stack=1 - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=ThreadSanitizer -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/csbuild: stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - | if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") fi # Check if the commit exists in this branch # This is not the case for a force push git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" - csbuild --build-dir=obj-csbuild --prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON @SRCDIR@" --build-cmd "make clean && make -j$(nproc)" --git-commit-range $CI_COMMIT_RANGE --color --print-current --print-fixed tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj-csbuild/ freebsd/x86_64: stage: test image: script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make && ctest --output-on-failure tags: - freebsd except: - tags only: - branches@cwrap/nss_wrapper - branches@cryptomilk/nss_wrapper artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/x86_64/gcc: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/x86_64/gcc7: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/x86_64/clang: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/static-analysis: stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - export CCC_CC=clang - export CCC_CXX=clang++ - mkdir -p obj && cd obj && scan-build cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && scan-build --status-bugs -o scan make -j$(nproc) tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/scan ubuntu/x86_64: stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ nss_wrapper-1.1.15/nss_wrapper.pl000755 001750 000144 00000024141 13634203624 017032 0ustar00asnusers000000 000000 #!/usr/bin/env perl # use strict; use Getopt::Long; use Cwd qw(abs_path); my $opt_help = 0; my $opt_passwd_path = undef; my $opt_group_path = undef; my $opt_action = undef; my $opt_type = undef; my $opt_name = undef; my $opt_member = undef; my $opt_gid = 65534;# nogroup gid my $passwdfn = undef; my $groupfn = undef; my $memberfn = undef; my $actionfn = undef; sub passwd_add($$$$$); sub passwd_delete($$$$$); sub group_add($$$$$); sub group_delete($$$$$); sub member_add($$$$$); sub member_delete($$$$$); sub check_path($$); my $result = GetOptions( 'help|h|?' => \$opt_help, 'passwd_path=s' => \$opt_passwd_path, 'group_path=s' => \$opt_group_path, 'action=s' => \$opt_action, 'type=s' => \$opt_type, 'name=s' => \$opt_name, 'member=s' => \$opt_member, 'gid=i' => \$opt_gid ); sub usage($;$) { my ($ret, $msg) = @_; print $msg."\n\n" if defined($msg); print "usage: --help|-h|-? Show this help. --passwd_path Path of the 'passwd' file. --group_path Path of the 'group' file. --type 'passwd', 'group' and 'member' are supported. --action 'add' or 'delete'. --name The name of the object. --member The name of the member. --gid Primary Group ID for new users. "; exit($ret); } usage(1) if (not $result); usage(0) if ($opt_help); if (not defined($opt_action)) { usage(1, "missing: --action [add|delete]"); } if ($opt_action eq "add") { $passwdfn = \&passwd_add; $groupfn = \&group_add; $memberfn = \&member_add; } elsif ($opt_action eq "delete") { $passwdfn = \&passwd_delete; $groupfn = \&group_delete; $memberfn = \&member_delete; } else { usage(1, "invalid: --action [add|delete]: '$opt_action'"); } if (not defined($opt_type)) { usage(1, "missing: --type [passwd|group|member]"); } if ($opt_type eq "member" and not defined($opt_member)) { usage(1, "missing: --member "); } my $opt_fullpath_passwd; my $opt_fullpath_group; if ($opt_type eq "passwd") { $actionfn = $passwdfn; $opt_fullpath_passwd = check_path($opt_passwd_path, $opt_type); } elsif ($opt_type eq "group") { $actionfn = $groupfn; $opt_fullpath_group = check_path($opt_group_path, $opt_type); } elsif ($opt_type eq "member") { $actionfn = $memberfn; $opt_fullpath_passwd = check_path($opt_passwd_path, "passwd"); $opt_fullpath_group = check_path($opt_group_path, "group"); } else { usage(1, "invalid: --type [passwd|group]: '$opt_type'") } if (not defined($opt_name)) { usage(1, "missing: --name "); } if ($opt_name eq "") { usage(1, "invalid: --name "); } exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name, $opt_gid); sub check_path($$) { my ($path,$type) = @_; if (not defined($path)) { usage(1, "missing: --$type\_path "); } if ($path eq "" or $path eq "/") { usage(1, "invalid: --$type\_path : '$path'"); } my $fullpath = abs_path($path); if (not defined($fullpath)) { usage(1, "invalid: --$type\_path : '$path'"); } return $fullpath; } sub passwd_add_entry($$); sub passwd_load($) { my ($path) = @_; my @lines; my $passwd = undef; open(PWD, "<$path") or die("Unable to open '$path' for read"); @lines = ; close(PWD); $passwd->{array} = (); $passwd->{name} = {}; $passwd->{uid} = {}; $passwd->{path} = $path; foreach my $line (@lines) { passwd_add_entry($passwd, $line); } return $passwd; } sub group_add_entry($$); sub group_load($) { my ($path) = @_; my @lines; my $group = undef; open(GROUP, "<$path") or die("Unable to open '$path' for read"); @lines = ; close(GROUP); $group->{array} = (); $group->{name} = {}; $group->{gid} = {}; $group->{path} = $path; foreach my $line (@lines) { group_add_entry($group, $line); } return $group; } sub passwd_lookup_name($$) { my ($passwd, $name) = @_; return undef unless defined($passwd->{name}{$name}); return $passwd->{name}{$name}; } sub group_lookup_name($$) { my ($group, $name) = @_; return undef unless defined($group->{name}{$name}); return $group->{name}{$name}; } sub passwd_lookup_uid($$) { my ($passwd, $uid) = @_; return undef unless defined($passwd->{uid}{$uid}); return $passwd->{uid}{$uid}; } sub group_lookup_gid($$) { my ($group, $gid) = @_; return undef unless defined($group->{gid}{$gid}); return $group->{gid}{$gid}; } sub passwd_get_free_uid($) { my ($passwd) = @_; my $uid = 1000; while (passwd_lookup_uid($passwd, $uid)) { $uid++; } return $uid; } sub group_get_free_gid($) { my ($group) = @_; my $gid = 1000; while (group_lookup_gid($group, $gid)) { $gid++; } return $gid; } sub passwd_add_entry($$) { my ($passwd, $str) = @_; chomp $str; my @e = split(':', $str); push(@{$passwd->{array}}, \@e); $passwd->{name}{$e[0]} = \@e; $passwd->{uid}{$e[2]} = \@e; } sub group_add_entry($$) { my ($group, $str) = @_; chomp $str; my @e = split(':', $str); push(@{$group->{array}}, \@e); $group->{name}{$e[0]} = \@e; $group->{gid}{$e[2]} = \@e; } sub passwd_remove_entry($$) { my ($passwd, $eref) = @_; for (my $i = 0; defined($passwd->{array}[$i]); $i++) { if ($eref == $passwd->{array}[$i]) { $passwd->{array}[$i] = undef; } } delete $passwd->{name}{${$eref}[0]}; delete $passwd->{uid}{${$eref}[2]}; } sub group_remove_entry($$) { my ($group, $eref) = @_; for (my $i = 0; defined($group->{array}[$i]); $i++) { if ($eref == $group->{array}[$i]) { $group->{array}[$i] = undef; } } delete $group->{name}{${$eref}[0]}; delete $group->{gid}{${$eref}[2]}; } sub group_add_member($$$) { my ($group, $eref, $username) = @_; my @members; my $str = @$eref[3] || undef; if ($str) { @members = split(",", $str); } foreach my $member (@members) { if ($member and $member eq $username) { die("account[$username] is already member of '@$eref[0]'"); } } push(@members, $username); my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @members); group_remove_entry($group, $eref); group_add_entry($group, $gwent); } sub group_delete_member($$$) { my ($group, $eref, $username) = @_; my @members = undef; my $str = @$eref[3] || undef; if ($str) { @members = split(",", $str); } my @new_members; my $removed = 0; foreach my $member (@members) { if ($member and $member ne $username) { push(@new_members, $member); } else { $removed = 1; } } if ($removed != 1) { die("account[$username] is not member of '@$eref[0]'"); } my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @new_members); group_remove_entry($group, $eref); group_add_entry($group, $gwent); } sub passwd_save($) { my ($passwd) = @_; my @lines = (); my $path = $passwd->{path}; my $tmppath = $path.$$; foreach my $eref (@{$passwd->{array}}) { next unless defined($eref); my $line = join(':', @{$eref}); push(@lines, $line); } open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write"); print PWD join("\n", @lines)."\n"; close(PWD); rename($tmppath, $path) or die("Unable to rename $tmppath => $path"); } sub group_save($) { my ($group) = @_; my @lines = (); my $path = $group->{path}; my $tmppath = $path.$$; foreach my $eref (@{$group->{array}}) { next unless defined($eref); my $line = join(':', @{$eref}); if (scalar(@{$eref}) == 3) { $line .= ":"; } push(@lines, $line); } open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write"); print GROUP join("\n", @lines)."\n"; close(GROUP); rename($tmppath, $path) or die("Unable to rename $tmppath => $path"); } sub passwd_add($$$$$) { my ($path, $dummy, $dummy2, $name, $gid) = @_; #print "passwd_add: '$name' in '$path'\n"; my $passwd = passwd_load($path); my $e = passwd_lookup_name($passwd, $name); die("account[$name] already exists in '$path'") if defined($e); my $uid = passwd_get_free_uid($passwd); my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false"; passwd_add_entry($passwd, $pwent); passwd_save($passwd); return 0; } sub passwd_delete($$$$$) { my ($path, $dummy, $dummy2, $name, $dummy3) = @_; #print "passwd_delete: '$name' in '$path'\n"; my $passwd = passwd_load($path); my $e = passwd_lookup_name($passwd, $name); die("account[$name] does not exists in '$path'") unless defined($e); passwd_remove_entry($passwd, $e); passwd_save($passwd); return 0; } sub group_add($$$$$) { my ($dummy, $dummy2, $path, $name, $dummy3) = @_; #print "group_add: '$name' in '$path'\n"; my $group = group_load($path); my $e = group_lookup_name($group, $name); die("group[$name] already exists in '$path'") if defined($e); my $gid = group_get_free_gid($group); my $gwent = $name.":x:".$gid.":".""; group_add_entry($group, $gwent); group_save($group); #printf("%d\n", $gid); return 0; } sub group_delete($$$$$) { my ($dummy, $dummy2, $path, $name, $dummy3) = @_; #print "group_delete: '$name' in '$path'\n"; my $group = group_load($path); my $e = group_lookup_name($group, $name); die("group[$name] does not exists in '$path'") unless defined($e); group_remove_entry($group, $e); group_save($group); return 0; } sub member_add($$$$$) { my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n"; my $group = group_load($group_path); my $g = group_lookup_name($group, $groupname); die("group[$groupname] does not exists in '$group_path'") unless defined($g); my $passwd = passwd_load($passwd_path); my $u = passwd_lookup_name($passwd, $username); die("account[$username] does not exists in '$passwd_path'") unless defined($u); group_add_member($group, $g, $username); group_save($group); return 0; } sub member_delete($$$$$) { my ($passwd_path, $username, $group_path, $groupname, $dummy) = @_; #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n"; my $group = group_load($group_path); my $g = group_lookup_name($group, $groupname); die("group[$groupname] does not exists in '$group_path'") unless defined($g); my $passwd = passwd_load($passwd_path); my $u = passwd_lookup_name($passwd, $username); die("account[$username] does not exists in '$passwd_path'") unless defined($u); group_delete_member($group, $g, $username); group_save($group); return 0; } nss_wrapper-1.1.15/README.md000644 001750 000144 00000000731 13634203624 015405 0ustar00asnusers000000 000000 NSS_WRAPPER =========== This is a wrapper for the user, group and hosts NSS API. DESCRIPTION ----------- More details can be found in the manpage: man -l ./doc/nss_wrapper.1 or the raw text version: less ./doc/nss_wrapper.1.txt For installation instructions please take a look at the README.install file. MAILINGLIST ----------- As the mailing list samba-technical is used and can be found here: * https://lists.samba.org/mailman/listinfo/samba-technical nss_wrapper-1.1.15/CPackConfig.cmake000644 001750 000144 00000003366 13641347314 017251 0ustar00asnusers000000 000000 # For help take a look at: # http://www.cmake.org/Wiki/CMake:CPackConfiguration ### general settings set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The NSS wrapper library") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md") set(CPACK_PACKAGE_VENDOR "The Samba Team") set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") ### versions set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") ### source generator set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") if (WIN32) set(CPACK_GENERATOR "ZIP") ### nsis generator find_package(NSIS) if (NSIS_MAKE) set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS") set(CPACK_NSIS_DISPLAY_NAME "The SSH Library") set(CPACK_NSIS_COMPRESSOR "/SOLID zlib") set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage") endif (NSIS_MAKE) endif (WIN32) set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh") set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}) set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers") set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "Libraries used to build programs which use libssh") set(CPACK_COMPONENT_HEADERS_DESCRIPTION "C/C++ header files for use with libssh") set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) #set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime") set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") set(CPACK_COMPONENT_HEADERS_GROUP "Development") include(CPack) nss_wrapper-1.1.15/DefineOptions.cmake000644 001750 000144 00000000061 12247646107 017700 0ustar00asnusers000000 000000 option(UNIT_TESTING "Build with unit tests" OFF) nss_wrapper-1.1.15/.clangd/000750 001750 000144 00000000000 14364246777 015447 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/.clangd/index/000750 001750 000144 00000000000 14364246777 016556 5ustar00asnusers000000 000000 nss_wrapper-1.1.15/.clangd/index/test_nwrap_vector.c.6DA36926E43E358A.idx000644 001750 000144 00000005324 13622466757 025171 0ustar00asnusers000000 000000 RIFF CdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_nwrap_vector.c/usr/bin/ccCMakeFiles/test_nwrap_vector.dir/test_nwrap_vector.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/src/nss_wrapper.cfile:///home/asn/workspace/projects/nss_wrapper/tests/test_nwrap_vector.cfile:///usr/include/cmocka.hfile:///usr/include/setjmp.hmaintest_nwrap_vector_basic_addtest_nwrap_vector_mergetest_nwrap_vector_merge_emptytest_nwrap_vector_merge_maxsymbm L 95 '5 'L& :5N N#5N N#yV=J <5o o'5o o'Kò ;5% %)5% %)W{ 855refswc>@5 555005445775<<5??5EE5[[5aa5dd555;5  5''5((5PP5QQ5qq5rrY055..5225WW5]]5yy5Zkx#5555555  5"" 5//5335885@@5AA5BB5FF5GG5HH5J J5K K5XX5^^5ee5ff5gg5hh5ii5k k5l l5zz55555 5 [;45665>>5DD5cc5VF 5l63P` 555::5;;5YY5ZZ5__5``5}}53A5""5JJ5KK5kk5ll55relasrcsS3458q{Y3127646172cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_shadow.c.85DFA55943F2551B.idx000644 001750 000144 00000004472 13622466757 023750 0ustar00asnusers000000 000000 RIFF2 CdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_shadow.c/usr/bin/ccCMakeFiles/test_shadow.dir/test_shadow.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdint.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_shadow.cfile:///usr/include/cmocka.hfile:///usr/include/crypt.hfile:///usr/include/setjmp.hfile:///usr/include/shadow.hfile:///usr/include/unistd.hmaintest_nwrap_getspenttest_nwrap_getspnamsymb`wՃol =5! !5! !; <5 5 W{ ;5==5==refsmb5 <5 _z5--577NX)`U5-*-150-0457*715:-:4g`Bf5"5"5++ 555 ։3eel5 5$$ `ګ5 VF 5@@6Nȭf5 5/7>nG5((522relasrcsw4:5Z7Zף 4128693:76137829cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_nwrap_disabled.c.59E63F9B2D58E517.idx000644 001750 000144 00000005524 13622466757 025453 0ustar00asnusers000000 000000 RIFFL CdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_nwrap_disabled.c/usr/bin/ccCMakeFiles/test_nwrap_disabled.dir/test_nwrap_disabled.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_nwrap_disabled.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/grp.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/pwd.hfile:///usr/include/setjmp.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/sys/types.hfile:///usr/include/unistd.hmaintest_nwrap_getaddrinfo_localtest_nwrap_gethostnametest_nwrap_hostenttest_nwrap_passwd_groupsymbc3;e B4< <"4< <"t4 D4 #4 #qK C4& &4& &{5B A4I I(4I I(W{ @4nn4nnrefsöJ$G&,4dd8S袹4-- cr43k" 4G!'4))/gGŨ4OA_ض4CC _Ú 4O OQd P\4XX4__"JD4F Fĵ4\S 4ȉ9T4_>4[[VF 4qq G 4i!i)ߐ$#4 lC4WW4^^ gݍY4KK4LL4V!V)* Ob4N Nl:BΤӉ4kk m\܂4X]I4YY7 M̦422 3_x]4VV46MQ4//v4!!{O0 /A4ggmE4i*i0~zƚl4!!relasrcs37:861;=<?94aPsN 312;6>=598:752cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_gethostent.c.FDE119456A174D8F.idx000644 001750 000144 00000004502 13622466757 024662 0ustar00asnusers000000 000000 RIFF: CdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_gethostent.c/usr/bin/ccCMakeFiles/test_gethostent.dir/test_gethostent.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_gethostent.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/setjmp.hfile:///usr/include/stdio.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/unistd.hmaintest_nwrap_gethostentsymb@\Sc! ?4 !4 !W{ >422422refs8S袹4 G!'4 <4 4 N(og44))4**'Y?N"X4"" Z,g@w4""VF 4553n7xĐ4!44##7 M̦4// 46MQ4 4*4:w4'' 4** relasrcs34: I 31296:;=<8577619;=<8:52cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_getpwuid_module.c.13413495523E694E.idx000644 001750 000144 00000003752 13641320060 025547 0ustar00asnusers000000 000000 RIFFCdIxmeta striq-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_getpwuid_module.c/usr/bin/ccCMakeFiles/test_getpwuid_module.dir/test_getpwuid_module.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_getpwuid_module.cfile:///usr/include/cmocka.hfile:///usr/include/pwd.hfile:///usr/include/setjmp.hmaintest_nwrap_passwdsymb@R( 94 4 W{ 844refsicr4/gGŨ4!9@-V4ĵ4VUO6+4  VF 4m\܂4  relasrcsS36514* 431275672cmdl2-0/%)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_getnameinfo.c.779E41D17A149E05.idx000644 001750 000144 00000006500 13622466757 024730 0ustar00asnusers000000 000000 RIFF8 CdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_getnameinfo.c/usr/bin/ccCMakeFiles/test_getnameinfo.dir/test_getnameinfo.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_getnameinfo.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/setjmp.hfile:///usr/include/stdio.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/unistd.hmaintest_nwrap_getnameinfotest_nwrap_getnameinfo_anytest_nwrap_getnameinfo_flagstest_nwrap_getnameinfo_localtest_nwrap_getnameinfo_nulltest_nwrap_getnameinfo_numericsymb;{*` @4l l&4l l&2-ز C4 '4 '(P{G D4< <*4< <*T 7 ?4 "4 "8vx A4 (4 (Χz B4 (4 (W{ >44refs _Ú 44""4@@4PP4pp4~~444444444mLT 44..4JJ4\\4zz44444444VF 4 G 4,44J,J44z)z14+34,44,44,4_5S4!!4114OO4aa4}}44444444444(WS#44HH4xx4444* Ob4! !(41 1(4O O(4a a(4} }(4 (4 (4 (4 (4 (4 (4 (4 (4 (4 (np)({ 44224AA4bb4qq4444440Eru4 4II 4yy 4 4 4 4 F%@4,,4ZZ4444{6_d4.(.14\(\14&/4'04(14(1Ҁ4--4[[4444relasrcs3764,0\d 31296:;=<85719;=<8:52cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_getaddrinfo.c.641BB471F444137A.idx000644 001750 000144 00000013130 13622466757 024702 0ustar00asnusers000000 000000 RIFFPCdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_getaddrinfo.c/usr/bin/ccCMakeFiles/test_getaddrinfo.dir/test_getaddrinfo.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_getaddrinfo.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/errno.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/setjmp.hfile:///usr/include/stdio.hfile:///usr/include/stdlib.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/unistd.hmaintest_nwrap_getaddrinfotest_nwrap_getaddrinfo_anytest_nwrap_getaddrinfo_dottest_nwrap_getaddrinfo_flags_ai_numerichosttest_nwrap_getaddrinfo_flags_ai_numericservtest_nwrap_getaddrinfo_ipv6test_nwrap_getaddrinfo_localtest_nwrap_getaddrinfo_multiple_mixedtest_nwrap_getaddrinfo_nametest_nwrap_getaddrinfo_nulltest_nwrap_getaddrinfo_reloadtest_nwrap_getaddrinfo_sambatest_nwrap_getaddrinfo_servicesymb  D4 74 7 =@ A4 "4 "7* L4 (4 (%*C/ I4 '4 '&~Ƃ G4 (4 (eU_l C4 &4 &n})>r M4 *4 *yt5S K4_ _)4_ _)}Zg E4 74 7%  J4 '4 'xA):n H4 14 1ІO B4 &4 &[e F4 '4 'W{ @44refsa öJ$G&,4''4//"400&4CC4KK"4LL&4oo44444"4&4"4&4"4&44"443Oນ4&&4BB4nn44444 _Ú 4 4 4 4 4 4 4 4 4 Qd P\4$$4@@4ll444"44"44"44"44"44"44"444_>.4++4GG4ss4444444444444444444444444444444444444444444Z,g@w4SS 4 4 4 4 4 4 HoQp4zz lC4##422 4??4NN 4kk444 44 44 44 44 44 44 4 4 44 44 44444 G 477!4!4!4!4!4!4&.4VF 4(WS#466%4%gݍY)444"!")4>!>)4aa4bb4j!j)444!)444!)4!)444!)444!)4!)444!)444!)44444!)444%-444!)444!)ãL'f4 X]I 4%%4AA4mm4444444444l:BΤӉ4;; 4WW 4ww 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 q m!4))4EE4qq4444.5* Ob 4 4 4 4 4 4 4 4 4 np)({ 4 4 4 4 4 4 4 4 4 0Eru4&.4!)3_x]4""4>>4jj444444444444&Sw4F%@4RR'4'j-747744444{6_d4S(S14(14(14(14{O0 /A4((4444DD4PP4pp44444444444444-4}} Ҁ4'0relasrcs34+J312:67;=958861:=?>9<;527cmdl1-//)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/testsuite.c.AF64C06B860D31A7.idx000644 001750 000144 00000015172 13634217564 023450 0ustar00asnusers000000 000000 RIFFrCdIxmeta stri -DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/testsuite.c/usr/bin/ccCMakeFiles/testsuite.dir/testsuite.c.oassert_group_equalassert_passwd_equalcopy_groupcopy_passwdfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdbool.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/testsuite.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/errno.hfile:///usr/include/grp.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/pwd.hfile:///usr/include/setjmp.hfile:///usr/include/stdio.hfile:///usr/include/stdlib.hfile:///usr/include/string.hfile:///usr/include/sys/types.hfile:///usr/include/unistd.hfree_groupfree_groupsfree_passwdfree_passwdsmainprint_groupprint_passwdtest_nwrap_duplicatestest_nwrap_enum_grouptest_nwrap_enum_passwdtest_nwrap_enum_r_grouptest_nwrap_enum_r_passwdtest_nwrap_enumerationtest_nwrap_getgrgidtest_nwrap_getgrgid_rtest_nwrap_getgrnamtest_nwrap_getgrnam_rtest_nwrap_getgrouplisttest_nwrap_getpwnamtest_nwrap_getpwnam_rtest_nwrap_getpwuidtest_nwrap_getpwuid_rtest_nwrap_grouptest_nwrap_group_duplicatestest_nwrap_group_rtest_nwrap_group_r_crosstest_nwrap_membershiptest_nwrap_membership_usertest_nwrap_passwdtest_nwrap_passwd_duplicatestest_nwrap_passwd_rtest_nwrap_passwd_r_crosstest_nwrap_reentrant_enumerationtest_nwrap_reentrant_enumeration_crosscheckstest_nwrap_user_in_groupsymbd8Ay a9 !9 ! vK"y ^9 '9 ' s PD 29) )9) )r"^B H9 9 #5U5 V9 9 K _9 9 "%/r Z9 !9 !24`DH P9 "9 "?.A `9 $9 $Fciɂ T9 9 HT g9 ,9 ,Ru? ]9 9 T0tv؁+ L9 9 U6~ \9 !9 !cl5 R9 $9 $f^wd f9 %9 %m>0 d9 (9 (s=> N9 !9 !tv gl X9 #9 #u{,> c9 9 |u 49G G9G Gt Y9 9 ~*| 195 595 5>s0Z e9 9 3zp W9 !9 !8 G9 9 qVd\ [9 9 ju M9s s9s s&w! b9 &9 &DŽM h9 89 8I_FC I9] ]9] ]Ҟ?7 J9i i9i iҾc O9 !9 !swS_+A 39 9 ,Oe Q9 #9 #ITc#N S9 "9 "oԾ U9 !9 !=m  i9 $9 $W{ K99refs{921B 9<<9<"<(9 99#9%9%9#9cr9//9/"/(9LL 9LL9 9"(9YBy9--"9-(-19JJ 9JJ%9``3k" 9HxO'89 9 I.K@9II9JJ9VV9W W9XX999 = 900!90'0/9VV 9VV#9dd/gGŨ 9,, 9,&,-9II 9II!9__9$9&9&9$9")9%9$+9!(9 9 }99@-V9..9.".(9KK 9KK9#9%9%9#ĵ9du?99VUO6+9 %9"'ȉ9T9XTl9YJW922!92'2/9XX 9XX#9ff\⟇9 ޕ>+99999^0a9 9 HoQp 9999999999VF 9ߐ$# 95,519669$)99#9$9$9 9 9 9 9 9 9 9 9).9 9 9059+09 9 9059 9 9 999 9 9 9 $SG9e7ҢE9 9 9 *,19==9=(=.9>>9>(>.9? ?9??%9BB9B B&9CC 9C)C/9 99)/99 9 9#99 99999 9$*999)/9}s5|B9 %9"'9 9 999k< go91191%1+9WW 9WW9eeb">G9m\܂9)-)39**9G%G+9G9G?9]]%9i i&9s s&99?99 99 99 99*0999069,29990699992894:99pH䕴U9='ҏ9;;"9;(;19 9%9{6~,9 9 3A9&,&09pp994= yZ9i.i49kk9,299 99 99999 9999999 9999999v9si#z9~#^n{`9~zƚl 9:: 9:&:-9 9!99$9&9&9$9 9"9$+9!(relasrcs8<=@>9k»n<857A;?:;5:ADF?6EBC7cmdl2-0/%)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/test_gethostby_name_addr.c.C9C460E7372D7C61.idx000644 001750 000144 00000007516 13640404461 026446 0ustar00asnusers000000 000000 RIFFFCdIxmeta stri-DNDEBUG-D_GNU_SOURCE-I/home/asn/workspace/projects/nss_wrapper/obj-I/home/asn/workspace/projects/nss_wrapper/obj/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O2-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIE-fno-common-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj/tests/home/asn/workspace/projects/nss_wrapper/tests/test_gethostby_name_addr.c/usr/bin/ccCMakeFiles/test_gethostby_name_addr.dir/test_gethostby_name_addr.c.ofile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/workspace/projects/nss_wrapper/obj/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/test_gethostby_name_addr.cfile:///usr/include/arpa/inet.hfile:///usr/include/cmocka.hfile:///usr/include/errno.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/pthread.hfile:///usr/include/setjmp.hfile:///usr/include/stdio.hfile:///usr/include/stdlib.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/unistd.hmaintest_nwrap_gethostbyaddrtest_nwrap_gethostbyaddr_rtest_nwrap_gethostbynametest_nwrap_gethostbyname2_r_v4test_nwrap_gethostbyname2_r_v6test_nwrap_gethostbyname_multipletest_nwrap_gethostbyname_rtest_nwrap_gethostbyname_r_nulltest_nwrap_gethostbyname_threadtest_nwrap_gethostnamethread_test_gethostbynamesymbmYm C4 &4 &$kR F4 *4 *Rݩ0 G4x x-4x x-]> M K4 "4 "zHd4܊ H4 &4 &}Nk u E4 *4 *AC D4b b$4b b$K|# L45 5&45 5&G9 B4 $4 $>e? J4B B+4B B+?N9 I4 +4 +W{ A44refsڇ<4G!' 4774DD4ee4zz44444444'.44)0Nzf4?? OA_ض4""4**400e]’44TH4==4>>4KK4LL4RR4^^4ll4oo444444444444Uxt44VX5W4;;4II4jj4Y?N"X4pp 4 4 4 4 4 Z,g@w4rr4 4444*'9w_4 4'' _[Cx42:42: b,4VF 4#ԥ443n7xĐ4mm 4rr'4 4 4 4)4 4'44 4 4'4 4'44 4 4(44 4)&k b44kCn4.. oY\V4EE e輚(s4OO 3A44444= yZ44ז|04NNrelasrcs3:861;4j fi3:12;67<>=@?958>@?9=<527cmdl2-0/%)$ , "  !%'&*0#.(+nss_wrapper-1.1.15/.clangd/index/nss_wrapper.c.496306141B70693D.idx000644 001750 000144 00000125006 13641330102 023645 0ustar00asnusers000000 000000 RIFFCdIxmeta stri3(${1:__gid_t __gid})(${1:__gid_t __gid}, ${2:struct group *restrict __resultbuf}, ${3:char *restrict __buffer}, ${4:size_t __buflen}, ${5:struct group **restrict __result})(${1:__uid_t __uid})(${1:__uid_t __uid}, ${2:struct passwd *restrict __resultbuf}, ${3:char *restrict __buffer}, ${4:size_t __buflen}, ${5:struct passwd **restrict __result})(${1:char *__name}, ${2:size_t __len})(${1:const char *__name})(${1:const char *__name}, ${2:int __af})(${1:const char *__user}, ${2:__gid_t __group})(${1:const char *__user}, ${2:__gid_t __group}, ${3:__gid_t *__groups}, ${4:int *__ngroups})(${1:const char *restrict __name}, ${2:const char *restrict __service}, ${3:const struct addrinfo *restrict __req}, ${4:struct addrinfo **restrict __pai})(${1:const char *restrict __name}, ${2:int __af}, ${3:struct hostent *restrict __result_buf}, ${4:char *restrict __buf}, ${5:size_t __buflen}, ${6:struct hostent **restrict __result}, ${7:int *restrict __h_errnop})(${1:const char *restrict __name}, ${2:struct group *restrict __resultbuf}, ${3:char *restrict __buffer}, ${4:size_t __buflen}, ${5:struct group **restrict __result})(${1:const char *restrict __name}, ${2:struct hostent *restrict __result_buf}, ${3:char *restrict __buf}, ${4:size_t __buflen}, ${5:struct hostent **restrict __result}, ${6:int *restrict __h_errnop})(${1:const char *restrict __name}, ${2:struct passwd *restrict __resultbuf}, ${3:char *restrict __buffer}, ${4:size_t __buflen}, ${5:struct passwd **restrict __result})(${1:const struct sockaddr *restrict __sa}, ${2:socklen_t __salen}, ${3:char *restrict __host}, ${4:socklen_t __hostlen}, ${5:char *restrict __serv}, ${6:socklen_t __servlen}, ${7:int __flags})(${1:const void *__addr}, ${2:__socklen_t __len}, ${3:int __type})(${1:const void *restrict __addr}, ${2:__socklen_t __len}, ${3:int __type}, ${4:struct hostent *restrict __result_buf}, ${5:char *restrict __buf}, ${6:size_t __buflen}, ${7:struct hostent **restrict __result}, ${8:int *restrict __h_errnop})(${1:int __stay_open})(${1:struct group *restrict __resultbuf}, ${2:char *restrict __buffer}, ${3:size_t __buflen}, ${4:struct group **restrict __result})(${1:struct passwd *restrict __resultbuf}, ${2:char *restrict __buffer}, ${3:size_t __buflen}, ${4:struct passwd **restrict __result})()(__gid_t __gid)(__gid_t __gid, struct group *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct group **restrict __result)(__uid_t __uid)(__uid_t __uid, struct passwd *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct passwd **restrict __result)(char *__name, size_t __len)(const char *__name)(const char *__name, int __af)(const char *__user, __gid_t __group)(const char *__user, __gid_t __group, __gid_t *__groups, int *__ngroups)(const char *restrict __name, const char *restrict __service, const struct addrinfo *restrict __req, struct addrinfo **restrict __pai)(const char *restrict __name, int __af, struct hostent *restrict __result_buf, char *restrict __buf, size_t __buflen, struct hostent **restrict __result, int *restrict __h_errnop)(const char *restrict __name, struct group *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct group **restrict __result)(const char *restrict __name, struct hostent *restrict __result_buf, char *restrict __buf, size_t __buflen, struct hostent **restrict __result, int *restrict __h_errnop)(const char *restrict __name, struct passwd *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct passwd **restrict __result)(const struct sockaddr *restrict __sa, socklen_t __salen, char *restrict __host, socklen_t __hostlen, char *restrict __serv, socklen_t __servlen, int __flags)(const void *__addr, __socklen_t __len, int __type)(const void *restrict __addr, __socklen_t __len, int __type, struct hostent *restrict __result_buf, char *restrict __buf, size_t __buflen, struct hostent **restrict __result, int *restrict __h_errnop)(int __stay_open)(struct group *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct group **restrict __result)(struct passwd *restrict __resultbuf, char *restrict __buffer, size_t __buflen, struct passwd **restrict __result)-D_GNU_SOURCE-Dnss_wrapper_EXPORTS-I/home/asn/workspace/projects/nss_wrapper/obj-asan-I/home/asn/workspace/projects/nss_wrapper/obj-asan/src-I/home/asn/workspace/projects/nss_wrapper/src-O0-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIC-fno-common-fno-omit-frame-pointer-fsanitize=address-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-ggdb-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj-asan/src/home/asn/workspace/projects/nss_wrapper/src/nss_wrapper.c/usr/bin/ccCMakeFiles/nss_wrapper.dir/nss_wrapper.c.oNSS_STATUSNWRAP_LIBCNWRAP_LIBNSLNWRAP_LIBSOCKETNWRAP_LOG_DEBUGNWRAP_LOG_ERRORNWRAP_LOG_TRACENWRAP_LOG_WARN__libc_endgrent__libc_endhostent__libc_endpwent__libc_getaddrinfo__libc_getgrent__libc_getgrent_r__libc_getgrgid__libc_getgrgid_r__libc_getgrnam__libc_getgrnam_r__libc_getgrouplist__libc_gethostbyaddr__libc_gethostbyaddr_r__libc_gethostbyname__libc_gethostbyname2__libc_gethostbyname2_r__libc_gethostbyname_r__libc_gethostent__libc_gethostname__libc_getnameinfo__libc_getpwent__libc_getpwent_r__libc_getpwnam__libc_getpwnam_r__libc_getpwuid__libc_getpwuid_r__libc_initgroups__libc_setgrent__libc_sethostent__libc_setpwent__nwrap_cache_gr__nwrap_cache_he__nwrap_cache_pw__nwrap_cache_sp__nwrap_main_global_libc_endgrent_libc_endhostent_libc_endpwent_libc_getaddrinfo_libc_getgrent_libc_getgrent_r_libc_getgrgid_libc_getgrgid_r_libc_getgrnam_libc_getgrnam_r_libc_getgrouplist_libc_gethostbyaddr_libc_gethostbyaddr_r_libc_gethostbyname_libc_gethostbyname2_libc_gethostbyname2_r_libc_gethostbyname_r_libc_gethostent_libc_gethostname_libc_getnameinfo_libc_getpwent_libc_getpwent_r_libc_getpwnam_libc_getpwnam_r_libc_getpwuid_libc_getpwuid_r_libc_initgroups_libc_setgrent_libc_sethostent_libc_setpwent_nss_endgrent_nss_endpwent_nss_getgrent_r_nss_getgrgid_r_nss_getgrnam_r_nss_gethostbyaddr_r_nss_gethostbyname2_r_nss_getpwent_r_nss_getpwnam_r_nss_getpwuid_r_nss_initgroups_nss_setgrent_nss_setpwent_nwrap_bind_symboladdraliases_countbackendsc:*$@S@groupc:*$@S@hostentc:*$@S@passwdc:*$@S@spwdc:Ic:vcachecapacitycountdefault_hintsedendgrentendhostentendpwentendspententriesffdfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdarg.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdbool.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdint.hfile:///home/asn/workspace/projects/nss_wrapper/obj-asan/config.hfile:///home/asn/workspace/projects/nss_wrapper/src/nss_wrapper.cfile:///usr/include/arpa/inet.hfile:///usr/include/assert.hfile:///usr/include/ctype.hfile:///usr/include/dlfcn.hfile:///usr/include/errno.hfile:///usr/include/fcntl.hfile:///usr/include/grp.hfile:///usr/include/netdb.hfile:///usr/include/netinet/in.hfile:///usr/include/nss.hfile:///usr/include/pthread.hfile:///usr/include/pwd.hfile:///usr/include/search.hfile:///usr/include/shadow.hfile:///usr/include/stdio.hfile:///usr/include/stdlib.hfile:///usr/include/string.hfile:///usr/include/sys/socket.hfile:///usr/include/sys/stat.hfile:///usr/include/sys/types.hfile:///usr/include/unistd.hfnsfpgetaddrinfogetgrentgetgrent_rgetgrgidgetgrgid_rgetgrnamgetgrnam_rgetgrouplistgethostbyaddrgethostbyaddr_rgethostbynamegethostbyname2gethostbyname2_rgethostbyname_rgethostentgethostnamegetnameinfogetprognamegetpwentgetpwent_rgetpwnamgetpwnam_rgetpwuidgetpwuid_rgetspentgetspnamhandlehost_addrhtidxinitgroupsintitemslibclibc_endgrentlibc_endhostentlibc_endpwentlibc_getaddrinfolibc_getgrentlibc_getgrent_rlibc_getgrgidlibc_getgrgid_rlibc_getgrnamlibc_getgrnam_rlibc_getgrouplistlibc_gethostbyaddrlibc_gethostbyaddr_rlibc_gethostbynamelibc_gethostbyname2libc_gethostbyname2_rlibc_gethostbyname_rlibc_gethostentlibc_gethostnamelibc_getnameinfolibc_getpwentlibc_getpwent_rlibc_getpwnamlibc_getpwnam_rlibc_getpwuidlibc_getpwuid_rlibc_initgroupslibc_setgrentlibc_sethostentlibc_setpwentlibc_symbol_binding_mutexlineslistlistsmax_hostentsnamenextnsl_handlenss_wrapper_enablednss_wrapper_hosts_enablednss_wrapper_shadow_enablednumnum_backendsnw_endgrentnw_endpwentnw_getgrentnw_getgrent_rnw_getgrgidnw_getgrgid_rnw_getgrnamnw_getgrnam_rnw_gethostbyaddrnw_gethostbynamenw_gethostbyname2nw_gethostbyname2_rnw_getpwentnw_getpwent_rnw_getpwnamnw_getpwnam_rnw_getpwuidnw_getpwuid_rnw_initgroupsnw_setgrentnw_setpwentnwrap_add_hnamenwrap_addrdatanwrap_addrdata::nwrap_backendnwrap_backend::nwrap_backend_initnwrap_cachenwrap_cache::nwrap_constructornwrap_convert_he_ainwrap_dbglvl_enwrap_destructornwrap_ed_inventarizenwrap_ed_inventarize_add_newnwrap_ed_inventarize_add_to_existingnwrap_endgrentnwrap_endhostentnwrap_endpwentnwrap_endspentnwrap_entdatanwrap_entdata::nwrap_entlistnwrap_entlist::nwrap_entlist_initnwrap_files_cache_reloadnwrap_files_cache_unloadnwrap_files_endgrentnwrap_files_endhostentnwrap_files_endpwentnwrap_files_endspentnwrap_files_getaddrinfonwrap_files_getgrentnwrap_files_getgrent_rnwrap_files_getgrgidnwrap_files_getgrgid_rnwrap_files_getgrnamnwrap_files_getgrnam_rnwrap_files_gethostbyaddrnwrap_files_gethostbynamenwrap_files_gethostbyname2nwrap_files_gethostbyname2_rnwrap_files_gethostentnwrap_files_getpwentnwrap_files_getpwent_rnwrap_files_getpwnamnwrap_files_getpwnam_rnwrap_files_getpwuidnwrap_files_getpwuid_rnwrap_files_getspentnwrap_files_getspnamnwrap_files_initgroupsnwrap_files_internal_gethostbynamenwrap_files_opsnwrap_files_setgrentnwrap_files_sethostentnwrap_files_setpwentnwrap_files_setspentnwrap_getaddrinfonwrap_getgrentnwrap_getgrent_rnwrap_getgrgidnwrap_getgrgid_rnwrap_getgrnamnwrap_getgrnam_rnwrap_getgrouplistnwrap_gethostbyaddrnwrap_gethostbyaddr_rnwrap_gethostbynamenwrap_gethostbyname2nwrap_gethostbyname2_rnwrap_gethostbyname_rnwrap_gethostentnwrap_gethostnamenwrap_getnameinfonwrap_getpwentnwrap_getpwent_rnwrap_getpwnamnwrap_getpwnam_rnwrap_getpwuidnwrap_getpwuid_rnwrap_getspentnwrap_getspnamnwrap_global_mutexnwrap_grnwrap_gr::nwrap_gr_copy_rnwrap_gr_globalnwrap_gr_global_mutexnwrap_gr_parse_linenwrap_gr_unloadnwrap_henwrap_he::nwrap_he_globalnwrap_he_global_mutexnwrap_he_parse_linenwrap_he_unloadnwrap_hostname_enablednwrap_initnwrap_initgroupsnwrap_initializednwrap_initialized_mutexnwrap_libnwrap_libcnwrap_libc::nwrap_libc_initnwrap_libc_symbolsnwrap_libc_symbols::nwrap_libc_symbols::(anonymous union)::nwrap_lines_unloadnwrap_load_lib_handlenwrap_load_modulenwrap_load_module_fnnwrap_load_module_fnsnwrap_lognwrap_mainnwrap_main::nwrap_main_globalnwrap_module_endgrentnwrap_module_endpwentnwrap_module_getgrentnwrap_module_getgrent_rnwrap_module_getgrgidnwrap_module_getgrgid_rnwrap_module_getgrnamnwrap_module_getgrnam_rnwrap_module_gethostbyaddrnwrap_module_gethostbynamenwrap_module_gethostbyname2nwrap_module_gethostbyname2_rnwrap_module_getpwentnwrap_module_getpwent_rnwrap_module_getpwnamnwrap_module_getpwnam_rnwrap_module_getpwuidnwrap_module_getpwuid_rnwrap_module_initnwrap_module_initgroupsnwrap_module_nss_fnsnwrap_module_nss_fns::nwrap_module_opsnwrap_module_setgrentnwrap_module_setpwentnwrap_opsnwrap_ops::nwrap_parse_filenwrap_pwnwrap_pw::nwrap_pw_copy_rnwrap_pw_globalnwrap_pw_global_mutexnwrap_pw_parse_linenwrap_pw_unloadnwrap_setgrentnwrap_sethostentnwrap_setpwentnwrap_setspentnwrap_spnwrap_sp::nwrap_sp_globalnwrap_sp_global_mutexnwrap_sp_parse_linenwrap_sp_unloadnwrap_str_libnwrap_thread_childnwrap_thread_parentnwrap_thread_preparenwrap_vectornwrap_vector::nwrap_vector_add_itemnwrap_vector_initnwrap_vector_mergeobjopsparse_linepathprivate_datasetgrentsethostentsetpwentsetspentso_handleso_pathsock_handleststr_tolowerstr_tolower_copystruct group *struct hostent *struct passwd *struct spwd *symbolsunloaduser_addrlistuser_addrlist2user_heuser_he2voidsymbE׮ŬILz ##** ƫ]WueE#r4?y,  0 01y:   M( y%%'Gdi8S袹 ++r r ']jDž$h=   Z_>_ ((#((#L%bCSA""~ /%LЃ x//Q dW   v#p   ;BI   i`  ** ($Ah Ӿ!     &&$&&$ } &&  #^ 5Ϥ_ }   Sy#Ӳ   E && i쥶p +Α~GɈj5yS  m'p;ў ) )) )6y.1*gcrY% % %% %>< \A8 q_> //   ]ĵ &&mm ^f|3d  ms'y ( (( (&<@Y)   ժQh   4s剕   V     !%d.k %%$%%$09B " "" ":*Mz //J~ p''EM ((6[ v$$x`   &  &դ\ $ $( (pr   ` UsiUs\ + ++ +fYnG + +YY _BzQ  B`^ US     C ?'$   DJ[y  D;q * ** *G߻0HxO'8 && G G ^H &p\@  J&#ӼIJ J   JA. %%11Kj3j4q  L>(N    L`f  M+J#MȋLTNW/  Oh7 ,,*,,*OA_ض 00  `OܭST  Qv3   Rlne  R5yYfRC$SFV*  S[>ĖT^AМi  U-E  Uw*Uڂ қ  U   VX5W ,,$ ]VX,sVtW-,   WElarWNPEPWP7*8!!XTl &&  ^Xy[o  Y $  YbxVR% Z3 ((Zkx  ZN5TZJ9=ek  [;4   [g7\Tx ]NQZ ##]rI֌ ^/OIU ,,,,^0a ** B B \^35dT`6lU> ++"++"` } ! !" "a-{ad1 jaY * ** *b}=JESX   c^]z-  eRxU+  ! !e   eD  fY0a  ! !fwTg#ՁZ !!gB l ((g>Mg%eyV%@   iDFQC   jɑ^k ?hro     l8Wf  l63P`  ! !m֡  n #}l ""**n4  " "oz<+ p}pH䕴U ''  )^q A  qb=`q47   q)/~y   rwtQY  tT ( ,,*,,*u']^4   u z%Q   uvVLvv#y(O ' '' 'wn.wE,G  xMwr   z;x n''z 2   |䨕  ! !|Gt5`| bYY"YY"}=Gс   )  )~#^n{` ''SS ^~fͱr  $ $~:Hm  CfR  ! !oP{ ))  (\c>@h'i     NR  3k" %%ss ^9x  ZIN> ,,?   "  "b5###s  $ $8w(5n>K  ;fp   ''x%  ' '^8N  ! !aov" '' M M ^<\A-Q\   A Yu !!++E㦰L'oI.iu=   #  #z!]a45u     +r lrx^  kw ,,(,,( _   #  #ܻSlm$ ++'++'w?/Pp  d+j  |f#UٮzRue]’    ]*ĴIaw  ! !?8,)a       H ٞsM / // /Q=Wݷ,.x" Fskb׫ 00 ~((ZG/^ ##**dso3;[j  v * ,,׀x__ Vm+b  &ݒTS8  T`ekK4;^   )  )J39v   ?-  *Q ,,Wѓ 00f<N 00k(  " "g6e m  :hzy *7w'  3%t w..f ))UdE 6CxJ $ $" "& -R$$],N9ܔ  b">G ((  ! \ Z   +Ly!c ɵ7   φ눛  |~   G{6~, )) < < \ #  PՎYyXGLh:b݉5lij< . .. .H;7W {++MX>Ci'ybBٯ0 # #" "+## - k  0::j $$11dK;c & && &^)|8hSJ   "  "6,%F  QyY ,,*,,*5>   6%h.\0si#z ))  \9qx~U ,,11ƖOtm   Օ3~f##e [>mb ** A A _qEf] **"   ++-?$     E8  ʥ  ʿRˮ"{ t!!˲~fNF ,,̆E;G ))gLxU   ͋x?  " "t-@Y0 $$my/Y~ 3   -  -ѝok<   #!E@ |  HgUe " "! !ֶLfR  du? **   \u E     ȉ9T ((dd \&zzFB ,,00׳qGԝ 00؇$ + ++ +أx/B ,,),,)@   `ګ ++ I I _j^_weqL - -  p ++"++"یֹrP $ $! !(<E   ܦ&Q ))(TWi9?* 0 00 0Vh# **ݡ &ݦ{%  " "$_   ߡS6Gߙ(ev efZ^ ' '' 'oeWa   z2`}  cu5̦  t    4 %%22(߷!dU ! !" "_5S 00  $])01k X  - -Yܛg>i   *  *6?4(     蒐~-|5Z  ꒺fCM ++.:""iƁs  ۑˆ$ɭ7% dw#K_z:%P ,,7 M̦ ++x x ]VEs({)  vUhz~;? " "" "Mdd   X?Q   #  #h?  nz@ ) )) )򚰅gRp:  " "̤/##WQ] ))3! ,,+,,+,՞*j   9x譗   "  "KcE   ~  ( (Ekm[@ **~ϰR$ E o ]Ys) # #! !gev ((jj \ h: ,,,,lگ  b#  혩 ,,% ]Har@refss/8S袹++ !f %ľS?3Oນ -- ----%- -----. ..".-/// ///!/ /cr -3  =  -5 o2&%.. }&& RKaM8<(,(,g`Bf .5%,$N(og  ! $ ؀-.. ID$bĵ&&z _>//Ӝ  ޕ>+ % , ""####$$%%%%**! b,  !vo=11 11 11 11 !b\`X  #ԥ  $SG))&k b)OqD00*$|/----#+b}}.lvy5!!!!!!!!!!""!""""!""##!####!$$$$!$$%%!%%!0Eru- -//3A,0****111146MQ++4= yZ         .4                               ( .                   !!!!"" ""##$$ $$$$%%%%%%%%&&&&&&&&&&&&&&'''' ''''''''(((((((((((((()))))))) ))))**,,,,,,//////0)0/00"006Nȭf+ +4 ˊ  6?        3 < & /$$,,, ,-- /8/A// 0+0400005C}DW  3_x].4  -- -- -- :.29. .:w  <Ƭ;eS!_7Y Y?G$F<>nG+ +B6|A// G!'V    ,3              $+                  $$$$$ $$ $%%%%%%%%++++,,,,,,,,,,,,,,,,,,,,,,,,,,-,-3//HxO'8&& I.K@  --// L%NX)`U OA_ض00Qd P\ -- ----%- ---- ---/ //// ///!/ /QF  TH +1  4 :- -- -&030900000%0+TUVUO6+*/!&$       $ )    ! !!! &%&*&&&&!&&VX5W,,XBWl~!!"! !!!!!"!!""""""""""##"####"$$$$"$$%%"%%"XTl&&Z,g@w  00\⟇ & ,$ ""####$$%%%%**--/ /^0a** _[Cx   + 3----adV(YJW -5"* e7ҢE   **gݍY      ,,---------.-6....... .. ./ // //!/)/(/0/// /Y?N"X   ''  - -----(- -k< go +1 l:BΤӉ--//m\܂d    (. 8>17&,%'-'- "%'-'- "# &(.(.           " ( (.<B'-%'-'- "  !!! !&!(!.!!!!!!!(!.!!!!""""#%%%%%% %5%;%(%.&(&.&)&/&&&&&& &.&4&(&.&!&'&)&/&&'''' '#')''#''''$np)({--'- --%-1////(oAb|0 0pH䕴U''pŰ{^y  sD k tZߴh  uTǙ̒--/ /s o|ems[v  xMڇ{6_d--////#{O0 /A-- -- -- ----~zƚl ,3")  "  %,$* ** *$oNkk${))ڇ<,, ꡛm8''21B  +1$* $#****#Θp8 !!!!"""""""##"####"$$$$"$$%%"%%"3k" %%mR-- --u+d%^O'' ~C311 11 11 11 /gGŨ  .5 %,$ S  Ӿ@U 11 8000*00e]’EfcK  !QH  **-- -- // HoQp  !"  $  $ %%%% 00lC (-- --... . G --////!}s5|B438).!&  16$       - 2 # (        (-"  """"## ## '.'3'!'&($()((((!))*0*5* ******-*2***C*H*+*0*#*(*0*5zdK !uFho..7Qt/" "b">G(((WS#- -J^~6 ='ҏ09$- &{6~,)) N47y1%0 05Q. ./ // /䇲(3   "ʿ$- 00 00 0000 "*  ~#^n{`''öJ$G&,------- -/// /// 9YBy2;\ c|$si#z))mb** . .BeX    减 ɞi  _Ú --&- --$-/////'JD "#     00 00 00 9@-V +1 $#Ђ X, du?**ȉ9T((։3eel    ++++ ++++ ׂԻz----00 `ګ++ X] // /"/-ۅ׾    fr2p`tn|`                  ްH'_mLT ....ߐ$#f    (- 8=16&+ $', ',  !$',', !" %(-(-            " '  (-;@', $', ',   ! """"" "%"("-#######(#-####$$$$"(((( (( (5(:(((-(((-()(.(((( (( (.(3(((-)!)&))).)))) )) )#)())"))))#** 3n7xĐ   "----*,1   !   %  ! ! & *** *&** _5S00G4za\. .DssT*X]I-- -- --. .....* Ob/7 ) 1- -- -/*/2////00%h6=..7 M̦++q m! -- -- /5/</ // ///$/ /N&A$[". .F%@- -  v((4@-. u. .//Ҁ- -//혩,,relasrcsz+iIcmdl4Y2[*+-.,TU/POM3X0GA15I;K=4E826F9J<@:HD>?7NRQBCVaLZSWnss_wrapper-1.1.15/.clangd/index/nss_nwrap.c.6CD8D6240BEF45A7.idx000644 001750 000144 00000006466 13641330102 023446 0ustar00asnusers000000 000000 RIFF. CdIxmeta stri-D_GNU_SOURCE-Dnss_nwrap_EXPORTS-I/home/asn/workspace/projects/nss_wrapper/obj-asan-I/home/asn/workspace/projects/nss_wrapper/obj-asan/tests-I/home/asn/workspace/projects/nss_wrapper/tests-O0-Wall-Wcast-align-Wdeclaration-after-statement-Werror-Werror-implicit-function-declaration-Werror=address-Werror=declaration-after-statement-Werror=format-security-Werror=pointer-arith-Werror=return-type-Werror=strict-overflow-Werror=strict-prototypes-Werror=uninitialized-Werror=write-strings-Wformat-Wformat-security-Wimplicit-fallthrough-Wmissing-prototypes-Wno-error=deprecated-declarations-Wno-error=tautological-compare-Wno-format-zero-length-Wpointer-arith-Wreturn-type-Wshadow-Wstrict-overflow=2-Wstrict-prototypes-Wuninitialized-Wwrite-strings-c-fPIC-fno-common-fno-omit-frame-pointer-fsanitize=address-fstack-clash-protection-fstack-protector-strong-fsyntax-only-g-ggdb-o-resource-dir=/home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0-std=gnu99/home/asn/workspace/projects/nss_wrapper/obj-asan/tests/home/asn/workspace/projects/nss_wrapper/tests/nss_nwrap.c/usr/bin/ccCMakeFiles/nss_nwrap.dir/nss_nwrap.c.oNSS_STATUS_nss_nwrap_endgrent_nss_nwrap_endpwent_nss_nwrap_getgrent_r_nss_nwrap_getgrgid_r_nss_nwrap_getgrnam_r_nss_nwrap_getpwent_r_nss_nwrap_getpwnam_r_nss_nwrap_getpwuid_r_nss_nwrap_initgroups_dyn_nss_nwrap_setgrent_nss_nwrap_setpwentfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stddef.hfile:///home/asn/.cache/dein/.cache/init.vim/.dein/third_party/ycmd/third_party/clang/lib/clang/9.0.0/include/stdint.hfile:///home/asn/workspace/projects/nss_wrapper/obj-asan/config.hfile:///home/asn/workspace/projects/nss_wrapper/tests/nss_nwrap.cfile:///usr/include/errno.hfile:///usr/include/fcntl.hfile:///usr/include/grp.hfile:///usr/include/nss.hfile:///usr/include/pwd.hfile:///usr/include/string.hpw_copy_rsymb B%؎S ?Co oC  ]Hi? 4C"C"1v4d% ;C  C% % 2C C' 'refscrCSS CSSC 9YByCPPCQQC = CaaCbbC /gGŨCAACNNCOO C QF C??CH H9@-VCRR CRRC VUO6+C#!#&C!&YJWCC CCeeCffC !QHCLLߐ$#C)()-C+:+?C-3-8C(-C:?C387Qt/ CqqCvvCCCCCCCCC}s5|BC-!-&C/1/6C00C!&C16Ck< goCccCdd C m\܂ C!(!.C#3#9C%:%@C7"7(C88C;;Cy(y.C39CC:@.lvy5C 3_x]C4= yZ C"" C$$C&&C** C,,C.. C:: Czz CCC CC ;eS!_7C $oNC44$relasrcswBEFIHC 46 BDE@AIHFGAG@Dcmdl4022+,'&$ / "  !%)(-3#1*.nss_wrapper-1.1.15/AUTHORS000644 001750 000144 00000000250 13634203624 015172 0ustar00asnusers000000 000000 Stefan Metzmacher Guenther Deschner Andreas Schneider Robin Hack Michael Adam nss_wrapper-1.1.15/nss_wrapper.pc.cmake000644 001750 000144 00000000211 13634217552 020072 0ustar00asnusers000000 000000 Name: @PROJECT_NAME@ Description: The nss_wrapper library Version: @PROJECT_VERSION@ Libs: @CMAKE_INSTALL_FULL_LIBDIR@/@NSS_WRAPPER_LIB@ nss_wrapper-1.1.15/LICENSE000644 001750 000144 00000003330 13634203624 015131 0ustar00asnusers000000 000000 BSD 3-Clause License Copyright (c) 2007, Stefan Metzmacher Copyright (c) 2009, Guenther Deschner Copyright (c) 2014-2015, Michael Adam Copyright (c) 2015, Robin Hack Copyright (c) 2013-2018, Andreas Schneider All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nss_wrapper-1.1.15/nss_wrapper-config-version.cmake.in000644 001750 000144 00000003300 14364206715 023026 0ustar00asnusers000000 000000 set(PACKAGE_VERSION @PROJECT_VERSION@) if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() if(${PACKAGE_VERSION} MATCHES "^([0-9]+)\\.") set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") endif() else() set(CVF_VERSION_MAJOR ${PACKAGE_VERSION}) endif() if(PACKAGE_FIND_VERSION_RANGE) # both endpoints of the range must have the expected major version math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) set(PACKAGE_VERSION_COMPATIBLE FALSE) elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() else() if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() endif()