diff options
author | Andreas Schneider <asn@samba.org> | 2014-01-31 15:57:43 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2014-04-17 14:56:06 +0200 |
commit | 5bb410f85312196bb24e62a6a0b8350576433dc6 (patch) | |
tree | c66efb80d8f91867f0404a96202dca89b4dacd56 | |
parent | b2163f23c09128ad0d2765a1a4c9a993500b588f (diff) | |
download | samba-5bb410f85312196bb24e62a6a0b8350576433dc6.tar.gz samba-5bb410f85312196bb24e62a6a0b8350576433dc6.tar.xz samba-5bb410f85312196bb24e62a6a0b8350576433dc6.zip |
lib: Change nss_wrapper to preloadable version.
This imports nss_wrapper version 1.0.2.
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rwxr-xr-x | configure.developer | 1 | ||||
-rw-r--r-- | lib/nss_wrapper/nss_wrapper.c | 2744 | ||||
-rw-r--r-- | lib/nss_wrapper/nss_wrapper.h | 171 | ||||
-rw-r--r-- | lib/nss_wrapper/testsuite.c | 958 | ||||
-rw-r--r-- | lib/nss_wrapper/wscript | 111 | ||||
-rw-r--r-- | lib/nss_wrapper/wscript_build | 10 | ||||
-rw-r--r-- | wscript | 1 |
7 files changed, 2460 insertions, 1536 deletions
diff --git a/configure.developer b/configure.developer index 50336702095..b8cf6d68b10 100755 --- a/configure.developer +++ b/configure.developer @@ -2,5 +2,4 @@ `dirname $0`/configure -C \ --enable-developer \ --enable-socket-wrapper \ - --enable-nss-wrapper \ "$@" diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c index 8767fbfd892..7c5a413ee78 100644 --- a/lib/nss_wrapper/nss_wrapper.c +++ b/lib/nss_wrapper/nss_wrapper.c @@ -1,6 +1,7 @@ /* * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org> * Copyright (C) Guenther Deschner 2009 <gd@samba.org> + * Copyright (C) Andreas Schneider 2013 <asn@samba.org> * * All rights reserved. * @@ -32,120 +33,229 @@ * SUCH DAMAGE. */ -#ifdef _SAMBA_BUILD_ +#include "config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> -/* defining this gives us the posix getpwnam_r() calls on solaris - Thanks to heimdal for this */ +/* + * 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 -#define NSS_WRAPPER_NOT_REPLACE -#include "../replace/replace.h" -#include "system/passwd.h" -#include "system/filesys.h" -#include "../nsswitch/nsstest.h" +#include <pwd.h> +#include <grp.h> + +#include <netdb.h> +#include <arpa/inet.h> +#include <netinet/in.h> + +#include <dlfcn.h> -#else /* _SAMBA_BUILD_ */ +#if defined(HAVE_NSS_H) +/* Linux and BSD */ +#include <nss.h> -#error nss_wrapper_only_supported_in_samba_yet +typedef enum nss_status NSS_STATUS; +#elif defined(HAVE_NSS_COMMON_H) +/* Solaris */ +#include <nss_common.h> +#include <nss_dbdefs.h> +#include <nsswitch.h> + +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 -/* not all systems have _r functions... */ -#ifndef HAVE_GETPWNAM_R -#define getpwnam_r(name, pwdst, buf, buflen, pwdstp) ENOSYS -#endif -#ifndef HAVE_GETPWUID_R -#define getpwuid_r(uid, pwdst, buf, buflen, pwdstp) ENOSYS +#ifndef EAI_NODATA +#define EAI_NODATA EAI_NONAME #endif -#ifndef HAVE_GETPWENT_R -#define getpwent_r(pwdst, buf, buflen, pwdstp) ENOSYS + +#ifndef EAI_ADDRFAMILY +#define EAI_ADDRFAMILY EAI_FAMILY #endif -#ifndef HAVE_GETGRNAM_R -#define getgrnam_r(name, grdst, buf, buflen, grdstp) ENOSYS + +#ifndef __STRING +#define __STRING(x) #x #endif -#ifndef HAVE_GETGRGID_R -#define getgrgid_r(gid, grdst, buf, buflen, grdstp) ENOSYS + +#ifndef __STRINGSTRING +#define __STRINGSTRING(x) __STRING(x) #endif -#ifndef HAVE_GETGRENT_R -#define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS + +#ifndef __LINESTR__ +#define __LINESTR__ __STRINGSTRING(__LINE__) #endif -/* not all systems have getgrouplist */ -#ifndef HAVE_GETGROUPLIST -#define getgrouplist(user, group, groups, ngroups) 0 +#ifndef __location__ +#define __location__ __FILE__ ":" __LINESTR__ #endif -/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support - * for now */ -#define REWRITE_CALLS +/* 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 REWRITE_CALLS +#ifdef HAVE_DESTRUCTOR_ATTRIBUTE +#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) +#else +#define DESTRUCTOR_ATTRIBUTE +#endif /* HAVE_DESTRUCTOR_ATTRIBUTE */ -#define real_getpwnam getpwnam -#define real_getpwnam_r getpwnam_r -#define real_getpwuid getpwuid -#define real_getpwuid_r getpwuid_r +#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) -#define real_setpwent setpwent -#define real_getpwent getpwent -#define real_getpwent_r getpwent_r -#define real_endpwent endpwent +enum nwrap_dbglvl_e { + NWRAP_LOG_ERROR = 0, + NWRAP_LOG_WARN, + NWRAP_LOG_DEBUG, + NWRAP_LOG_TRACE +}; -/* -#define real_getgrlst getgrlst -#define real_getgrlst_r getgrlst_r -#define real_initgroups_dyn initgroups_dyn -*/ -#define real_initgroups initgroups -#define real_getgrouplist getgrouplist - -#define real_getgrnam getgrnam -#define real_getgrnam_r getgrnam_r -#define real_getgrgid getgrgid -#define real_getgrgid_r getgrgid_r - -#define real_setgrent setgrent -#define real_getgrent getgrent -#define real_getgrent_r getgrent_r -#define real_endgrent endgrent +#ifdef NDEBUG +# define NWRAP_LOG(...) +#else -#endif +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__) -#if 0 -# ifdef DEBUG -# define NWRAP_ERROR(args) DEBUG(0, args) -# else -# define NWRAP_ERROR(args) printf args -# endif +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; + int pid = getpid(); + + d = getenv("NSS_WRAPPER_DEBUGLEVEL"); + if (d != NULL) { + lvl = atoi(d); + } + + va_start(va, format); + vsnprintf(buffer, sizeof(buffer), format, va); + va_end(va); + + if (lvl >= dbglvl) { + switch (dbglvl) { + case NWRAP_LOG_ERROR: + fprintf(stderr, + "NWRAP_ERROR(%d) - %s: %s\n", + pid, func, buffer); + break; + case NWRAP_LOG_WARN: + fprintf(stderr, + "NWRAP_WARN(%d) - %s: %s\n", + pid, func, buffer); + break; + case NWRAP_LOG_DEBUG: + fprintf(stderr, + "NWRAP_DEBUG(%d) - %s: %s\n", + pid, func, buffer); + break; + case NWRAP_LOG_TRACE: + fprintf(stderr, + "NWRAP_TRACE(%d) - %s: %s\n", + pid, func, buffer); + break; + } + } +} +#endif /* NDEBUG NWRAP_LOG */ + +struct nwrap_libc_fns { + struct passwd *(*_libc_getpwnam)(const char *name); + int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd, + char *buf, size_t buflen, struct passwd **result); + struct passwd *(*_libc_getpwuid)(uid_t uid); + int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); + void (*_libc_setpwent)(void); + struct passwd *(*_libc_getpwent)(void); +#ifdef HAVE_SOLARIS_GETPWENT_R + struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen); #else -#define NWRAP_ERROR(args) + int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); #endif - -#if 0 -# ifdef DEBUG -# define NWRAP_DEBUG(args) DEBUG(0, args) -# else -# define NWRAP_DEBUG(args) printf args -# endif + void (*_libc_endpwent)(void); + int (*_libc_initgroups)(const char *user, gid_t gid); + struct group *(*_libc_getgrnam)(const char *name); + int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result); + struct group *(*_libc_getgrgid)(gid_t gid); + int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result); + void (*_libc_setgrent)(void); + struct group *(*_libc_getgrent)(void); +#ifdef HAVE_SOLARIS_GETGRENT_R + struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen); #else -#define NWRAP_DEBUG(args) + int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result); #endif + void (*_libc_endgrent)(void); + int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups); -#if 0 -# ifdef DEBUG -# define NWRAP_VERBOSE(args) DEBUG(0, args) -# else -# define NWRAP_VERBOSE(args) printf args -# endif -#else -#define NWRAP_VERBOSE(args) + void (*_libc_sethostent)(int stayopen); + struct hostent *(*_libc_gethostent)(void); + void (*_libc_endhostent)(void); + + struct hostent *(*_libc_gethostbyname)(const char *name); +#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ + struct hostent *(*_libc_gethostbyname2)(const char *name, int af); +#endif + struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type); + + int (*_libc_getaddrinfo)(const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res); + int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags); + int (*_libc_gethostname)(char *name, size_t len); +#ifdef HAVE_GETHOSTBYNAME_R + 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 + 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 +}; struct nwrap_module_nss_fns { NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer, @@ -213,6 +323,11 @@ struct nwrap_ops { void (*nw_endgrent)(struct nwrap_backend *b); }; +/* Public prototypes */ + +bool nss_wrapper_enabled(void); +bool nss_wrapper_hosts_enabled(void); + /* prototypes for files backend */ @@ -328,10 +443,18 @@ struct nwrap_ops nwrap_module_ops = { .nw_endgrent = nwrap_module_endgrent, }; +struct nwrap_libc { + void *handle; + void *nsl_handle; + void *sock_handle; + struct nwrap_libc_fns *fns; +}; + struct nwrap_main { const char *nwrap_switch; int num_backends; struct nwrap_backend *backends; + struct nwrap_libc *libc; }; struct nwrap_main *nwrap_main_global; @@ -372,8 +495,550 @@ struct nwrap_gr { struct nwrap_cache __nwrap_cache_gr; struct nwrap_gr nwrap_gr_global; +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 */ + char *h_addr_ptrs[2]; /* host_addr pointer + NULL */ +}; + +struct nwrap_entdata { + struct nwrap_addrdata *addr; + struct hostent ht; +}; + +struct nwrap_he { + struct nwrap_cache *cache; + + struct nwrap_entdata *list; + int num; + int idx; +}; + +struct nwrap_cache __nwrap_cache_he; +struct nwrap_he nwrap_he_global; + + +/********************************************************* + * NWRAP PROTOTYPES + *********************************************************/ + +static void nwrap_init(void); static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line); static void nwrap_gr_unload(struct nwrap_cache *nwrap); +void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE; + +/********************************************************* + * NWRAP LIBC LOADER FUNCTIONS + *********************************************************/ + +enum nwrap_lib { + NWRAP_LIBC, + NWRAP_LIBNSL, + NWRAP_LIBSOCKET, +}; + +#ifndef NDEBUG +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"; +} +#endif + +static void *nwrap_load_lib_handle(enum nwrap_lib lib) +{ + int flags = RTLD_LAZY; + void *handle = NULL; + int i; + +#ifdef HAVE_APPLE + return RTLD_NEXT; +#endif + +#ifdef RTLD_DEEPBIND + flags |= RTLD_DEEPBIND; +#endif + + switch (lib) { + case NWRAP_LIBNSL: +#ifdef HAVE_LIBNSL + handle = nwrap_main_global->libc->nsl_handle; + if (handle == NULL) { + for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) { + char soname[256] = {0}; + + snprintf(soname, sizeof(soname), "libnsl.so.%d", i); + handle = dlopen(soname, flags); + } + + 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 (handle = NULL, i = 10; handle == NULL && i >= 0; i--) { + char soname[256] = {0}; + + snprintf(soname, sizeof(soname), "libsocket.so.%d", i); + handle = dlopen(soname, flags); + } + + nwrap_main_global->libc->sock_handle = handle; + } + break; +#endif + /* FALL TROUGH */ + case NWRAP_LIBC: + handle = nwrap_main_global->libc->handle; + if (handle == NULL) { + for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) { + char soname[256] = {0}; + + snprintf(soname, sizeof(soname), "libc.so.%d", i); + handle = dlopen(soname, flags); + } + + nwrap_main_global->libc->handle = handle; + } + break; + } + + if (handle == NULL) { + NWRAP_LOG(NWRAP_LOG_ERROR, + "Failed to dlopen library: %s\n", + dlerror()); + exit(-1); + } + + return handle; +} + +static void *_nwrap_load_lib_function(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_load_lib_function(lib, fn_name) \ + if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \ + *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \ + _nwrap_load_lib_function(lib, #fn_name); \ + } + +/* + * 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_load_lib_function(NWRAP_LIBC, getpwnam); + + return nwrap_main_global->libc->fns->_libc_getpwnam(name); +} + +#ifdef HAVE_GETPWNAM_R +static int libc_getpwnam_r(const char *name, + struct passwd *pwd, + char *buf, + size_t buflen, + struct passwd **result) +{ +#ifdef HAVE___POSIX_GETPWNAM_R + if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) { + *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) = + _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r"); + } +#else + nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r); +#endif + + return nwrap_main_global->libc->fns->_libc_getpwnam_r(name, + pwd, + buf, + buflen, + result); +} +#endif + +static struct passwd *libc_getpwuid(uid_t uid) +{ + nwrap_load_lib_function(NWRAP_LIBC, getpwuid); + + return nwrap_main_global->libc->fns->_libc_getpwuid(uid); +} + +#ifdef HAVE_GETPWUID_R +static int libc_getpwuid_r(uid_t uid, + struct passwd *pwd, + char *buf, + size_t buflen, + struct passwd **result) +{ +#ifdef HAVE___POSIX_GETPWUID_R + if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) { + *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) = + _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r"); + } +#else + nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r); +#endif + + return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid, + pwd, + buf, + buflen, + result); +} +#endif + +static void libc_setpwent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, setpwent); + + nwrap_main_global->libc->fns->_libc_setpwent(); +} + +static struct passwd *libc_getpwent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, getpwent); + + return nwrap_main_global->libc->fns->_libc_getpwent(); +} + +#ifdef HAVE_SOLARIS_GETPWENT_R +static struct passwd *libc_getpwent_r(struct passwd *pwdst, + char *buf, + int buflen) +{ + nwrap_load_lib_function(NWRAP_LIBC, getpwent_r); + + return nwrap_main_global->libc->fns->_libc_getpwent_r(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_load_lib_function(NWRAP_LIBC, getpwent_r); + + return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst, + buf, + buflen, + pwdstp); +} +#endif /* HAVE_SOLARIS_GETPWENT_R */ + +static void libc_endpwent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, endpwent); + + nwrap_main_global->libc->fns->_libc_endpwent(); +} + +static int libc_initgroups(const char *user, gid_t gid) +{ + nwrap_load_lib_function(NWRAP_LIBC, initgroups); + + return nwrap_main_global->libc->fns->_libc_initgroups(user, gid); +} + +static struct group *libc_getgrnam(const char *name) +{ + nwrap_load_lib_function(NWRAP_LIBC, getgrnam); + + return nwrap_main_global->libc->fns->_libc_getgrnam(name); +} + +#ifdef HAVE_GETGRNAM_R +static int libc_getgrnam_r(const char *name, + struct group *grp, + char *buf, + size_t buflen, + struct group **result) +{ +#ifdef HAVE___POSIX_GETGRNAM_R + if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) { + *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) = + _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r"); + } +#else + nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r); +#endif + + return nwrap_main_global->libc->fns->_libc_getgrnam_r(name, + grp, + buf, + buflen, + result); +} +#endif + +static struct group *libc_getgrgid(gid_t gid) +{ + nwrap_load_lib_function(NWRAP_LIBC, getgrgid); + + return nwrap_main_global->libc->fns->_libc_getgrgid(gid); +} + +#ifdef HAVE_GETGRGID_R +static int libc_getgrgid_r(gid_t gid, + struct group *grp, + char *buf, + size_t buflen, + struct group **result) +{ +#ifdef HAVE___POSIX_GETGRGID_R + if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) { + *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) = + _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r"); + } +#else + nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r); +#endif + + return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid, + grp, + buf, + buflen, + result); +} +#endif + +static void libc_setgrent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, setgrent); + + nwrap_main_global->libc->fns->_libc_setgrent(); +} + +static struct group *libc_getgrent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, getgrent); + + return nwrap_main_global->libc->fns->_libc_getgrent(); +} + +#ifdef HAVE_GETGRENT_R +#ifdef HAVE_SOLARIS_GETGRENT_R +static struct group *libc_getgrent_r(struct group *group, + char *buf, + size_t buflen) +{ + nwrap_load_lib_function(NWRAP_LIBC, getgrent_r); + + return nwrap_main_global->libc->fns->_libc_getgrent_r(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_load_lib_function(NWRAP_LIBC, getgrent_r); + + return nwrap_main_global->libc->fns->_libc_getgrent_r(group, + buf, + buflen, + result); +} +#endif /* HAVE_SOLARIS_GETGRENT_R */ +#endif /* HAVE_GETGRENT_R */ + +static void libc_endgrent(void) +{ + nwrap_load_lib_function(NWRAP_LIBC, endgrent); + + nwrap_main_global->libc->fns->_libc_endgrent(); +} + +#ifdef HAVE_GETGROUPLIST +static int libc_getgrouplist(const char *user, + gid_t group, + gid_t *groups, + int *ngroups) +{ + nwrap_load_lib_function(NWRAP_LIBC, getgrouplist); + + return nwrap_main_global->libc->fns->_libc_getgrouplist(user, + group, + groups, + ngroups); +} +#endif + +static void libc_sethostent(int stayopen) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, sethostent); + + nwrap_main_global->libc->fns->_libc_sethostent(stayopen); +} + +static struct hostent *libc_gethostent(void) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostent); + + return nwrap_main_global->libc->fns->_libc_gethostent(); +} + +static void libc_endhostent(void) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, endhostent); + + nwrap_main_global->libc->fns->_libc_endhostent(); +} + +static struct hostent *libc_gethostbyname(const char *name) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname); + + return nwrap_main_global->libc->fns->_libc_gethostbyname(name); +} + +#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ +static struct hostent *libc_gethostbyname2(const char *name, int af) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2); + + return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af); +} +#endif + +static struct hostent *libc_gethostbyaddr(const void *addr, + socklen_t len, + int type) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr); + + return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr, + len, + type); +} + +static int libc_gethostname(char *name, size_t len) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostname); + + return nwrap_main_global->libc->fns->_libc_gethostname(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_load_lib_function(NWRAP_LIBNSL, gethostbyname_r); + + return nwrap_main_global->libc->fns->_libc_gethostbyname_r(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_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r); + + return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(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_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo); + + return nwrap_main_global->libc->fns->_libc_getaddrinfo(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_load_lib_function(NWRAP_LIBSOCKET, getnameinfo); + + return nwrap_main_global->libc->fns->_libc_getnameinfo(sa, + salen, + host, + hostlen, + serv, + servlen, + flags); +} + +/********************************************************* + * NWRAP NSS MODULE LOADER FUNCTIONS + *********************************************************/ static void *nwrap_load_module_fn(struct nwrap_backend *b, const char *fn_name) @@ -382,21 +1047,20 @@ static void *nwrap_load_module_fn(struct nwrap_backend *b, char *s; if (!b->so_handle) { - NWRAP_ERROR(("%s: no handle\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "No handle"); return NULL; } if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) { - NWRAP_ERROR(("%s: out of memory\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return NULL; } res = dlsym(b->so_handle, s); if (!res) { - NWRAP_ERROR(("%s: cannot find function %s in %s\n", - __location__, s, b->so_path)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Cannot find function %s in %s", + s, b->so_path); } free(s); s = NULL; @@ -416,28 +1080,28 @@ static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend * return NULL; } - fns->_nss_getpwnam_r = (NSS_STATUS (*)(const char *, struct passwd *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getpwnam_r"); - fns->_nss_getpwuid_r = (NSS_STATUS (*)(uid_t, struct passwd *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getpwuid_r"); - fns->_nss_setpwent = (NSS_STATUS(*)(void)) - nwrap_load_module_fn(b, "setpwent"); - fns->_nss_getpwent_r = (NSS_STATUS (*)(struct passwd *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getpwent_r"); - fns->_nss_endpwent = (NSS_STATUS(*)(void)) - nwrap_load_module_fn(b, "endpwent"); - fns->_nss_initgroups = (NSS_STATUS (*)(const char *, gid_t, long int *, long int *, gid_t **, long int, int *)) - nwrap_load_module_fn(b, "initgroups_dyn"); - fns->_nss_getgrnam_r = (NSS_STATUS (*)(const char *, struct group *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getgrnam_r"); - fns->_nss_getgrgid_r = (NSS_STATUS (*)(gid_t, struct group *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getgrgid_r"); - fns->_nss_setgrent = (NSS_STATUS(*)(void)) - nwrap_load_module_fn(b, "setgrent"); - fns->_nss_getgrent_r = (NSS_STATUS (*)(struct group *, char *, size_t, int *)) - nwrap_load_module_fn(b, "getgrent_r"); - fns->_nss_endgrent = (NSS_STATUS(*)(void)) - nwrap_load_module_fn(b, "endgrent"); + *(void **)(&fns->_nss_getpwnam_r) = + nwrap_load_module_fn(b, "getpwnam_r"); + *(void **)(&fns->_nss_getpwuid_r) = + nwrap_load_module_fn(b, "getpwuid_r"); + *(void **)(&fns->_nss_setpwent) = + nwrap_load_module_fn(b, "setpwent"); + *(void **)(&fns->_nss_getpwent_r) = + nwrap_load_module_fn(b, "getpwent_r"); + *(void **)(&fns->_nss_endpwent) = + nwrap_load_module_fn(b, "endpwent"); + *(void **)(&fns->_nss_initgroups) = + nwrap_load_module_fn(b, "initgroups_dyn"); + *(void **)(&fns->_nss_getgrnam_r) = + nwrap_load_module_fn(b, "getgrnam_r"); + *(void **)(&fns->_nss_getgrgid_r)= + nwrap_load_module_fn(b, "getgrgid_r"); + *(void **)(&fns->_nss_setgrent) = + nwrap_load_module_fn(b, "setgrent"); + *(void **)(&fns->_nss_getgrent_r) = + nwrap_load_module_fn(b, "getgrent_r"); + *(void **)(&fns->_nss_endgrent) = + nwrap_load_module_fn(b, "endgrent"); return fns; } @@ -452,8 +1116,9 @@ static void *nwrap_load_module(const char *so_path) h = dlopen(so_path, RTLD_LAZY); if (!h) { - NWRAP_ERROR(("%s: cannot open shared library %s\n", - __location__, so_path)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Cannot open shared library %s", + so_path); return NULL; } @@ -471,8 +1136,7 @@ static bool nwrap_module_init(const char *name, *backends = (struct nwrap_backend *)realloc(*backends, sizeof(struct nwrap_backend) * ((*num_backends) + 1)); if (!*backends) { - NWRAP_ERROR(("%s: out of memory\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } @@ -498,9 +1162,27 @@ static bool nwrap_module_init(const char *name, return true; } +static void nwrap_libc_init(struct nwrap_main *r) +{ + r->libc = malloc(sizeof(struct nwrap_libc)); + if (r->libc == NULL) { + printf("Failed to allocate memory for libc"); + exit(-1); + } + ZERO_STRUCTP(r->libc); + + r->libc->fns = malloc(sizeof(struct nwrap_libc_fns)); + if (r->libc->fns == NULL) { + printf("Failed to allocate memory for libc functions"); + exit(-1); + } + ZERO_STRUCTP(r->libc->fns); +} + static void nwrap_backend_init(struct nwrap_main *r) { - const char *winbind_so_path = getenv("NSS_WRAPPER_WINBIND_SO_PATH"); + 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; @@ -508,17 +1190,23 @@ static void nwrap_backend_init(struct nwrap_main *r) if (!nwrap_module_init("files", &nwrap_files_ops, NULL, &r->num_backends, &r->backends)) { - NWRAP_ERROR(("%s: failed to initialize 'files' backend\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Failed to initialize 'files' backend"); return; } - if (winbind_so_path && strlen(winbind_so_path)) { - if (!nwrap_module_init("winbind", &nwrap_module_ops, winbind_so_path, + 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_ERROR(("%s: failed to initialize 'winbind' backend\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Failed to initialize '%s' backend", + module_fn_name); return; } } @@ -533,6 +1221,8 @@ static void nwrap_init(void) nwrap_main_global = &__nwrap_main_global; + nwrap_libc_init(nwrap_main_global); + nwrap_backend_init(nwrap_main_global); nwrap_pw_global.cache = &__nwrap_cache_pw; @@ -550,22 +1240,49 @@ static void nwrap_init(void) 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; + + nwrap_he_global.cache = &__nwrap_cache_he; + + nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS"); + 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; } -static bool nwrap_enabled(void) +bool nss_wrapper_enabled(void) { nwrap_init(); - if (!nwrap_pw_global.cache->path) { + if (nwrap_pw_global.cache->path == NULL || + nwrap_pw_global.cache->path[0] == '\0') { return false; } - if (nwrap_pw_global.cache->path[0] == '\0') { + if (nwrap_gr_global.cache->path == NULL || + nwrap_gr_global.cache->path[0] == '\0') { return false; } - if (!nwrap_gr_global.cache->path) { + + return true; +} + +bool nss_wrapper_hosts_enabled(void) +{ + nwrap_init(); + + if (nwrap_he_global.cache->path == NULL || + nwrap_he_global.cache->path[0] == '\0') { return false; } - if (nwrap_gr_global.cache->path[0] == '\0') { + + return true; +} + +static bool nwrap_hostname_enabled(void) +{ + nwrap_init(); + + if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) { return false; } @@ -579,40 +1296,41 @@ static bool nwrap_parse_file(struct nwrap_cache *nwrap) char *nline; if (nwrap->st.st_size == 0) { - NWRAP_DEBUG(("%s: size == 0\n", - __location__)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0"); goto done; } if (nwrap->st.st_size > INT32_MAX) { - NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n", - __location__, (unsigned)nwrap->st.st_size)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Size[%u] larger than INT32_MAX", + (unsigned)nwrap->st.st_size); goto failed; } ret = lseek(nwrap->fd, 0, SEEK_SET); if (ret != 0) { - NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret)); + NWRAP_LOG(NWRAP_LOG_ERROR, "lseek - rc=%d\n", ret); goto failed; } buf = (uint8_t *)malloc(nwrap->st.st_size + 1); if (!buf) { - NWRAP_ERROR(("%s: malloc failed\n",__location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); goto failed; } ret = read(nwrap->fd, buf, nwrap->st.st_size); if (ret != nwrap->st.st_size) { - NWRAP_ERROR(("%s: read(%u) gave %d\n", - __location__, (unsigned)nwrap->st.st_size, ret)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "read(%u) rc=%d\n", + (unsigned)nwrap->st.st_size, ret); goto failed; } buf[nwrap->st.st_size] = '\0'; nline = (char *)buf; - while (nline && nline[0]) { + while (nline != NULL && nline[0] != '\0') { char *line; char *e; bool ok; @@ -631,8 +1349,6 @@ static bool nwrap_parse_file(struct nwrap_cache *nwrap) nline = e; } - NWRAP_VERBOSE(("%s:'%s'\n",__location__, line)); - if (strlen(line) == 0) { continue; } @@ -672,28 +1388,30 @@ reopen: if (nwrap->fd < 0) { nwrap->fd = open(nwrap->path, O_RDONLY); if (nwrap->fd < 0) { - NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n", - __location__, - nwrap->path, nwrap->fd, - strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Unable to open '%s' readonly %d:%s", + nwrap->path, nwrap->fd, + strerror(errno)); return; } - NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path); } ret = fstat(nwrap->fd, &st); if (ret != 0) { - NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n", - __location__, - nwrap->path, - ret, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "fstat(%s) - %d:%s", + nwrap->path, + ret, + strerror(errno)); return; } if (retried == false && st.st_nlink == 0) { /* maybe someone has replaced the file... */ - NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n", - __location__, nwrap->path)); + NWRAP_LOG(NWRAP_LOG_TRACE, + "st_nlink == 0, reopen %s", + nwrap->path); retried = true; memset(&nwrap->st, 0, sizeof(nwrap->st)); close(nwrap->fd); @@ -702,13 +1420,16 @@ reopen: } if (st.st_mtime == nwrap->st.st_mtime) { - NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n", - __location__, (unsigned)st.st_mtime)); + NWRAP_LOG(NWRAP_LOG_TRACE, + "st_mtime[%u] hasn't changed, skip reload", + (unsigned)st.st_mtime); return; } - NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n", - __location__, (unsigned)st.st_mtime, - (unsigned)nwrap->st.st_mtime)); + + 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; @@ -716,12 +1437,11 @@ reopen: ok = nwrap_parse_file(nwrap); if (!ok) { - NWRAP_ERROR(("%s: failed to reload %s\n", - __location__, nwrap->path)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path); nwrap_files_cache_unload(nwrap); } - NWRAP_DEBUG(("%s: reloaded %s\n", - __location__, nwrap->path)); + + NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path); } /* @@ -741,8 +1461,9 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1); pw = (struct passwd *)realloc(nwrap_pw->list, list_size); if (!pw) { - NWRAP_ERROR(("%s:realloc(%u) failed\n", - __location__, list_size)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "realloc(%u) failed", + (unsigned)list_size); return false; } nwrap_pw->list = pw; @@ -754,8 +1475,10 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) /* name */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s'", + line, + c); return false; } *p = '\0'; @@ -763,13 +1486,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) pw->pw_name = c; c = p; - NWRAP_VERBOSE(("name[%s]\n", pw->pw_name)); + NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name); /* password */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -777,13 +1499,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) pw->pw_passwd = c; c = p; - NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd)); + NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd); /* uid */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -791,29 +1512,31 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) e = NULL; pw->pw_uid = (uid_t)strtoul(c, &e, 10); if (c == e) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e == NULL) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e[0] != '\0') { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } c = p; - NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid)); + NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid); /* gid */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -821,29 +1544,31 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) e = NULL; pw->pw_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e == NULL) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e[0] != '\0') { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } c = p; - NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid)); + NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid); /* gecos */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -851,12 +1576,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) pw->pw_gecos = c; c = p; - NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos)); + NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos); /* dir */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:'%s'\n",__location__,c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c); return false; } *p = '\0'; @@ -864,16 +1589,17 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) pw->pw_dir = c; c = p; - NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir)); + NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir); /* shell */ pw->pw_shell = c; - NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell)); + NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell); - NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n", - pw->pw_name, pw->pw_passwd, - pw->pw_uid, pw->pw_gid, - pw->pw_gecos, pw->pw_dir, 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; @@ -905,7 +1631,7 @@ static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst, ofs = PTR_DIFF(last + 1, first); - if (ofs > buflen) { + if (ofs > (off_t) buflen) { return ERANGE; } @@ -949,7 +1675,7 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1); gr = (struct group *)realloc(nwrap_gr->list, list_size); if (!gr) { - NWRAP_ERROR(("%s:realloc failed\n",__location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed"); return false; } nwrap_gr->list = gr; @@ -961,8 +1687,7 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) /* name */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -970,13 +1695,12 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) gr->gr_name = c; c = p; - NWRAP_VERBOSE(("name[%s]\n", gr->gr_name)); + NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name); /* password */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -984,13 +1708,12 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) gr->gr_passwd = c; c = p; - NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd)); + NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd); /* gid */ p = strchr(c, ':'); if (!p) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", - __location__, line, c)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c); return false; } *p = '\0'; @@ -998,28 +1721,31 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) e = NULL; gr->gr_gid = (gid_t)strtoul(c, &e, 10); if (c == e) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e == NULL) { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } if (e[0] != '\0') { - NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", - __location__, line, c, strerror(errno))); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s' - %s", + line, c, strerror(errno)); return false; } c = p; - NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid)); + NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid); /* members */ gr->gr_mem = (char **)malloc(sizeof(char *)); if (!gr->gr_mem) { - NWRAP_ERROR(("%s:calloc failed\n",__location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); return false; } gr->gr_mem[0] = NULL; @@ -1041,19 +1767,23 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) m_size = sizeof(char *) * (nummem+2); m = (char **)realloc(gr->gr_mem, m_size); if (!m) { - NWRAP_ERROR(("%s:realloc(%u) failed\n", - __location__, m_size)); + 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_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem])); + NWRAP_LOG(NWRAP_LOG_TRACE, + "member[%u]: '%s'", + nummem, gr->gr_mem[nummem]); } - NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, 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; @@ -1106,7 +1836,7 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst, ofsb = PTR_DIFF(last + 1, first); ofsm = PTR_DIFF(lastm + 1, src->gr_mem); - if ((ofsb + ofsm) > buflen) { + if ((ofsb + ofsm) > (off_t) buflen) { return ERANGE; } @@ -1132,26 +1862,212 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst, return 0; } +static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line) +{ + struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data; + struct nwrap_entdata *ed; + size_t list_size; + bool do_aliases = true; + int aliases_count = 0; + char *p; + char *i; + char *n; + + list_size = sizeof(struct nwrap_entdata) * (nwrap_he->num + 1); + + ed = (struct nwrap_entdata *)realloc(nwrap_he->list, list_size); + if (ed == NULL) { + NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size); + return false; + } + nwrap_he->list = ed; + + /* set it to the last element */ + ed = &(nwrap_he->list[nwrap_he->num]); + + ed->addr = malloc(sizeof(struct nwrap_addrdata)); + if (ed->addr == NULL) { + NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size); + return false; + } + + 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); + return false; + } + } + + for (i = p; !isspace((int)*p); p++) { + if (*p == '\0') { + NWRAP_LOG(NWRAP_LOG_ERROR, + "Invalid line[%s]: '%s'", + line, i); + 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); + + return false; + } + + ed->addr->h_addr_ptrs[0] = (char *)ed->addr->host_addr; + ed->addr->h_addr_ptrs[1] = NULL; + + ed->ht.h_addr_list = ed->addr->h_addr_ptrs; + + 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); + + return false; + } + } + + for (n = p; !isspace((int)*p); p++) { + if (*p == '\0') { + do_aliases = false; + break; + } + } + + *p = '\0'; + + 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) { + 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) { + return false; + } + ed->ht.h_aliases = aliases; + + aliases[aliases_count] = a; + aliases[aliases_count + 1] = NULL; + + aliases_count++; + } + + 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; + int i; + + if (nwrap_he->list != NULL) { + for (i = 0; i < nwrap_he->num; i++) { + if (nwrap_he->list[i].ht.h_aliases != NULL) { + free(nwrap_he->list[i].ht.h_aliases); + } + if (nwrap_he->list[i].addr != NULL) { + free(nwrap_he->list[i].addr); + } + } + free(nwrap_he->list); + } + + nwrap_he->list = NULL; + nwrap_he->num = 0; + nwrap_he->idx = 0; +} + + /* user functions */ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, const char *name) { int i; + (void) b; /* unused */ + + NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name); + nwrap_files_cache_reload(nwrap_pw_global.cache); for (i=0; i<nwrap_pw_global.num; i++) { if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) { - NWRAP_DEBUG(("%s: user[%s] found\n", - __location__, name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name); return &nwrap_pw_global.list[i]; } - NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n", - __location__, name, - nwrap_pw_global.list[i].pw_name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "user[%s] does not match [%s]", + name, + nwrap_pw_global.list[i].pw_name); } - NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name); errno = ENOENT; return NULL; @@ -1179,20 +2095,22 @@ static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b, { int i; + (void) b; /* unused */ + nwrap_files_cache_reload(nwrap_pw_global.cache); for (i=0; i<nwrap_pw_global.num; i++) { if (nwrap_pw_global.list[i].pw_uid == uid) { - NWRAP_DEBUG(("%s: uid[%u] found\n", - __location__, uid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid); return &nwrap_pw_global.list[i]; } - NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n", - __location__, uid, - nwrap_pw_global.list[i].pw_uid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "uid[%u] does not match [%u]", + uid, + nwrap_pw_global.list[i].pw_uid); } - NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid); errno = ENOENT; return NULL; @@ -1218,6 +2136,8 @@ static int nwrap_files_getpwuid_r(struct nwrap_backend *b, /* user enum functions */ static void nwrap_files_setpwent(struct nwrap_backend *b) { + (void) b; /* unused */ + nwrap_pw_global.idx = 0; } @@ -1225,6 +2145,8 @@ static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b) { struct passwd *pw; + (void) b; /* unused */ + if (nwrap_pw_global.idx == 0) { nwrap_files_cache_reload(nwrap_pw_global.cache); } @@ -1236,8 +2158,9 @@ static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b) pw = &nwrap_pw_global.list[nwrap_pw_global.idx++]; - NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n", - __location__, pw->pw_name, pw->pw_uid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "return user[%s] uid[%u]", + pw->pw_name, pw->pw_uid); return pw; } @@ -1261,6 +2184,8 @@ static int nwrap_files_getpwent_r(struct nwrap_backend *b, static void nwrap_files_endpwent(struct nwrap_backend *b) { + (void) b; /* unused */ + nwrap_pw_global.idx = 0; } @@ -1268,6 +2193,10 @@ static void nwrap_files_endpwent(struct nwrap_backend *b) static int nwrap_files_initgroups(struct nwrap_backend *b, const char *user, gid_t group) { + (void) b; /* unused */ + (void) user; /* unused */ + (void) group; /* used */ + /* TODO: maybe we should also fake this... */ return EPERM; } @@ -1278,20 +2207,22 @@ static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, { int i; + (void) b; /* unused */ + nwrap_files_cache_reload(nwrap_gr_global.cache); for (i=0; i<nwrap_gr_global.num; i++) { if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) { - NWRAP_DEBUG(("%s: group[%s] found\n", - __location__, name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name); return &nwrap_gr_global.list[i]; } - NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n", - __location__, name, - nwrap_gr_global.list[i].gr_name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "group[%s] does not match [%s]", + name, + nwrap_gr_global.list[i].gr_name); } - NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name); errno = ENOENT; return NULL; @@ -1319,20 +2250,22 @@ static struct group *nwrap_files_getgrgid(struct nwrap_backend *b, { int i; + (void) b; /* unused */ + nwrap_files_cache_reload(nwrap_gr_global.cache); for (i=0; i<nwrap_gr_global.num; i++) { if (nwrap_gr_global.list[i].gr_gid == gid) { - NWRAP_DEBUG(("%s: gid[%u] found\n", - __location__, gid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid); return &nwrap_gr_global.list[i]; } - NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n", - __location__, gid, - nwrap_gr_global.list[i].gr_gid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "gid[%u] does not match [%u]", + gid, + nwrap_gr_global.list[i].gr_gid); } - NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid); errno = ENOENT; return NULL; @@ -1358,6 +2291,8 @@ static int nwrap_files_getgrgid_r(struct nwrap_backend *b, /* group enum functions */ static void nwrap_files_setgrent(struct nwrap_backend *b) { + (void) b; /* unused */ + nwrap_gr_global.idx = 0; } @@ -1365,6 +2300,8 @@ static struct group *nwrap_files_getgrent(struct nwrap_backend *b) { struct group *gr; + (void) b; /* unused */ + if (nwrap_gr_global.idx == 0) { nwrap_files_cache_reload(nwrap_gr_global.cache); } @@ -1376,8 +2313,9 @@ static struct group *nwrap_files_getgrent(struct nwrap_backend *b) gr = &nwrap_gr_global.list[nwrap_gr_global.idx++]; - NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n", - __location__, gr->gr_name, gr->gr_gid)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "return group[%s] gid[%u]", + gr->gr_name, gr->gr_gid); return gr; } @@ -1401,9 +2339,189 @@ static int nwrap_files_getgrent_r(struct nwrap_backend *b, static void nwrap_files_endgrent(struct nwrap_backend *b) { + (void) b; /* unused */ + nwrap_gr_global.idx = 0; } +/* hosts functions */ +static struct hostent *nwrap_files_gethostbyname(const char *name, int af) +{ + struct hostent *he; + int i; + + nwrap_files_cache_reload(nwrap_he_global.cache); + + for (i = 0; i < nwrap_he_global.num; i++) { + int j; + + he = &nwrap_he_global.list[i].ht; + + /* Filter by address familiy if provided */ + if (af != AF_UNSPEC && he->h_addrtype != af) { + continue; + } + + if (strcasecmp(he->h_name, name) == 0) { + NWRAP_LOG(NWRAP_LOG_DEBUG, "name[%s] found", name); + return he; + } + + if (he->h_aliases == NULL) { + continue; + } + + for (j = 0; he->h_aliases[j] != NULL; j++) { + if (strcasecmp(he->h_aliases[j], name) == 0) { + NWRAP_LOG(NWRAP_LOG_DEBUG, + "name[%s] found", + name); + return he; + } + } + } + + errno = ENOENT; + return NULL; +} + +#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) +{ + *result = nwrap_files_gethostbyname(name, AF_UNSPEC); + if (*result != NULL) { + memset(buf, '\0', buflen); + *ret = **result; + return 0; + } else { + *h_errnop = h_errno; + return -1; + } +} + +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 + +static struct hostent *nwrap_files_gethostbyaddr(const void *addr, + socklen_t len, int type) +{ + struct hostent *he; + char ip[INET6_ADDRSTRLEN] = {0}; + const char *a; + int i; + + (void) len; /* unused */ + + nwrap_files_cache_reload(nwrap_he_global.cache); + + a = inet_ntop(type, addr, ip, sizeof(ip)); + if (a == NULL) { + errno = EINVAL; + return NULL; + } + + for (i = 0; i < nwrap_he_global.num; i++) { + he = &nwrap_he_global.list[i].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) +{ + *result = nwrap_files_gethostbyaddr(addr, len, type); + if (*result != NULL) { + memset(buf, '\0', buflen); + *ret = **result; + return 0; + } else { + *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) { + nwrap_files_cache_reload(nwrap_he_global.cache); + } + + if (nwrap_he_global.idx >= nwrap_he_global.num) { + errno = ENOENT; + return NULL; + } + + he = &nwrap_he_global.list[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 */ @@ -1430,6 +2548,7 @@ static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, if (status != NSS_STATUS_SUCCESS) { return NULL; } + return &pwd; } @@ -1439,6 +2558,10 @@ static int nwrap_module_getpwnam_r(struct nwrap_backend *b, { int ret; + (void) b; /* unused */ + (void) pwdst; /* unused */ + (void) pwdstp; /* unused */ + if (!b->fns->_nss_getpwnam_r) { return NSS_STATUS_NOTFOUND; } @@ -1492,6 +2615,8 @@ static int nwrap_module_getpwuid_r(struct nwrap_backend *b, { int ret; + (void) pwdstp; /* unused */ + if (!b->fns->_nss_getpwuid_r) { return ENOENT; } @@ -1553,6 +2678,8 @@ static int nwrap_module_getpwent_r(struct nwrap_backend *b, { int ret; + (void) pwdstp; /* unused */ + if (!b->fns->_nss_getpwent_r) { return ENOENT; } @@ -1644,6 +2771,8 @@ static int nwrap_module_getgrnam_r(struct nwrap_backend *b, { int ret; + (void) grdstp; /* unused */ + if (!b->fns->_nss_getgrnam_r) { return ENOENT; } @@ -1713,6 +2842,8 @@ static int nwrap_module_getgrgid_r(struct nwrap_backend *b, { int ret; + (void) grdstp; /* unused */ + if (!b->fns->_nss_getgrgid_r) { return ENOENT; } @@ -1790,6 +2921,8 @@ static int nwrap_module_getgrent_r(struct nwrap_backend *b, { int ret; + (void) grdstp; /* unused */ + if (!b->fns->_nss_getgrent_r) { return ENOENT; } @@ -1825,19 +2958,15 @@ static void nwrap_module_endgrent(struct nwrap_backend *b) b->fns->_nss_endgrent(); } -/* - * PUBLIC interface - */ +/**************************************************************************** + * GETPWNAM + ***************************************************************************/ -_PUBLIC_ struct passwd *nwrap_getpwnam(const char *name) +static struct passwd *nwrap_getpwnam(const char *name) { int i; struct passwd *pwd; - if (!nwrap_enabled()) { - return real_getpwnam(name); - } - 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); @@ -1849,15 +2978,24 @@ _PUBLIC_ struct passwd *nwrap_getpwnam(const char *name) return NULL; } -_PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, - char *buf, size_t buflen, struct passwd **pwdstp) +struct passwd *getpwnam(const char *name) { - int i,ret; - - if (!nwrap_enabled()) { - return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp); + 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) +{ + int i,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); @@ -1870,15 +3008,32 @@ _PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, return ENOENT; } -_PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid) +#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) { int i; struct passwd *pwd; - if (!nwrap_enabled()) { - return real_getpwuid(uid); - } - 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); @@ -1890,15 +3045,24 @@ _PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid) return NULL; } -_PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, - char *buf, size_t buflen, struct passwd **pwdstp) +struct passwd *getpwuid(uid_t uid) { - int i,ret; - - if (!nwrap_enabled()) { - return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); + 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) +{ + int i,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); @@ -1911,30 +3075,54 @@ _PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, return ENOENT; } -_PUBLIC_ void nwrap_setpwent(void) +#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 { - int i; - - if (!nwrap_enabled()) { - real_setpwent(); - return; + 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) +{ + int 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); } } -_PUBLIC_ struct passwd *nwrap_getpwent(void) +void setpwent(void) +{ + if (!nss_wrapper_enabled()) { + libc_setpwent(); + return; + } + + nwrap_setpwent(); +} + +/**************************************************************************** + * GETPWENT + ***************************************************************************/ + +static struct passwd *nwrap_getpwent(void) { int i; struct passwd *pwd; - if (!nwrap_enabled()) { - return real_getpwent(); - } - 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); @@ -1946,30 +3134,24 @@ _PUBLIC_ struct passwd *nwrap_getpwent(void) return NULL; } -_PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf, - size_t buflen, struct passwd **pwdstp) +struct passwd *getpwent(void) { - int i,ret; - - if (!nwrap_enabled()) { -#ifdef SOLARIS_GETPWENT_R - struct passwd *pw; - pw = real_getpwent_r(pwdst, buf, buflen); - if (!pw) { - if (errno == 0) { - return ENOENT; - } - return errno; - } - if (pwdstp) { - *pwdstp = pw; - } - return 0; -#else - return real_getpwent_r(pwdst, buf, buflen, pwdstp); -#endif + if (!nss_wrapper_enabled()) { + return libc_getpwent(); } + return nwrap_getpwent(); +} + +/**************************************************************************** + * GETPWENT_R + ***************************************************************************/ + +static int nwrap_getpwent_r(struct passwd *pwdst, char *buf, + size_t buflen, struct passwd **pwdstp) +{ + int i,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); @@ -1982,14 +3164,41 @@ _PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf, return ENOENT; } -_PUBLIC_ void nwrap_endpwent(void) +#ifdef HAVE_SOLARIS_GETPWENT_R +struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen) { - int i; + struct passwd *pwdstp = NULL; + int rc; - if (!nwrap_enabled()) { - real_endpwent(); - return; + 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 */ + +/**************************************************************************** + * ENDPWENT + ***************************************************************************/ + +static void nwrap_endpwent(void) +{ + int i; for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; @@ -1997,32 +3206,56 @@ _PUBLIC_ void nwrap_endpwent(void) } } -_PUBLIC_ int nwrap_initgroups(const char *user, gid_t group) +void endpwent(void) { - int i; - - if (!nwrap_enabled()) { - return real_initgroups(user, group); + if (!nss_wrapper_enabled()) { + libc_endpwent(); + return; } + nwrap_endpwent(); +} + +/**************************************************************************** + * INITGROUPS + ***************************************************************************/ + +static int nwrap_initgroups(const char *user, gid_t group) +{ + int i; + for (i=0; i < nwrap_main_global->num_backends; i++) { struct nwrap_backend *b = &nwrap_main_global->backends[i]; - return b->ops->nw_initgroups(b, user, group); + int rc; + + rc = b->ops->nw_initgroups(b, user, group); + if (rc == 0) { + return 0; + } } errno = ENOENT; return -1; } -_PUBLIC_ struct group *nwrap_getgrnam(const char *name) +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) { int i; struct group *grp; - if (!nwrap_enabled()) { - return real_getgrnam(name); - } - 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); @@ -2034,15 +3267,24 @@ _PUBLIC_ struct group *nwrap_getgrnam(const char *name) return NULL; } -_PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst, - char *buf, size_t buflen, struct group **grdstp) +struct group *getgrnam(const char *name) { - int i,ret; - - if (!nwrap_enabled()) { - return real_getgrnam_r(name, grdst, buf, buflen, grdstp); + 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) +{ + int i, 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); @@ -2055,15 +3297,36 @@ _PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst, return ENOENT; } -_PUBLIC_ struct group *nwrap_getgrgid(gid_t gid) +#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) { int i; struct group *grp; - if (!nwrap_enabled()) { - return real_getgrgid(gid); - } - 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); @@ -2075,15 +3338,24 @@ _PUBLIC_ struct group *nwrap_getgrgid(gid_t gid) return NULL; } -_PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst, - char *buf, size_t buflen, struct group **grdstp) +struct group *getgrgid(gid_t gid) { - int i,ret; - - if (!nwrap_enabled()) { - return real_getgrgid_r(gid, grdst, buf, buflen, grdstp); + 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) +{ + int i,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); @@ -2096,30 +3368,67 @@ _PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst, return ENOENT; } -_PUBLIC_ void nwrap_setgrent(void) +#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 */ { - int i; - - if (!nwrap_enabled()) { - real_setgrent(); - return; + 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) +{ + int 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); } } -_PUBLIC_ struct group *nwrap_getgrent(void) +#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) { int i; struct group *grp; - if (!nwrap_enabled()) { - return real_getgrent(); - } - 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); @@ -2131,30 +3440,24 @@ _PUBLIC_ struct group *nwrap_getgrent(void) return NULL; } -_PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf, - size_t buflen, struct group **grdstp) +struct group *getgrent(void) { - int i,ret; - - if (!nwrap_enabled()) { -#ifdef SOLARIS_GETGRENT_R - struct group *gr; - gr = real_getgrent_r(grdst, buf, buflen); - if (!gr) { - if (errno == 0) { - return ENOENT; - } - return errno; - } - if (grdstp) { - *grdstp = gr; - } - return 0; -#else - return real_getgrent_r(grdst, buf, buflen, grdstp); -#endif + if (!nss_wrapper_enabled()) { + return libc_getgrent(); } + return nwrap_getgrent(); +} + +/**************************************************************************** + * GETGRENT_R + ***************************************************************************/ + +static int nwrap_getgrent_r(struct group *grdst, char *buf, + size_t buflen, struct group **grdstp) +{ + int i,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); @@ -2167,37 +3470,77 @@ _PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf, return ENOENT; } -_PUBLIC_ void nwrap_endgrent(void) +#ifdef HAVE_SOLARIS_GETGRENT_R +struct group *getgrent_r(struct group *src, char *buf, int buflen) { - int i; + struct group *grdstp = NULL; + int rc; - if (!nwrap_enabled()) { - real_endgrent(); - return; + 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 */ + +/**************************************************************************** + * ENDGRENT + ***************************************************************************/ + +static void nwrap_endgrent(void) +{ + int 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); } } -_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +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, + gid_t *groups, int *ngroups) { struct group *grp; gid_t *groups_tmp; int count = 1; const char *name_of_group = ""; - if (!nwrap_enabled()) { - return real_getgrouplist(user, group, groups, ngroups); - } - - NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user)); + NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user); groups_tmp = (gid_t *)malloc(count * sizeof(gid_t)); if (!groups_tmp) { - NWRAP_ERROR(("%s:calloc failed\n",__location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory"); errno = ENOMEM; return -1; } @@ -2213,20 +3556,24 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in while ((grp = nwrap_getgrent()) != NULL) { int i = 0; - NWRAP_VERBOSE(("%s: inspecting %s for group membership\n", - __location__, grp->gr_name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "Inspecting %s for group membership", + grp->gr_name); for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { if ((strcmp(user, grp->gr_mem[i]) == 0) && (strcmp(name_of_group, grp->gr_name) != 0)) { - NWRAP_DEBUG(("%s: %s is member of %s\n", - __location__, user, grp->gr_name)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "%s is member of %s", + user, + grp->gr_name); groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t)); if (!groups_tmp) { - NWRAP_ERROR(("%s:calloc failed\n",__location__)); + NWRAP_LOG(NWRAP_LOG_ERROR, + "Out of memory"); errno = ENOMEM; return -1; } @@ -2239,8 +3586,9 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in nwrap_endgrent(); - NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n", - __location__, user, *ngroups)); + NWRAP_LOG(NWRAP_LOG_DEBUG, + "%s is member of %d groups", + user, *ngroups); if (*ngroups < count) { *ngroups = count; @@ -2254,3 +3602,631 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in return count; } + +int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + if (!nss_wrapper_enabled()) { + return libc_getgrouplist(user, group, groups, ngroups); + } + + return nwrap_getgrouplist(user, group, groups, ngroups); +} +#endif + +/********************************************************** + * 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 */ + +static struct hostent *nwrap_gethostbyname(const char *name) +{ + return nwrap_files_gethostbyname(name, AF_UNSPEC); +} + +struct hostent *gethostbyname(const char *name) +{ + if (!nss_wrapper_hosts_enabled()) { + return libc_gethostbyname(name); + } + + return nwrap_gethostbyname(name); +} + +/* This is a GNU extension */ +#ifdef HAVE_GETHOSTBYNAME2 +static struct hostent *nwrap_gethostbyname2(const char *name, int af) +{ + return nwrap_files_gethostbyname(name, af); +} + +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) +{ + return nwrap_files_gethostbyaddr(addr, len, type); +} + +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) +{ + struct addrinfo *ai; + socklen_t socklen; + + 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 = 0; + ai->ai_family = he->h_addrtype; + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + + 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: + { + struct sockaddr_in *sinp = + (struct sockaddr_in *) ai->ai_addr; + + memset(sinp, 0, sizeof(struct sockaddr_in)); + + sinp->sin_port = htons(port); + sinp->sin_family = AF_INET; + + memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); + memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length); + + } + break; +#ifdef HAVE_IPV6 + case AF_INET6: + { + struct sockaddr_in6 *sin6p = + (struct sockaddr_in6 *) ai->ai_addr; + + memset(sin6p, 0, sizeof(struct sockaddr_in6)); + + sin6p->sin6_port = htons(port); + sin6p->sin6_family = AF_INET6; + + memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length); + } + break; +#endif + } + + ai->ai_next = NULL; + + if (he->h_name) { + 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; + struct addrinfo *p = NULL; + unsigned short port = 0; + struct hostent *he; + struct in_addr in; + bool is_addr_ipv4 = false; + bool is_addr_ipv6 = false; + int eai = EAI_SYSTEM; + int ret; + int rc; + int af; + + if (node == NULL && service == NULL) { + return EAI_NONAME; + } + + ret = libc_getaddrinfo(node, service, hints, &p); + if (ret == 0) { + *res = p; + } + + /* If no node has been specified, let glibc deal with it */ + if (node == NULL) { + return ret; + } + + if (hints == NULL) { + hints = &default_hints; + } + + if ((hints->ai_flags & AI_CANONNAME) && node == NULL) { + return EAI_BADFLAGS; + } + + if (service != NULL && service[0] != '\0') { + if (isdigit((int)service[0])) { + port = (unsigned short)atoi(service); + } else { + const char *proto = NULL; + struct servent *s; + + 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) { + port = ntohs(s->s_port); + } else { + if (p != NULL) { + freeaddrinfo(p); + } + return EAI_SERVICE; + } + } + } + + af = hints->ai_family; + if (af == AF_UNSPEC) { + af = AF_INET; + } + + rc = inet_pton(af, node, &in); + if (rc == 1) { + is_addr_ipv4 = true; + if (af == AF_UNSPEC) { + af = AF_INET; + } +#ifdef HAVE_IPV6 + } else { + struct in6_addr in6; + + af = AF_INET6; + + rc = inet_pton(af, node, &in6); + if (rc == 1) { + is_addr_ipv6 = true; + } +#endif + } + + if (is_addr_ipv4) { + he = nwrap_files_gethostbyaddr(&in, sizeof(struct in_addr), af); + if (he != NULL) { + rc = nwrap_convert_he_ai(he, port, hints, &ai); + } else { + eai = EAI_NODATA; + rc = -1; + } +#ifdef HAVE_IPV6 + } else if (is_addr_ipv6) { + struct in6_addr in6; + + rc = inet_pton(af, node, &in6); + if (rc <= 0) { + eai = EAI_ADDRFAMILY; + return ret == 0 ? 0 : eai; + } + + he = nwrap_files_gethostbyaddr(&in6, + sizeof(struct in6_addr), + af); + if (he != NULL) { + rc = nwrap_convert_he_ai(he, port, hints, &ai); + eai = rc; + } else { + eai = EAI_NODATA; + rc = -1; + } +#endif + } else { + he = nwrap_files_gethostbyname(node, hints->ai_family); + if (he != NULL) { + rc = nwrap_convert_he_ai(he, port, hints, &ai); + eai = rc; + } else { + eai = EAI_NODATA; + rc = -1; + } + } + + if (rc < 0) { + return ret == 0 ? 0 : eai; + } + + if (ret == 0) { + freeaddrinfo(p); + } + + if (ai->ai_flags == 0) { + ai->ai_flags = hints->ai_flags; + } + if (ai->ai_socktype == 0) { + ai->ai_socktype = SOCK_DGRAM; + } + if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) { + ai->ai_protocol = 17; /* UDP */ + } else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) { + ai->ai_protocol = 6; /* TCP */ + } + + if (hints->ai_socktype == 0) { + /* Add second ai */ + rc = nwrap_convert_he_ai(he, port, hints, &ai->ai_next); + if (rc < 0) { + freeaddrinfo(ai); + return rc; + } + + if (ai->ai_next->ai_flags == 0) { + ai->ai_next->ai_flags = hints->ai_flags; + } + if (ai->ai_socktype == SOCK_DGRAM) { + ai->ai_next->ai_socktype = SOCK_STREAM; + } else if (ai->ai_socktype == SOCK_STREAM) { + ai->ai_next->ai_socktype = SOCK_DGRAM; + } + if (ai->ai_next->ai_socktype == SOCK_DGRAM) { + ai->ai_next->ai_protocol = 17; /* UDP */ + } else if (ai->ai_next->ai_socktype == SOCK_STREAM) { + ai->ai_next->ai_protocol = 6; /* TCP */ + } + } + + *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; + + 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: + if (salen < sizeof(struct sockaddr_in)) + return EAI_FAMILY; + addr = &((struct sockaddr_in *)sa)->sin_addr; + addrlen = sizeof(((struct sockaddr_in *)sa)->sin_addr); + port = ntohs(((struct sockaddr_in *)sa)->sin_port); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + if (salen < sizeof(struct sockaddr_in6)) + return EAI_FAMILY; + addr = &((struct sockaddr_in6 *)sa)->sin6_addr; + addrlen = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); + port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); + break; +#endif + default: + return EAI_FAMILY; + } + + if (host != NULL) { + he = NULL; + if ((flags & NI_NUMERICHOST) == 0) { + he = nwrap_files_gethostbyaddr(addr, addrlen, type); + 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; + strcpy(host, 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; + strcpy(serv, 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); +} + +/**************************** + * 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) +{ + int i; + + if (nwrap_main_global != NULL) { + struct nwrap_main *m = nwrap_main_global; + + /* libc */ + SAFE_FREE(m->libc->fns); + if (m->libc->handle != NULL) { + dlclose(m->libc->handle); + } + if (m->libc->nsl_handle != NULL) { + dlclose(m->libc->nsl_handle); + } + if (m->libc->sock_handle != NULL) { + dlclose(m->libc->sock_handle); + } + SAFE_FREE(m->libc); + + /* backends */ + 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->fns); + } + 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) { + close(c->fd); + } + + 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) { + close(c->fd); + } + + SAFE_FREE(nwrap_gr_global.list); + nwrap_pw_global.num = 0; + } + + if (nwrap_he_global.cache != NULL) { + struct nwrap_cache *c = nwrap_he_global.cache; + + nwrap_files_cache_unload(c); + if (c->fd >= 0) { + close(c->fd); + } + + SAFE_FREE(nwrap_he_global.list); + nwrap_he_global.num = 0; + } +} diff --git a/lib/nss_wrapper/nss_wrapper.h b/lib/nss_wrapper/nss_wrapper.h deleted file mode 100644 index 5bcd42ead40..00000000000 --- a/lib/nss_wrapper/nss_wrapper.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org> - * - * 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_WRAPPER_H__ -#define __NSS_WRAPPER_H__ - -struct passwd *nwrap_getpwnam(const char *name); -int nwrap_getpwnam_r(const char *name, struct passwd *pwbuf, - char *buf, size_t buflen, struct passwd **pwbufp); -struct passwd *nwrap_getpwuid(uid_t uid); -int nwrap_getpwuid_r(uid_t uid, struct passwd *pwbuf, - char *buf, size_t buflen, struct passwd **pwbufp); -void nwrap_setpwent(void); -struct passwd *nwrap_getpwent(void); -int nwrap_getpwent_r(struct passwd *pwbuf, char *buf, - size_t buflen, struct passwd **pwbufp); -void nwrap_endpwent(void); -int nwrap_initgroups(const char *user, gid_t group); -int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups); -struct group *nwrap_getgrnam(const char *name); -int nwrap_getgrnam_r(const char *name, struct group *gbuf, - char *buf, size_t buflen, struct group **gbufp); -struct group *nwrap_getgrgid(gid_t gid); -int nwrap_getgrgid_r(gid_t gid, struct group *gbuf, - char *buf, size_t buflen, struct group **gbufp); -void nwrap_setgrent(void); -struct group *nwrap_getgrent(void); -int nwrap_getgrent_r(struct group *gbuf, char *buf, - size_t buflen, struct group **gbufp); -void nwrap_endgrent(void); - -#ifdef NSS_WRAPPER_REPLACE - -#ifdef getpwnam -#undef getpwnam -#endif -#define getpwnam nwrap_getpwnam - -#ifdef getpwnam_r -#undef getpwnam_r -#endif -#define getpwnam_r nwrap_getpwnam_r - -#ifdef getpwuid -#undef getpwuid -#endif -#define getpwuid nwrap_getpwuid - -#ifdef getpwuid_r -#undef getpwuid_r -#endif -#define getpwuid_r nwrap_getpwuid_r - -#ifdef setpwent -#undef setpwent -#endif -#define setpwent nwrap_setpwent - -#ifdef getpwent -#undef getpwent -#endif -#define getpwent nwrap_getpwent - -#ifdef getpwent_r -#undef getpwent_r -#endif -#define getpwent_r nwrap_getpwent_r - -#ifdef endpwent -#undef endpwent -#endif -#define endpwent nwrap_endpwent - -#ifdef getgrlst -#undef getgrlst -#endif -#define getgrlst __none_nwrap_getgrlst - -#ifdef getgrlst_r -#undef getgrlst_r -#endif -#define getgrlst_r __none_nwrap_getgrlst_r - -#ifdef initgroups_dyn -#undef initgroups_dyn -#endif -#define initgroups_dyn __none_nwrap_initgroups_dyn - -#ifdef initgroups -#undef initgroups -#endif -#define initgroups nwrap_initgroups - -#ifdef getgrouplist -#undef getgrouplist -#endif -#define getgrouplist nwrap_getgrouplist - -#ifdef getgrnam -#undef getgrnam -#endif -#define getgrnam nwrap_getgrnam - -#ifdef getgrnam_r -#undef getgrnam_r -#endif -#define getgrnam_r nwrap_getgrnam_r - -#ifdef getgrgid -#undef getgrgid -#endif -#define getgrgid nwrap_getgrgid - -#ifdef getgrgid_r -#undef getgrgid_r -#endif -#define getgrgid_r nwrap_getgrgid_r - -#ifdef setgrent -#undef setgrent -#endif -#define setgrent nwrap_setgrent - -#ifdef getgrent -#undef getgrent -#endif -#define getgrent nwrap_getgrent - -#ifdef getgrent_r -#undef getgrent_r -#endif -#define getgrent_r nwrap_getgrent_r - -#ifdef endgrent -#undef endgrent -#endif -#define endgrent nwrap_endgrent - -#endif /* NSS_WRAPPER_REPLACE */ - -#endif /* __NSS_WRAPPER_H__ */ diff --git a/lib/nss_wrapper/testsuite.c b/lib/nss_wrapper/testsuite.c deleted file mode 100644 index 6fae1244f08..00000000000 --- a/lib/nss_wrapper/testsuite.c +++ /dev/null @@ -1,958 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - local testing of the nss wrapper - - Copyright (C) Guenther Deschner 2009-2010 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -#ifndef NSS_WRAPPER -#define NSS_WRAPPER -#endif - -#include "torture/torture.h" -#include "torture/local/proto.h" -#include "lib/replace/system/passwd.h" - -static bool copy_passwd(struct torture_context *tctx, - const struct passwd *pwd, - struct passwd *p) -{ - p->pw_name = talloc_strdup(tctx, pwd->pw_name); - p->pw_passwd = talloc_strdup(tctx, pwd->pw_passwd); - p->pw_uid = pwd->pw_uid; - p->pw_gid = pwd->pw_gid; - p->pw_gecos = talloc_strdup(tctx, pwd->pw_gecos); - p->pw_dir = talloc_strdup(tctx, pwd->pw_dir); - p->pw_shell = talloc_strdup(tctx, pwd->pw_shell); - - return true; -} - -static void print_passwd(struct passwd *pwd) -{ - printf("%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(struct torture_context *tctx, - const char *name, - struct passwd *pwd_p) -{ - struct passwd *pwd; - - torture_comment(tctx, "Testing getpwnam: %s\n", name); - - pwd = getpwnam(name); - if (pwd) { - print_passwd(pwd); - } - - if (pwd_p) { - copy_passwd(tctx, pwd, pwd_p); - } - - return pwd ? true : false; -} - -static bool test_nwrap_getpwnam_r(struct torture_context *tctx, - const char *name, - struct passwd *pwd_p) -{ - struct passwd pwd, *pwdp; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing getpwnam_r: %s\n", name); - - ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - return false; - } - - print_passwd(&pwd); - - if (pwd_p) { - copy_passwd(tctx, &pwd, pwd_p); - } - - return true; -} - -static bool test_nwrap_getpwuid(struct torture_context *tctx, - uid_t uid, - struct passwd *pwd_p) -{ - struct passwd *pwd; - - torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid); - - pwd = getpwuid(uid); - if (pwd) { - print_passwd(pwd); - } - - if (pwd_p) { - copy_passwd(tctx, pwd, pwd_p); - } - - return pwd ? true : false; -} - -static bool test_nwrap_getpwuid_r(struct torture_context *tctx, - uid_t uid, - struct passwd *pwd_p) -{ - struct passwd pwd, *pwdp; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing getpwuid_r: %lu\n", (unsigned long)uid); - - ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - return false; - } - - print_passwd(&pwd); - - if (pwd_p) { - copy_passwd(tctx, &pwd, pwd_p); - } - - return true; -} - - -static bool copy_group(struct torture_context *tctx, - const struct group *grp, - struct group *g) -{ - int i; - - g->gr_name = talloc_strdup(tctx, grp->gr_name); - g->gr_passwd = talloc_strdup(tctx, grp->gr_passwd); - g->gr_gid = grp->gr_gid; - g->gr_mem = NULL; - - for (i=0; grp->gr_mem && grp->gr_mem[i]; i++) { - g->gr_mem = talloc_realloc(tctx, g->gr_mem, char *, i + 2); - g->gr_mem[i] = talloc_strdup(g->gr_mem, grp->gr_mem[i]); - g->gr_mem[i+1] = NULL; - } - - return true; -} - -static void print_group(struct group *grp) -{ - int i; - printf("%s:%s:%lu:", - grp->gr_name, - grp->gr_passwd, - (unsigned long)grp->gr_gid); - - if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) { - printf("\n"); - return; - } - - for (i=0; grp->gr_mem[i+1]; i++) { - printf("%s,", grp->gr_mem[i]); - } - printf("%s\n", grp->gr_mem[i]); -} - -static bool test_nwrap_getgrnam(struct torture_context *tctx, - const char *name, - struct group *grp_p) -{ - struct group *grp; - - torture_comment(tctx, "Testing getgrnam: %s\n", name); - - grp = getgrnam(name); - if (grp) { - print_group(grp); - } - - if (grp_p) { - copy_group(tctx, grp, grp_p); - } - - return grp ? true : false; -} - -static bool test_nwrap_getgrnam_r(struct torture_context *tctx, - const char *name, - struct group *grp_p) -{ - struct group grp, *grpp; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing getgrnam_r: %s\n", name); - - ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - return false; - } - - print_group(&grp); - - if (grp_p) { - copy_group(tctx, &grp, grp_p); - } - - return true; -} - - -static bool test_nwrap_getgrgid(struct torture_context *tctx, - gid_t gid, - struct group *grp_p) -{ - struct group *grp; - - torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid); - - grp = getgrgid(gid); - if (grp) { - print_group(grp); - } - - if (grp_p) { - copy_group(tctx, grp, grp_p); - } - - return grp ? true : false; -} - -static bool test_nwrap_getgrgid_r(struct torture_context *tctx, - gid_t gid, - struct group *grp_p) -{ - struct group grp, *grpp; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing getgrgid_r: %lu\n", (unsigned long)gid); - - ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - return false; - } - - print_group(&grp); - - if (grp_p) { - copy_group(tctx, &grp, grp_p); - } - - return true; -} - -static bool test_nwrap_enum_passwd(struct torture_context *tctx, - struct passwd **pwd_array_p, - size_t *num_pwd_p) -{ - struct passwd *pwd; - struct passwd *pwd_array = NULL; - size_t num_pwd = 0; - - torture_comment(tctx, "Testing setpwent\n"); - setpwent(); - - while ((pwd = getpwent()) != NULL) { - torture_comment(tctx, "Testing getpwent\n"); - - print_passwd(pwd); - if (pwd_array_p && num_pwd_p) { - pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1); - torture_assert(tctx, pwd_array, "out of memory"); - copy_passwd(tctx, pwd, &pwd_array[num_pwd]); - num_pwd++; - } - } - - torture_comment(tctx, "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 torture_context *tctx, - struct passwd **pwd_array_p, - size_t *num_pwd_p) -{ - struct passwd pwd, *pwdp; - struct passwd *pwd_array = NULL; - size_t num_pwd = 0; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing setpwent\n"); - setpwent(); - - while (1) { - torture_comment(tctx, "Testing getpwent_r\n"); - - ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - break; - } - print_passwd(&pwd); - if (pwd_array_p && num_pwd_p) { - pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1); - torture_assert(tctx, pwd_array, "out of memory"); - copy_passwd(tctx, &pwd, &pwd_array[num_pwd]); - num_pwd++; - } - } - - torture_comment(tctx, "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 torture_assert_passwd_equal(struct torture_context *tctx, - const struct passwd *p1, - const struct passwd *p2, - const char *comment) -{ - torture_assert_str_equal(tctx, p1->pw_name, p2->pw_name, comment); - torture_assert_str_equal(tctx, p1->pw_passwd, p2->pw_passwd, comment); - torture_assert_int_equal(tctx, p1->pw_uid, p2->pw_uid, comment); - torture_assert_int_equal(tctx, p1->pw_gid, p2->pw_gid, comment); - torture_assert_str_equal(tctx, p1->pw_gecos, p2->pw_gecos, comment); - torture_assert_str_equal(tctx, p1->pw_dir, p2->pw_dir, comment); - torture_assert_str_equal(tctx, p1->pw_shell, p2->pw_shell, comment); - - return true; -} - -static bool test_nwrap_passwd(struct torture_context *tctx) -{ - int i; - struct passwd *pwd, pwd1, pwd2; - size_t num_pwd; - - torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), - "failed to enumerate passwd"); - - for (i=0; i < num_pwd; i++) { - torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name, &pwd1), - "failed to call getpwnam for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd1, - "getpwent and getpwnam gave different results"); - torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid, &pwd2), - "failed to call getpwuid for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd2, - "getpwent and getpwuid gave different results"); - torture_assert_passwd_equal(tctx, &pwd1, &pwd2, - "getpwnam and getpwuid gave different results"); - } - - return true; -} - -static bool test_nwrap_passwd_r(struct torture_context *tctx) -{ - int i; - struct passwd *pwd, pwd1, pwd2; - size_t num_pwd; - - torture_assert(tctx, test_nwrap_enum_r_passwd(tctx, &pwd, &num_pwd), - "failed to enumerate passwd"); - - for (i=0; i < num_pwd; i++) { - torture_assert(tctx, test_nwrap_getpwnam_r(tctx, pwd[i].pw_name, &pwd1), - "failed to call getpwnam_r for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd1, - "getpwent_r and getpwnam_r gave different results"); - torture_assert(tctx, test_nwrap_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2), - "failed to call getpwuid_r for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd2, - "getpwent_r and getpwuid_r gave different results"); - torture_assert_passwd_equal(tctx, &pwd1, &pwd2, - "getpwnam_r and getpwuid_r gave different results"); - } - - return true; -} - -static bool test_nwrap_passwd_r_cross(struct torture_context *tctx) -{ - int i; - struct passwd *pwd, pwd1, pwd2, pwd3, pwd4; - size_t num_pwd; - - torture_assert(tctx, test_nwrap_enum_r_passwd(tctx, &pwd, &num_pwd), - "failed to enumerate passwd"); - - for (i=0; i < num_pwd; i++) { - torture_assert(tctx, test_nwrap_getpwnam_r(tctx, pwd[i].pw_name, &pwd1), - "failed to call getpwnam_r for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd1, - "getpwent_r and getpwnam_r gave different results"); - torture_assert(tctx, test_nwrap_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2), - "failed to call getpwuid_r for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd2, - "getpwent_r and getpwuid_r gave different results"); - torture_assert_passwd_equal(tctx, &pwd1, &pwd2, - "getpwnam_r and getpwuid_r gave different results"); - torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name, &pwd3), - "failed to call getpwnam for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd3, - "getpwent_r and getpwnam gave different results"); - torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid, &pwd4), - "failed to call getpwuid for enumerated user"); - torture_assert_passwd_equal(tctx, &pwd[i], &pwd4, - "getpwent_r and getpwuid gave different results"); - torture_assert_passwd_equal(tctx, &pwd3, &pwd4, - "getpwnam and getpwuid gave different results"); - } - - return true; -} - -static bool test_nwrap_enum_group(struct torture_context *tctx, - struct group **grp_array_p, - size_t *num_grp_p) -{ - struct group *grp; - struct group *grp_array = NULL; - size_t num_grp = 0; - - torture_comment(tctx, "Testing setgrent\n"); - setgrent(); - - while ((grp = getgrent()) != NULL) { - torture_comment(tctx, "Testing getgrent\n"); - - print_group(grp); - if (grp_array_p && num_grp_p) { - grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1); - torture_assert(tctx, grp_array, "out of memory"); - copy_group(tctx, grp, &grp_array[num_grp]); - num_grp++; - } - } - - torture_comment(tctx, "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 torture_context *tctx, - struct group **grp_array_p, - size_t *num_grp_p) -{ - struct group grp, *grpp; - struct group *grp_array = NULL; - size_t num_grp = 0; - char buffer[4096]; - int ret; - - torture_comment(tctx, "Testing setgrent\n"); - setgrent(); - - while (1) { - torture_comment(tctx, "Testing getgrent_r\n"); - - ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp); - if (ret != 0) { - if (ret != ENOENT) { - torture_comment(tctx, "got %d return code\n", ret); - } - break; - } - print_group(&grp); - if (grp_array_p && num_grp_p) { - grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1); - torture_assert(tctx, grp_array, "out of memory"); - copy_group(tctx, &grp, &grp_array[num_grp]); - num_grp++; - } - } - - torture_comment(tctx, "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 torture_assert_group_equal(struct torture_context *tctx, - const struct group *g1, - const struct group *g2, - const char *comment) -{ - int i; - torture_assert_str_equal(tctx, g1->gr_name, g2->gr_name, comment); - torture_assert_str_equal(tctx, g1->gr_passwd, g2->gr_passwd, comment); - torture_assert_int_equal(tctx, g1->gr_gid, g2->gr_gid, comment); - if (g1->gr_mem && !g2->gr_mem) { - return false; - } - if (!g1->gr_mem && g2->gr_mem) { - return false; - } - if (!g1->gr_mem && !g2->gr_mem) { - return true; - } - for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) { - torture_assert_str_equal(tctx, g1->gr_mem[i], g2->gr_mem[i], comment); - } - - return true; -} - -static bool test_nwrap_group(struct torture_context *tctx) -{ - int i; - struct group *grp, grp1, grp2; - size_t num_grp; - - torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp), - "failed to enumerate group"); - - for (i=0; i < num_grp; i++) { - torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name, &grp1), - "failed to call getgrnam for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp1, - "getgrent and getgrnam gave different results"); - torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid, &grp2), - "failed to call getgrgid for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp2, - "getgrent and getgrgid gave different results"); - torture_assert_group_equal(tctx, &grp1, &grp2, - "getgrnam and getgrgid gave different results"); - } - - return true; -} - -static bool test_nwrap_group_r(struct torture_context *tctx) -{ - int i; - struct group *grp, grp1, grp2; - size_t num_grp; - - torture_assert(tctx, test_nwrap_enum_r_group(tctx, &grp, &num_grp), - "failed to enumerate group"); - - for (i=0; i < num_grp; i++) { - torture_assert(tctx, test_nwrap_getgrnam_r(tctx, grp[i].gr_name, &grp1), - "failed to call getgrnam_r for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp1, - "getgrent_r and getgrnam_r gave different results"); - torture_assert(tctx, test_nwrap_getgrgid_r(tctx, grp[i].gr_gid, &grp2), - "failed to call getgrgid_r for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp2, - "getgrent_r and getgrgid_r gave different results"); - torture_assert_group_equal(tctx, &grp1, &grp2, - "getgrnam_r and getgrgid_r gave different results"); - } - - return true; -} - -static bool test_nwrap_group_r_cross(struct torture_context *tctx) -{ - int i; - struct group *grp, grp1, grp2, grp3, grp4; - size_t num_grp; - - torture_assert(tctx, test_nwrap_enum_r_group(tctx, &grp, &num_grp), - "failed to enumerate group"); - - for (i=0; i < num_grp; i++) { - torture_assert(tctx, test_nwrap_getgrnam_r(tctx, grp[i].gr_name, &grp1), - "failed to call getgrnam_r for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp1, - "getgrent_r and getgrnam_r gave different results"); - torture_assert(tctx, test_nwrap_getgrgid_r(tctx, grp[i].gr_gid, &grp2), - "failed to call getgrgid_r for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp2, - "getgrent_r and getgrgid_r gave different results"); - torture_assert_group_equal(tctx, &grp1, &grp2, - "getgrnam_r and getgrgid_r gave different results"); - torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name, &grp3), - "failed to call getgrnam for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp3, - "getgrent_r and getgrnam gave different results"); - torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid, &grp4), - "failed to call getgrgid for enumerated user"); - torture_assert_group_equal(tctx, &grp[i], &grp4, - "getgrent_r and getgrgid gave different results"); - torture_assert_group_equal(tctx, &grp3, &grp4, - "getgrnam and getgrgid gave different results"); - } - - return true; -} - -static bool test_nwrap_getgrouplist(struct torture_context *tctx, - const char *user, - gid_t gid, - gid_t **gids_p, - int *num_gids_p) -{ - int ret; - int num_groups = 0; - gid_t *groups = NULL; - - torture_comment(tctx, "Testing getgrouplist: %s\n", user); - - ret = getgrouplist(user, gid, NULL, &num_groups); - if (ret == -1 || num_groups != 0) { - - groups = talloc_array(tctx, gid_t, num_groups); - torture_assert(tctx, groups, "out of memory\n"); - - ret = getgrouplist(user, gid, groups, &num_groups); - } - - torture_assert(tctx, (ret != -1), "failed to call getgrouplist"); - - torture_comment(tctx, "%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(struct torture_context *tctx, - const struct passwd *pwd, - const struct group *grp) -{ - int i; - - for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { - if (strequal(grp->gr_mem[i], pwd->pw_name)) { - return true; - } - } - - return false; -} - -static bool test_nwrap_membership_user(struct torture_context *tctx, - const struct passwd *pwd, - struct group *grp_array, - size_t num_grp) -{ - int num_user_groups = 0; - int num_user_groups_from_enum = 0; - gid_t *user_groups = NULL; - int g, i; - bool primary_group_had_user_member = false; - - torture_assert(tctx, test_nwrap_getgrouplist(tctx, - pwd->pw_name, - pwd->pw_gid, - &user_groups, - &num_user_groups), - "failed to test getgrouplist"); - - for (g=0; g < num_user_groups; g++) { - torture_assert(tctx, test_nwrap_getgrgid(tctx, user_groups[g], NULL), - "failed to find the group the user is a member of"); - } - - - for (i=0; i < num_grp; i++) { - - struct group grp = grp_array[i]; - - if (test_nwrap_user_in_group(tctx, pwd, &grp)) { - - struct group current_grp; - num_user_groups_from_enum++; - - torture_assert(tctx, test_nwrap_getgrnam(tctx, grp.gr_name, ¤t_grp), - "failed to find the group the user is a member of"); - - if (current_grp.gr_gid == pwd->pw_gid) { - torture_comment(tctx, "primary group %s of user %s lists user as member\n", - current_grp.gr_name, - pwd->pw_name); - primary_group_had_user_member = true; - } - - continue; - } - } - - if (!primary_group_had_user_member) { - num_user_groups_from_enum++; - } - - torture_assert_int_equal(tctx, num_user_groups, num_user_groups_from_enum, - "getgrouplist and real inspection of grouplist gave different results\n"); - - return true; -} - -static bool test_nwrap_membership(struct torture_context *tctx) -{ - 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; - int i; - - if (!old_pwd || !old_group) { - torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); - torture_skip(tctx, "nothing to test\n"); - } - - torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), - "failed to enumerate passwd"); - torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp), - "failed to enumerate group"); - - for (i=0; i < num_pwd; i++) { - - torture_assert(tctx, test_nwrap_membership_user(tctx, &pwd[i], grp, num_grp), - "failed to test membership for user"); - - } - - return true; -} - -static bool test_nwrap_enumeration(struct torture_context *tctx) -{ - const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); - const char *old_group = getenv("NSS_WRAPPER_GROUP"); - - if (!old_pwd || !old_group) { - torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); - torture_skip(tctx, "nothing to test\n"); - } - - torture_assert(tctx, test_nwrap_passwd(tctx), - "failed to test users"); - torture_assert(tctx, test_nwrap_group(tctx), - "failed to test groups"); - - return true; -} - -static bool test_nwrap_reentrant_enumeration(struct torture_context *tctx) -{ - const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); - const char *old_group = getenv("NSS_WRAPPER_GROUP"); - - if (!old_pwd || !old_group) { - torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); - torture_skip(tctx, "nothing to test\n"); - } - - torture_comment(tctx, "Testing re-entrant calls\n"); - - torture_assert(tctx, test_nwrap_passwd_r(tctx), - "failed to test users"); - torture_assert(tctx, test_nwrap_group_r(tctx), - "failed to test groups"); - - return true; -} - -static bool test_nwrap_reentrant_enumeration_crosschecks(struct torture_context *tctx) -{ - const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); - const char *old_group = getenv("NSS_WRAPPER_GROUP"); - - if (!old_pwd || !old_group) { - torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); - torture_skip(tctx, "nothing to test\n"); - } - - torture_comment(tctx, "Testing re-entrant calls with cross checks\n"); - - torture_assert(tctx, test_nwrap_passwd_r_cross(tctx), - "failed to test users"); - torture_assert(tctx, test_nwrap_group_r_cross(tctx), - "failed to test groups"); - - return true; -} - -static bool test_nwrap_passwd_duplicates(struct torture_context *tctx) -{ - int i, d; - struct passwd *pwd; - size_t num_pwd; - int duplicates = 0; - - torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd), - "failed to enumerate passwd"); - - 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 (!strequal(current_name, dup_name)) { - continue; - } - - torture_warning(tctx, "found duplicate names:"); - print_passwd(&pwd[d]); - print_passwd(&pwd[i]); - duplicates++; - } - } - - if (duplicates) { - torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates)); - } - - return true; -} - -static bool test_nwrap_group_duplicates(struct torture_context *tctx) -{ - int i, d; - struct group *grp; - size_t num_grp; - int duplicates = 0; - - torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp), - "failed to enumerate group"); - - 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 (!strequal(current_name, dup_name)) { - continue; - } - - torture_warning(tctx, "found duplicate names:"); - print_group(&grp[d]); - print_group(&grp[i]); - duplicates++; - } - } - - if (duplicates) { - torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates)); - } - - return true; -} - - -static bool test_nwrap_duplicates(struct torture_context *tctx) -{ - const char *old_pwd = getenv("NSS_WRAPPER_PASSWD"); - const char *old_group = getenv("NSS_WRAPPER_GROUP"); - - if (!old_pwd || !old_group) { - torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n"); - torture_skip(tctx, "nothing to test\n"); - } - - torture_assert(tctx, test_nwrap_passwd_duplicates(tctx), - "failed to test users"); - torture_assert(tctx, test_nwrap_group_duplicates(tctx), - "failed to test groups"); - - return true; -} - - -struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "nss-wrapper"); - - torture_suite_add_simple_test(suite, "enumeration", test_nwrap_enumeration); - torture_suite_add_simple_test(suite, "reentrant enumeration", test_nwrap_reentrant_enumeration); - torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_nwrap_reentrant_enumeration_crosschecks); - torture_suite_add_simple_test(suite, "membership", test_nwrap_membership); - torture_suite_add_simple_test(suite, "duplicates", test_nwrap_duplicates); - - return suite; -} diff --git a/lib/nss_wrapper/wscript b/lib/nss_wrapper/wscript index 5cfff1f76cb..34026c06ed7 100644 --- a/lib/nss_wrapper/wscript +++ b/lib/nss_wrapper/wscript @@ -1,17 +1,106 @@ #!/usr/bin/env python -import Options +import os -def set_options(opt): - gr = opt.option_group('developer options') - gr.add_option('--enable-nss-wrapper', - help=("Turn on nss wrapper library (default=no)"), - action="store_true", dest='enable_nss_wrapper', default=False) +VERSION="1.0.2" def configure(conf): - if (Options.options.enable_nss_wrapper or - Options.options.developer or - Options.options.enable_selftest): - conf.DEFINE('NSS_WRAPPER', 1) - conf.ADD_GLOBAL_DEPENDENCY('nss_wrapper') + if conf.CHECK_BUNDLED_SYSTEM('nss_wrapper', minversion=VERSION, set_target=False): + conf.DEFINE('USING_SYSTEM_NSS_WRAPPER', 1) + libnss_wrapper_so_path = 'libnss_wrapper.so' + else: + # check HAVE_GCC_THREAD_LOCAL_STORAGE + conf.CHECK_CODE(''' + __thread int tls; + int main(void) { + return 0; + } + ''', + 'HAVE_GCC_THREAD_LOCAL_STORAGE', + addmain=False, + msg='Checking for thread local storage') + + # check HAVE_DESTRUCTOR_ATTRIBUTE + conf.CHECK_CODE(''' + void test_destructor_attribute(void) __attribute__ ((destructor)); + + void test_destructor_attribute(void) + { + return; + } + + int main(void) { + return 0; + } + ''', + 'HAVE_DESTRUCTOR_ATTRIBUTE', + addmain=False, + msg='Checking for library destructor support') + + conf.CHECK_FUNCS('gethostbyaddr_r gethostbyname_r') + # Solaris + conf.CHECK_FUNCS('__posix_getpwnam_r __posix_getpwuid_r') + conf.CHECK_FUNCS('__posix_getgrgid_r __posix_getgrnam_r') + + conf.CHECK_FUNCS_IN('nsl', + 'gethostname', + checklibc=True, + headers='unistd.h') + + # Prototype checks + conf.CHECK_C_PROTOTYPE('getpwent_r', + 'struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)', + define='HAVE_SOLARIS_GETPWENT_R', headers='unistd.h pwd.h') + conf.CHECK_C_PROTOTYPE('getpwnam_r', + 'int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)', + define='HAVE_SOLARIS_GETPWNAM_R', headers='unistd.h pwd.h') + conf.CHECK_C_PROTOTYPE('getpwuid_r', + 'int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)', + define='HAVE_SOLARIS_GETPWUID_R', headers='unistd.h pwd.h') + conf.CHECK_C_PROTOTYPE('getgrent_r', + 'struct group *getgrent_r(struct group *src, char *buf, int buflen)', + define='SOLARIS_GETGRENT_R', headers='unistd.h grp.h') + conf.CHECK_C_PROTOTYPE('getgrnam_r', + 'int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)', + define='HAVE_SOLARIS_GETGRNAM_R', headers='unistd.h grp.h') + conf.CHECK_C_PROTOTYPE('getgrgid_r', + 'int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)', + define='HAVE_SOLARIS_GETGRGID_R', headers='unistd.h grp.h') + conf.CHECK_C_PROTOTYPE('sethostent', + 'int sethostent(int stayopen)', + define='HAVE_SOLARIS_SETHOSTENT', headers='unistd.h netdb.h') + conf.CHECK_C_PROTOTYPE('endhostent', + 'int endhostent(void)', + define='HAVE_SOLARIS_ENDHOSTENT', headers='unistd.h netdb.h') + conf.CHECK_C_PROTOTYPE('gethostname', + 'int gethostname(char *name, int len)', + define='HAVE_SOLARIS_GETHOSTNAME', headers='unistd.h netdb.h') + conf.CHECK_C_PROTOTYPE('setgrent', + 'int setgrent(void)', + define='HAVE_BSD_SETGRENT', headers='unistd.h grp.h') + conf.CHECK_C_PROTOTYPE('getnameinfo', + 'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)', + define='HAVE_LINUX_GETNAMEINFO', headers='unistd.h netdb.h') + conf.CHECK_C_PROTOTYPE('getnameinfo', + 'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)', + define='HAVE_LINUX_GETNAMEINFO_UNSIGNED', headers='unistd.h netdb.h') + + # Create full path to nss_wrapper + srcdir = os.path.realpath(conf.srcdir) + libnss_wrapper_so_path = srcdir + '/bin/default/lib/nss_wrapper/libnss-wrapper.so' + + conf.DEFINE('LIBNSS_WRAPPER_SO_PATH', libnss_wrapper_so_path) + conf.DEFINE('NSS_WRAPPER', 1) + +def build(bld): + if not bld.CONFIG_SET("USING_SYSTEM_NSS_WRAPPER"): + # We need to do it this way or the library wont work. + # Using private_library=True will add symbol version which + # breaks preloading! + bld.SAMBA_LIBRARY('nss_wrapper', + source='nss_wrapper.c', + cflags='-DNDEBUG', + deps='dl', + install=False, + realname='libnss-wrapper.so') diff --git a/lib/nss_wrapper/wscript_build b/lib/nss_wrapper/wscript_build deleted file mode 100644 index 5f9df3a600c..00000000000 --- a/lib/nss_wrapper/wscript_build +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python - - -bld.SAMBA_LIBRARY('nss_wrapper', - source='nss_wrapper.c', - deps='replace', - private_library=True, - enabled=bld.CONFIG_SET("NSS_WRAPPER"), - ) - @@ -40,7 +40,6 @@ def set_options(opt): opt.RECURSE('lib/ntdb') opt.RECURSE('selftest') opt.RECURSE('source4/lib/tls') - opt.RECURSE('lib/nss_wrapper') opt.RECURSE('lib/socket_wrapper') opt.RECURSE('pidl') opt.RECURSE('source3') |