2007-11-05 18:38:36 +03:00
/*
* Copyright ( C ) Stefan Metzmacher 2007 < metze @ samba . org >
2009-06-07 17:59:20 +04:00
* Copyright ( C ) Guenther Deschner 2009 < gd @ samba . org >
2014-01-31 18:57:43 +04:00
* Copyright ( C ) Andreas Schneider 2013 < asn @ samba . org >
2007-11-05 18:38:36 +03:00
*
* 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 .
*/
2014-01-31 18:57:43 +04:00
# include "config.h"
2015-03-24 19:54:34 +03:00
# include <pthread.h>
2014-01-31 18:57:43 +04:00
# 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>
2007-11-05 18:38:36 +03:00
2015-11-12 13:08:47 +03:00
# include <netinet/in.h>
2015-07-15 16:01:48 +03:00
# include <search.h>
2015-03-23 16:10:18 +03:00
# include <assert.h>
2014-01-31 18:57:43 +04:00
/*
* 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
*/
2011-05-05 01:57:37 +04:00
# ifndef _POSIX_PTHREAD_SEMANTICS
2010-03-22 10:40:44 +03:00
# define _POSIX_PTHREAD_SEMANTICS
2011-05-05 01:57:37 +04:00
# endif
2010-03-22 10:40:44 +03:00
2014-01-31 18:57:43 +04:00
# include <pwd.h>
# include <grp.h>
2015-10-06 11:19:48 +03:00
# ifdef HAVE_SHADOW_H
2015-09-17 11:33:58 +03:00
# include <shadow.h>
2015-10-06 11:19:48 +03:00
# endif /* HAVE_SHADOW_H */
2014-01-31 18:57:43 +04:00
# include <netdb.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# include <dlfcn.h>
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
# if defined(HAVE_NSS_H)
/* Linux and BSD */
# include <nss.h>
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
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
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
# ifndef PTR_DIFF
# define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
2007-11-05 18:38:36 +03:00
# endif
# ifndef _PUBLIC_
# define _PUBLIC_
# endif
2014-01-31 18:57:43 +04:00
# ifndef EAI_NODATA
# define EAI_NODATA EAI_NONAME
2007-11-06 11:06:50 +03:00
# endif
2014-01-31 18:57:43 +04:00
# ifndef EAI_ADDRFAMILY
# define EAI_ADDRFAMILY EAI_FAMILY
2007-11-06 11:06:50 +03:00
# endif
2014-01-31 18:57:43 +04:00
# ifndef __STRING
# define __STRING(x) #x
2007-11-06 11:06:50 +03:00
# endif
2014-01-31 18:57:43 +04:00
# ifndef __STRINGSTRING
# define __STRINGSTRING(x) __STRING(x)
2007-11-06 11:06:50 +03:00
# endif
2014-01-31 18:57:43 +04:00
# ifndef __LINESTR__
# define __LINESTR__ __STRINGSTRING(__LINE__)
2007-11-06 11:06:50 +03:00
# endif
2014-01-31 18:57:43 +04:00
# ifndef __location__
# define __location__ __FILE__ ":" __LINESTR__
2009-05-31 00:43:17 +04:00
# endif
2014-10-09 11:16:33 +04:00
# ifndef DNS_NAME_MAX
# define DNS_NAME_MAX 255
# endif
2014-01-31 18:57:43 +04:00
/* 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 */
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
# ifdef HAVE_DESTRUCTOR_ATTRIBUTE
# define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
# else
# define DESTRUCTOR_ATTRIBUTE
# endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
# define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
2007-11-05 18:38:36 +03:00
2014-11-29 15:22:46 +03:00
# ifndef SAFE_FREE
# define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
# endif
2015-03-25 11:36:10 +03:00
# ifdef HAVE_IPV6
# define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
# else
# define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
# endif
2015-03-24 19:54:34 +03:00
# define NWRAP_LOCK(m) do { \
pthread_mutex_lock ( & ( m # # _mutex ) ) ; \
} while ( 0 )
# define NWRAP_UNLOCK(m) do { \
pthread_mutex_unlock ( & ( m # # _mutex ) ) ; \
} while ( 0 )
static bool nwrap_initialized = false ;
static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER ;
/* The mutex or accessing the id */
static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER ;
static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER ;
static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER ;
static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER ;
static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER ;
/* Add new global locks here please */
/* Also don't forget to add locks to
* nwrap_init ( ) function .
*/
# define NWRAP_LOCK_ALL do { \
NWRAP_LOCK ( nwrap_initialized ) ; \
NWRAP_LOCK ( nwrap_global ) ; \
NWRAP_LOCK ( nwrap_gr_global ) ; \
NWRAP_LOCK ( nwrap_he_global ) ; \
NWRAP_LOCK ( nwrap_pw_global ) ; \
NWRAP_LOCK ( nwrap_sp_global ) ; \
} while ( 0 ) ;
# define NWRAP_UNLOCK_ALL do {\
NWRAP_UNLOCK ( nwrap_sp_global ) ; \
NWRAP_UNLOCK ( nwrap_pw_global ) ; \
NWRAP_UNLOCK ( nwrap_he_global ) ; \
NWRAP_UNLOCK ( nwrap_gr_global ) ; \
NWRAP_UNLOCK ( nwrap_global ) ; \
NWRAP_UNLOCK ( nwrap_initialized ) ; \
} while ( 0 ) ;
static void nwrap_thread_prepare ( void )
{
NWRAP_LOCK_ALL ;
}
static void nwrap_thread_parent ( void )
{
NWRAP_UNLOCK_ALL ;
}
static void nwrap_thread_child ( void )
{
NWRAP_UNLOCK_ALL ;
}
2014-01-31 18:57:43 +04:00
enum nwrap_dbglvl_e {
NWRAP_LOG_ERROR = 0 ,
NWRAP_LOG_WARN ,
NWRAP_LOG_DEBUG ,
NWRAP_LOG_TRACE
} ;
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
# ifdef NDEBUG
# define NWRAP_LOG(...)
# else
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
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__)
2007-11-05 18:38:36 +03:00
2014-01-31 18:57:43 +04:00
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 ) ;
2007-11-05 18:39:46 +03:00
# else
2014-01-31 18:57:43 +04:00
int ( * _libc_getpwent_r ) ( struct passwd * pwbuf , char * buf , size_t buflen , struct passwd * * pwbufp ) ;
2007-11-05 18:39:46 +03:00
# endif
2014-01-31 18:57:43 +04:00
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 ) ;
2007-11-05 18:39:46 +03:00
# else
2014-01-31 18:57:43 +04:00
int ( * _libc_getgrent_r ) ( struct group * group , char * buf , size_t buflen , struct group * * result ) ;
2007-11-05 18:39:46 +03:00
# endif
2014-01-31 18:57:43 +04:00
void ( * _libc_endgrent ) ( void ) ;
int ( * _libc_getgrouplist ) ( const char * user , gid_t group , gid_t * groups , int * ngroups ) ;
2007-11-05 18:39:46 +03:00
2014-01-31 18:57:43 +04:00
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 ) ;
2007-11-05 18:39:46 +03:00
# endif
2014-01-31 18:57:43 +04:00
} ;
2007-11-05 18:39:46 +03:00
2009-06-04 13:59:32 +04:00
struct nwrap_module_nss_fns {
NSS_STATUS ( * _nss_getpwnam_r ) ( const char * name , struct passwd * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_getpwuid_r ) ( uid_t uid , struct passwd * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_setpwent ) ( void ) ;
NSS_STATUS ( * _nss_getpwent_r ) ( struct passwd * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_endpwent ) ( void ) ;
NSS_STATUS ( * _nss_initgroups ) ( const char * user , gid_t group , long int * start ,
long int * size , gid_t * * groups , long int limit , int * errnop ) ;
NSS_STATUS ( * _nss_getgrnam_r ) ( const char * name , struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_getgrgid_r ) ( gid_t gid , struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_setgrent ) ( void ) ;
NSS_STATUS ( * _nss_getgrent_r ) ( struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS ( * _nss_endgrent ) ( void ) ;
} ;
2009-06-03 13:10:13 +04:00
struct nwrap_backend {
2009-05-31 03:01:13 +04:00
const char * name ;
2009-06-04 13:59:32 +04:00
const char * so_path ;
void * so_handle ;
2009-06-03 13:10:13 +04:00
struct nwrap_ops * ops ;
2009-06-04 13:59:32 +04:00
struct nwrap_module_nss_fns * fns ;
2009-05-31 03:01:13 +04:00
} ;
2009-06-03 13:10:13 +04:00
struct nwrap_ops {
struct passwd * ( * nw_getpwnam ) ( struct nwrap_backend * b ,
const char * name ) ;
int ( * nw_getpwnam_r ) ( struct nwrap_backend * b ,
const char * name , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
struct passwd * ( * nw_getpwuid ) ( struct nwrap_backend * b ,
uid_t uid ) ;
int ( * nw_getpwuid_r ) ( struct nwrap_backend * b ,
uid_t uid , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
void ( * nw_setpwent ) ( struct nwrap_backend * b ) ;
struct passwd * ( * nw_getpwent ) ( struct nwrap_backend * b ) ;
int ( * nw_getpwent_r ) ( struct nwrap_backend * b ,
struct passwd * pwdst , char * buf ,
size_t buflen , struct passwd * * pwdstp ) ;
void ( * nw_endpwent ) ( struct nwrap_backend * b ) ;
int ( * nw_initgroups ) ( struct nwrap_backend * b ,
const char * user , gid_t group ) ;
struct group * ( * nw_getgrnam ) ( struct nwrap_backend * b ,
const char * name ) ;
int ( * nw_getgrnam_r ) ( struct nwrap_backend * b ,
const char * name , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp ) ;
struct group * ( * nw_getgrgid ) ( struct nwrap_backend * b ,
gid_t gid ) ;
int ( * nw_getgrgid_r ) ( struct nwrap_backend * b ,
gid_t gid , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp ) ;
void ( * nw_setgrent ) ( struct nwrap_backend * b ) ;
struct group * ( * nw_getgrent ) ( struct nwrap_backend * b ) ;
int ( * nw_getgrent_r ) ( struct nwrap_backend * b ,
struct group * grdst , char * buf ,
size_t buflen , struct group * * grdstp ) ;
void ( * nw_endgrent ) ( struct nwrap_backend * b ) ;
} ;
2014-01-31 18:57:43 +04:00
/* Public prototypes */
bool nss_wrapper_enabled ( void ) ;
2015-09-17 11:37:50 +03:00
bool nss_wrapper_shadow_enabled ( void ) ;
2014-01-31 18:57:43 +04:00
bool nss_wrapper_hosts_enabled ( void ) ;
2010-02-21 08:32:29 +03:00
/* prototypes for files backend */
2009-06-03 13:10:13 +04:00
static struct passwd * nwrap_files_getpwnam ( struct nwrap_backend * b ,
const char * name ) ;
static int nwrap_files_getpwnam_r ( struct nwrap_backend * b ,
const char * name , struct passwd * pwdst ,
2009-05-31 03:01:13 +04:00
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
2009-06-03 13:10:13 +04:00
static struct passwd * nwrap_files_getpwuid ( struct nwrap_backend * b ,
uid_t uid ) ;
static int nwrap_files_getpwuid_r ( struct nwrap_backend * b ,
uid_t uid , struct passwd * pwdst ,
2009-05-31 03:01:13 +04:00
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
2009-06-03 13:10:13 +04:00
static void nwrap_files_setpwent ( struct nwrap_backend * b ) ;
static struct passwd * nwrap_files_getpwent ( struct nwrap_backend * b ) ;
static int nwrap_files_getpwent_r ( struct nwrap_backend * b ,
struct passwd * pwdst , char * buf ,
2009-05-31 03:01:13 +04:00
size_t buflen , struct passwd * * pwdstp ) ;
2009-06-03 13:10:13 +04:00
static void nwrap_files_endpwent ( struct nwrap_backend * b ) ;
static int nwrap_files_initgroups ( struct nwrap_backend * b ,
const char * user , gid_t group ) ;
static struct group * nwrap_files_getgrnam ( struct nwrap_backend * b ,
const char * name ) ;
static int nwrap_files_getgrnam_r ( struct nwrap_backend * b ,
const char * name , struct group * grdst ,
2009-05-31 03:01:13 +04:00
char * buf , size_t buflen , struct group * * grdstp ) ;
2009-06-03 13:10:13 +04:00
static struct group * nwrap_files_getgrgid ( struct nwrap_backend * b ,
gid_t gid ) ;
static int nwrap_files_getgrgid_r ( struct nwrap_backend * b ,
gid_t gid , struct group * grdst ,
2009-05-31 03:01:13 +04:00
char * buf , size_t buflen , struct group * * grdstp ) ;
2009-06-03 13:10:13 +04:00
static void nwrap_files_setgrent ( struct nwrap_backend * b ) ;
static struct group * nwrap_files_getgrent ( struct nwrap_backend * b ) ;
static int nwrap_files_getgrent_r ( struct nwrap_backend * b ,
struct group * grdst , char * buf ,
2009-05-31 03:01:13 +04:00
size_t buflen , struct group * * grdstp ) ;
2009-06-03 13:10:13 +04:00
static void nwrap_files_endgrent ( struct nwrap_backend * b ) ;
2009-05-31 03:01:13 +04:00
2010-02-21 08:32:29 +03:00
/* prototypes for module backend */
2009-06-04 14:17:39 +04:00
static struct passwd * nwrap_module_getpwent ( struct nwrap_backend * b ) ;
static int nwrap_module_getpwent_r ( struct nwrap_backend * b ,
struct passwd * pwdst , char * buf ,
size_t buflen , struct passwd * * pwdstp ) ;
static struct passwd * nwrap_module_getpwnam ( struct nwrap_backend * b ,
const char * name ) ;
static int nwrap_module_getpwnam_r ( struct nwrap_backend * b ,
const char * name , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
static struct passwd * nwrap_module_getpwuid ( struct nwrap_backend * b ,
uid_t uid ) ;
static int nwrap_module_getpwuid_r ( struct nwrap_backend * b ,
uid_t uid , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp ) ;
static void nwrap_module_setpwent ( struct nwrap_backend * b ) ;
static void nwrap_module_endpwent ( struct nwrap_backend * b ) ;
static struct group * nwrap_module_getgrent ( struct nwrap_backend * b ) ;
static int nwrap_module_getgrent_r ( struct nwrap_backend * b ,
struct group * grdst , char * buf ,
size_t buflen , struct group * * grdstp ) ;
static struct group * nwrap_module_getgrnam ( struct nwrap_backend * b ,
const char * name ) ;
static int nwrap_module_getgrnam_r ( struct nwrap_backend * b ,
const char * name , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp ) ;
static struct group * nwrap_module_getgrgid ( struct nwrap_backend * b ,
gid_t gid ) ;
static int nwrap_module_getgrgid_r ( struct nwrap_backend * b ,
gid_t gid , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp ) ;
static void nwrap_module_setgrent ( struct nwrap_backend * b ) ;
static void nwrap_module_endgrent ( struct nwrap_backend * b ) ;
static int nwrap_module_initgroups ( struct nwrap_backend * b ,
const char * user , gid_t group ) ;
2009-05-31 03:01:13 +04:00
struct nwrap_ops nwrap_files_ops = {
2009-06-02 16:52:53 +04:00
. nw_getpwnam = nwrap_files_getpwnam ,
. nw_getpwnam_r = nwrap_files_getpwnam_r ,
. nw_getpwuid = nwrap_files_getpwuid ,
. nw_getpwuid_r = nwrap_files_getpwuid_r ,
. nw_setpwent = nwrap_files_setpwent ,
. nw_getpwent = nwrap_files_getpwent ,
. nw_getpwent_r = nwrap_files_getpwent_r ,
. nw_endpwent = nwrap_files_endpwent ,
. nw_initgroups = nwrap_files_initgroups ,
. nw_getgrnam = nwrap_files_getgrnam ,
. nw_getgrnam_r = nwrap_files_getgrnam_r ,
. nw_getgrgid = nwrap_files_getgrgid ,
. nw_getgrgid_r = nwrap_files_getgrgid_r ,
. nw_setgrent = nwrap_files_setgrent ,
. nw_getgrent = nwrap_files_getgrent ,
. nw_getgrent_r = nwrap_files_getgrent_r ,
. nw_endgrent = nwrap_files_endgrent ,
2009-05-31 03:01:13 +04:00
} ;
2009-06-04 14:17:39 +04:00
struct nwrap_ops nwrap_module_ops = {
. nw_getpwnam = nwrap_module_getpwnam ,
. nw_getpwnam_r = nwrap_module_getpwnam_r ,
. nw_getpwuid = nwrap_module_getpwuid ,
. nw_getpwuid_r = nwrap_module_getpwuid_r ,
. nw_setpwent = nwrap_module_setpwent ,
. nw_getpwent = nwrap_module_getpwent ,
. nw_getpwent_r = nwrap_module_getpwent_r ,
. nw_endpwent = nwrap_module_endpwent ,
. nw_initgroups = nwrap_module_initgroups ,
. nw_getgrnam = nwrap_module_getgrnam ,
. nw_getgrnam_r = nwrap_module_getgrnam_r ,
. nw_getgrgid = nwrap_module_getgrgid ,
. nw_getgrgid_r = nwrap_module_getgrgid_r ,
. nw_setgrent = nwrap_module_setgrent ,
. nw_getgrent = nwrap_module_getgrent ,
. nw_getgrent_r = nwrap_module_getgrent_r ,
. nw_endgrent = nwrap_module_endgrent ,
} ;
2014-01-31 18:57:43 +04:00
struct nwrap_libc {
void * handle ;
void * nsl_handle ;
void * sock_handle ;
struct nwrap_libc_fns * fns ;
} ;
2009-05-31 03:01:13 +04:00
struct nwrap_main {
2009-06-03 13:10:13 +04:00
int num_backends ;
struct nwrap_backend * backends ;
2014-01-31 18:57:43 +04:00
struct nwrap_libc * libc ;
2009-05-31 03:01:13 +04:00
} ;
2015-07-16 17:10:20 +03:00
static struct nwrap_main * nwrap_main_global ;
static struct nwrap_main __nwrap_main_global ;
/*
* PROTOTYPES
*/
static int nwrap_convert_he_ai ( const struct hostent * he ,
unsigned short port ,
const struct addrinfo * hints ,
struct addrinfo * * pai ,
bool skip_canonname ) ;
2009-05-31 03:01:13 +04:00
2015-03-23 16:10:18 +03:00
/*
* VECTORS
*/
# define DEFAULT_VECTOR_CAPACITY 16
struct nwrap_vector {
void * * items ;
size_t count ;
size_t capacity ;
} ;
/* Macro returns pointer to first element of vector->items array.
*
* nwrap_vector is used as a memory backend which take care of
* memory allocations and other stuff like memory growing .
* nwrap_vectors should not be considered as some abstract structures .
* On this level , vectors are more handy than direct realloc / malloc
* calls .
*
* nwrap_vector - > items is array inside nwrap_vector which can be
* directly pointed by libc structure assembled by cwrap itself .
*
* EXAMPLE :
*
* 1 ) struct hostent contains char * * h_addr_list element .
* 2 ) nwrap_vector holds array of pointers to addresses .
* It ' s easier to use vector to store results of
* file parsing etc .
*
* Now , pretend that cwrap assembled struct hostent and
* we need to set h_addr_list to point to nwrap_vector .
* Idea behind is to shield users from internal nwrap_vector
* implementation .
* ( Yes , not fully - array terminated by NULL is needed because
* it ' s result expected by libc function caller . )
*
*
* CODE EXAMPLE :
*
* struct hostent he ;
* struct nwrap_vector * vector = malloc ( sizeof ( struct nwrap_vector ) ) ;
* . . . don ' t care about failed allocation now . . .
*
* . . . fill nwrap vector . . .
*
* struct hostent he ;
* he . h_addr_list = nwrap_vector_head ( vector ) ;
*
*/
# define nwrap_vector_head(vect) ((void *)((vect)->items))
# define nwrap_vector_foreach(item, vect, iter) \
for ( iter = 0 , ( item ) = ( vect ) . items = = NULL ? NULL : ( vect ) . items [ 0 ] ; \
item ! = NULL ; \
( item ) = ( vect ) . items [ + + iter ] )
2015-10-08 16:27:47 +03:00
# define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
2015-03-23 16:10:18 +03:00
static inline bool nwrap_vector_init ( struct nwrap_vector * const vector )
{
if ( vector = = NULL ) {
return false ;
}
/* count is initialized by ZERO_STRUCTP */
ZERO_STRUCTP ( vector ) ;
vector - > items = malloc ( sizeof ( void * ) * ( DEFAULT_VECTOR_CAPACITY + 1 ) ) ;
if ( vector - > items = = NULL ) {
return false ;
}
vector - > capacity = DEFAULT_VECTOR_CAPACITY ;
memset ( vector - > items , ' \0 ' , sizeof ( void * ) * ( DEFAULT_VECTOR_CAPACITY + 1 ) ) ;
return true ;
}
2015-10-08 15:09:11 +03:00
static bool nwrap_vector_add_item ( struct nwrap_vector * vector , void * const item )
2015-03-23 16:10:18 +03:00
{
2015-10-08 15:09:11 +03:00
assert ( vector ! = NULL ) ;
2015-03-23 16:10:18 +03:00
2015-10-08 15:09:11 +03:00
if ( vector - > items = = NULL ) {
nwrap_vector_init ( vector ) ;
2015-03-23 16:10:18 +03:00
}
2015-10-08 15:09:11 +03:00
if ( vector - > count = = vector - > capacity ) {
2015-03-23 16:10:18 +03:00
/* Items array _MUST_ be NULL terminated because it's passed
* as result to caller which expect NULL terminated array from libc .
*/
2015-10-08 15:09:11 +03:00
void * * items = realloc ( vector - > items , sizeof ( void * ) * ( ( vector - > capacity * 2 ) + 1 ) ) ;
2015-03-23 16:10:18 +03:00
if ( items = = NULL ) {
return false ;
}
2015-10-08 15:09:11 +03:00
vector - > items = items ;
2015-03-23 16:10:18 +03:00
/* Don't count ending NULL to capacity */
2015-10-08 15:09:11 +03:00
vector - > capacity * = 2 ;
2015-03-23 16:10:18 +03:00
}
2015-10-08 15:09:11 +03:00
vector - > items [ vector - > count ] = item ;
2015-03-23 16:10:18 +03:00
2015-10-08 15:09:11 +03:00
vector - > count + = 1 ;
vector - > items [ vector - > count ] = NULL ;
2015-03-23 16:10:18 +03:00
return true ;
}
static bool nwrap_vector_merge ( struct nwrap_vector * dst ,
struct nwrap_vector * src )
{
void * * dst_items = NULL ;
size_t count ;
if ( src - > count = = 0 ) {
return true ;
}
count = dst - > count + src - > count ;
/* We don't need reallocation if we have enough capacity. */
if ( src - > count > ( dst - > capacity - dst - > count ) ) {
dst_items = ( void * * ) realloc ( dst - > items , ( count + 1 ) * sizeof ( void * ) ) ;
if ( dst_items = = NULL ) {
return false ;
}
dst - > items = dst_items ;
dst - > capacity = count ;
}
memcpy ( ( void * ) ( ( ( long * ) dst - > items ) + dst - > count ) ,
src - > items ,
src - > count * sizeof ( void * ) ) ;
dst - > count = count ;
return true ;
}
2007-11-05 18:39:46 +03:00
struct nwrap_cache {
const char * path ;
int fd ;
2015-03-23 16:39:28 +03:00
FILE * fp ;
2007-11-05 18:39:46 +03:00
struct stat st ;
void * private_data ;
2015-03-23 16:39:28 +03:00
struct nwrap_vector lines ;
2007-11-05 18:39:46 +03:00
bool ( * parse_line ) ( struct nwrap_cache * , char * line ) ;
void ( * unload ) ( struct nwrap_cache * ) ;
} ;
2015-09-17 11:33:58 +03:00
/* passwd */
2007-11-05 18:39:46 +03:00
struct nwrap_pw {
struct nwrap_cache * cache ;
struct passwd * list ;
int num ;
int idx ;
} ;
struct nwrap_cache __nwrap_cache_pw ;
struct nwrap_pw nwrap_pw_global ;
static bool nwrap_pw_parse_line ( struct nwrap_cache * nwrap , char * line ) ;
static void nwrap_pw_unload ( struct nwrap_cache * nwrap ) ;
2015-09-17 11:33:58 +03:00
/* shadow */
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2015-09-17 11:33:58 +03:00
struct nwrap_sp {
struct nwrap_cache * cache ;
struct spwd * list ;
int num ;
int idx ;
} ;
struct nwrap_cache __nwrap_cache_sp ;
struct nwrap_sp nwrap_sp_global ;
static bool nwrap_sp_parse_line ( struct nwrap_cache * nwrap , char * line ) ;
static void nwrap_sp_unload ( struct nwrap_cache * nwrap ) ;
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-09-17 11:33:58 +03:00
/* group */
2007-11-05 18:41:23 +03:00
struct nwrap_gr {
struct nwrap_cache * cache ;
struct group * list ;
int num ;
int idx ;
} ;
struct nwrap_cache __nwrap_cache_gr ;
struct nwrap_gr nwrap_gr_global ;
2015-09-17 11:33:58 +03:00
/* hosts */
2014-01-31 18:57:43 +04:00
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 */
} ;
2015-07-15 16:01:48 +03:00
static size_t max_hostents = 100 ;
2014-01-31 18:57:43 +04:00
struct nwrap_entdata {
2015-07-16 17:10:20 +03:00
struct nwrap_addrdata addr ;
2014-01-31 18:57:43 +04:00
struct hostent ht ;
2015-07-15 16:01:48 +03:00
struct nwrap_vector nwrap_addrdata ;
ssize_t aliases_count ;
2015-11-11 12:27:50 +03:00
} ;
2015-07-15 16:01:48 +03:00
2015-11-11 12:27:50 +03:00
struct nwrap_entlist {
struct nwrap_entlist * next ;
struct nwrap_entdata * ed ;
2014-01-31 18:57:43 +04:00
} ;
struct nwrap_he {
struct nwrap_cache * cache ;
2015-11-19 02:30:17 +03:00
struct nwrap_vector entries ;
2015-11-19 03:00:16 +03:00
struct nwrap_vector lists ;
2015-07-16 17:10:20 +03:00
2014-01-31 18:57:43 +04:00
int num ;
int idx ;
} ;
2015-07-16 17:10:20 +03:00
static struct nwrap_cache __nwrap_cache_he ;
static struct nwrap_he nwrap_he_global ;
2014-01-31 18:57:43 +04:00
/*********************************************************
* NWRAP PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void nwrap_init ( void ) ;
2007-11-05 18:41:23 +03:00
static bool nwrap_gr_parse_line ( struct nwrap_cache * nwrap , char * line ) ;
static void nwrap_gr_unload ( struct nwrap_cache * nwrap ) ;
2014-01-31 18:57:43 +04:00
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 RTLD_DEEPBIND
flags | = RTLD_DEEPBIND ;
# endif
switch ( lib ) {
case NWRAP_LIBNSL :
# ifdef HAVE_LIBNSL
handle = nwrap_main_global - > libc - > nsl_handle ;
if ( handle = = NULL ) {
2014-10-01 19:15:35 +04:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-01-31 18:57:43 +04:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libnsl.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2014-10-01 19:15:35 +04:00
if ( handle ! = NULL ) {
break ;
}
2014-01-31 18:57:43 +04:00
}
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 ) {
2014-10-01 19:15:35 +04:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-01-31 18:57:43 +04:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libsocket.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2014-10-01 19:15:35 +04:00
if ( handle ! = NULL ) {
break ;
}
2014-01-31 18:57:43 +04:00
}
nwrap_main_global - > libc - > sock_handle = handle ;
}
break ;
# endif
/* FALL TROUGH */
case NWRAP_LIBC :
handle = nwrap_main_global - > libc - > handle ;
if ( handle = = NULL ) {
2014-10-01 19:15:35 +04:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-01-31 18:57:43 +04:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libc.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2014-10-01 19:15:35 +04:00
if ( handle ! = NULL ) {
break ;
}
2014-01-31 18:57:43 +04:00
}
nwrap_main_global - > libc - > handle = handle ;
}
break ;
}
if ( handle = = NULL ) {
2014-10-09 11:13:48 +04:00
# ifdef RTLD_NEXT
handle = nwrap_main_global - > libc - > handle
= nwrap_main_global - > libc - > sock_handle
= nwrap_main_global - > libc - > nsl_handle
= RTLD_NEXT ;
# else
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Failed to dlopen library: %s \n " ,
dlerror ( ) ) ;
exit ( - 1 ) ;
2014-10-09 11:13:48 +04:00
# endif
2014-01-31 18:57:43 +04:00
}
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 ) ; \
}
2015-03-23 16:39:28 +03:00
/* INTERNAL HELPER FUNCTIONS */
static void nwrap_lines_unload ( struct nwrap_cache * const nwrap )
{
size_t p ;
2015-10-08 15:00:38 +03:00
void * item ;
nwrap_vector_foreach ( item , nwrap - > lines , p ) {
2015-03-23 16:39:28 +03:00
/* Maybe some vectors were merged ... */
2015-10-08 15:00:38 +03:00
SAFE_FREE ( item ) ;
2015-03-23 16:39:28 +03:00
}
SAFE_FREE ( nwrap - > lines . items ) ;
2015-10-08 15:00:38 +03:00
ZERO_STRUCTP ( & nwrap - > lines ) ;
2015-03-23 16:39:28 +03:00
}
2014-01-31 18:57:43 +04:00
/*
* 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
2015-03-24 17:14:35 +03:00
static inline void str_tolower ( char * dst , char * src )
{
register char * src_tmp = src ;
register char * dst_tmp = dst ;
while ( * src_tmp ! = ' \0 ' ) {
* dst_tmp = tolower ( * src_tmp ) ;
+ + src_tmp ;
+ + dst_tmp ;
}
}
static bool str_tolower_copy ( char * * dst_name , const char * const src_name )
{
char * h_name_lower ;
if ( ( dst_name = = NULL ) | | ( src_name = = NULL ) ) {
return false ;
}
h_name_lower = strdup ( src_name ) ;
if ( h_name_lower = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Out of memory while strdup " ) ;
return false ;
}
str_tolower ( h_name_lower , h_name_lower ) ;
* dst_name = h_name_lower ;
return true ;
}
2014-01-31 18:57:43 +04:00
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-05 18:41:23 +03:00
2009-06-04 13:59:32 +04:00
static void * nwrap_load_module_fn ( struct nwrap_backend * b ,
const char * fn_name )
{
void * res ;
char * s ;
if ( ! b - > so_handle ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " No handle " ) ;
2009-06-04 13:59:32 +04:00
return NULL ;
}
if ( asprintf ( & s , " _nss_%s_%s " , b - > name , fn_name ) = = - 1 ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Out of memory " ) ;
2009-06-04 13:59:32 +04:00
return NULL ;
}
res = dlsym ( b - > so_handle , s ) ;
if ( ! res ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Cannot find function %s in %s " ,
s , b - > so_path ) ;
2009-06-04 13:59:32 +04:00
}
2014-11-29 15:22:46 +03:00
SAFE_FREE ( s ) ;
2009-06-04 13:59:32 +04:00
return res ;
}
static struct nwrap_module_nss_fns * nwrap_load_module_fns ( struct nwrap_backend * b )
{
struct nwrap_module_nss_fns * fns ;
if ( ! b - > so_handle ) {
return NULL ;
}
fns = ( struct nwrap_module_nss_fns * ) malloc ( sizeof ( struct nwrap_module_nss_fns ) ) ;
if ( ! fns ) {
return NULL ;
}
2014-01-31 18:57:43 +04:00
* ( 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 " ) ;
2009-06-04 13:59:32 +04:00
return fns ;
}
static void * nwrap_load_module ( const char * so_path )
{
void * h ;
if ( ! so_path | | ! strlen ( so_path ) ) {
return NULL ;
}
h = dlopen ( so_path , RTLD_LAZY ) ;
if ( ! h ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Cannot open shared library %s " ,
so_path ) ;
2009-06-04 13:59:32 +04:00
return NULL ;
}
return h ;
}
2009-06-03 13:10:13 +04:00
static bool nwrap_module_init ( const char * name ,
struct nwrap_ops * ops ,
2009-06-04 13:59:32 +04:00
const char * so_path ,
2009-06-03 13:10:13 +04:00
int * num_backends ,
struct nwrap_backend * * backends )
{
2011-02-24 01:17:58 +03:00
struct nwrap_backend * b ;
2009-06-03 13:10:13 +04:00
* backends = ( struct nwrap_backend * ) realloc ( * backends ,
sizeof ( struct nwrap_backend ) * ( ( * num_backends ) + 1 ) ) ;
if ( ! * backends ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Out of memory " ) ;
2009-06-06 01:10:58 +04:00
return false ;
2009-06-03 13:10:13 +04:00
}
2011-02-24 01:17:58 +03:00
b = & ( ( * backends ) [ * num_backends ] ) ;
b - > name = name ;
b - > ops = ops ;
b - > so_path = so_path ;
2011-02-24 01:20:27 +03:00
if ( so_path ! = NULL ) {
b - > so_handle = nwrap_load_module ( so_path ) ;
b - > fns = nwrap_load_module_fns ( b ) ;
if ( b - > fns = = NULL ) {
return false ;
}
} else {
b - > so_handle = NULL ;
b - > fns = NULL ;
}
2009-06-03 13:10:13 +04:00
( * num_backends ) + + ;
return true ;
}
2014-01-31 18:57:43 +04:00
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 ) ;
}
2009-06-03 13:10:13 +04:00
static void nwrap_backend_init ( struct nwrap_main * r )
{
2014-01-31 18:57:43 +04:00
const char * module_so_path = getenv ( " NSS_WRAPPER_MODULE_SO_PATH " ) ;
const char * module_fn_name = getenv ( " NSS_WRAPPER_MODULE_FN_PREFIX " ) ;
2009-06-04 14:26:55 +04:00
2009-06-03 13:10:13 +04:00
r - > num_backends = 0 ;
r - > backends = NULL ;
2009-06-04 13:59:32 +04:00
if ( ! nwrap_module_init ( " files " , & nwrap_files_ops , NULL ,
2009-06-03 13:10:13 +04:00
& r - > num_backends ,
& r - > backends ) ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Failed to initialize 'files' backend " ) ;
2009-06-03 13:10:13 +04:00
return ;
}
2009-06-04 14:26:55 +04:00
2014-01-31 18:57:43 +04:00
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 ,
2009-06-04 14:26:55 +04:00
& r - > num_backends ,
& r - > backends ) ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Failed to initialize '%s' backend " ,
module_fn_name ) ;
2009-06-04 14:26:55 +04:00
return ;
}
}
2009-06-03 13:10:13 +04:00
}
2007-11-05 18:39:46 +03:00
static void nwrap_init ( void )
{
2015-07-15 16:01:48 +03:00
const char * env ;
char * endptr ;
size_t max_hostents_tmp ;
2007-11-05 18:39:46 +03:00
2015-03-24 19:54:34 +03:00
NWRAP_LOCK ( nwrap_initialized ) ;
if ( nwrap_initialized ) {
NWRAP_UNLOCK ( nwrap_initialized ) ;
return ;
}
/*
* Still holding nwrap_initialized lock here .
* We don ' t use NWRAP_ ( UN ) LOCK_ALL macros here because we
* want to avoid overhead when other threads do their job .
*/
NWRAP_LOCK ( nwrap_global ) ;
NWRAP_LOCK ( nwrap_gr_global ) ;
NWRAP_LOCK ( nwrap_he_global ) ;
NWRAP_LOCK ( nwrap_pw_global ) ;
NWRAP_LOCK ( nwrap_sp_global ) ;
nwrap_initialized = true ;
/* Initialize pthread_atfork handlers */
pthread_atfork ( & nwrap_thread_prepare , & nwrap_thread_parent ,
& nwrap_thread_child ) ;
2007-11-05 18:39:46 +03:00
2015-07-15 16:01:48 +03:00
env = getenv ( " NSS_WRAPPER_MAX_HOSTENTS " ) ;
if ( env ! = NULL ) {
max_hostents_tmp = ( size_t ) strtol ( env , & endptr , 10 ) ;
if ( ( ( env ! = ' \0 ' ) & & ( endptr = = ' \0 ' ) ) | |
( max_hostents_tmp = = 0 ) ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Error parsing NSS_WRAPPER_MAX_HOSTENTS "
" value or value is too small. "
" Using default value: %lu. " ,
2015-11-16 12:19:27 +03:00
( unsigned long ) max_hostents ) ;
2015-07-15 16:01:48 +03:00
} else {
max_hostents = max_hostents_tmp ;
}
}
/* Initialize hash table */
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
2015-11-16 12:19:27 +03:00
" Initializing hash table of size %lu items. " ,
( unsigned long ) max_hostents ) ;
2015-07-15 16:01:48 +03:00
if ( hcreate ( max_hostents ) = = 0 ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Failed to initialize hash table " ) ;
2015-03-24 19:54:34 +03:00
goto done ;
2015-07-15 16:01:48 +03:00
}
2009-05-31 03:01:13 +04:00
nwrap_main_global = & __nwrap_main_global ;
2014-01-31 18:57:43 +04:00
nwrap_libc_init ( nwrap_main_global ) ;
2009-06-03 13:10:13 +04:00
nwrap_backend_init ( nwrap_main_global ) ;
2009-05-31 03:01:13 +04:00
2015-09-17 11:33:58 +03:00
/* passwd */
2007-11-05 18:39:46 +03:00
nwrap_pw_global . cache = & __nwrap_cache_pw ;
nwrap_pw_global . cache - > path = getenv ( " NSS_WRAPPER_PASSWD " ) ;
2015-03-23 16:39:28 +03:00
nwrap_pw_global . cache - > fp = NULL ;
2007-11-05 18:39:46 +03:00
nwrap_pw_global . cache - > fd = - 1 ;
nwrap_pw_global . cache - > private_data = & nwrap_pw_global ;
nwrap_pw_global . cache - > parse_line = nwrap_pw_parse_line ;
nwrap_pw_global . cache - > unload = nwrap_pw_unload ;
2007-11-05 18:41:23 +03:00
2015-09-17 11:33:58 +03:00
/* shadow */
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2015-09-17 11:33:58 +03:00
nwrap_sp_global . cache = & __nwrap_cache_sp ;
nwrap_sp_global . cache - > path = getenv ( " NSS_WRAPPER_SHADOW " ) ;
2015-03-23 16:39:28 +03:00
nwrap_sp_global . cache - > fp = NULL ;
2015-09-17 11:33:58 +03:00
nwrap_sp_global . cache - > fd = - 1 ;
nwrap_sp_global . cache - > private_data = & nwrap_sp_global ;
nwrap_sp_global . cache - > parse_line = nwrap_sp_parse_line ;
nwrap_sp_global . cache - > unload = nwrap_sp_unload ;
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-09-17 11:33:58 +03:00
/* group */
2007-11-05 18:41:23 +03:00
nwrap_gr_global . cache = & __nwrap_cache_gr ;
nwrap_gr_global . cache - > path = getenv ( " NSS_WRAPPER_GROUP " ) ;
2015-03-23 16:39:28 +03:00
nwrap_gr_global . cache - > fp = NULL ;
2007-11-05 18:41:23 +03:00
nwrap_gr_global . cache - > fd = - 1 ;
nwrap_gr_global . cache - > private_data = & nwrap_gr_global ;
nwrap_gr_global . cache - > parse_line = nwrap_gr_parse_line ;
nwrap_gr_global . cache - > unload = nwrap_gr_unload ;
2014-01-31 18:57:43 +04:00
2015-09-17 11:33:58 +03:00
/* hosts */
2014-01-31 18:57:43 +04:00
nwrap_he_global . cache = & __nwrap_cache_he ;
nwrap_he_global . cache - > path = getenv ( " NSS_WRAPPER_HOSTS " ) ;
2015-03-23 16:39:28 +03:00
nwrap_he_global . cache - > fp = NULL ;
2014-01-31 18:57:43 +04:00
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 ;
2015-03-24 19:54:34 +03:00
done :
/* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
NWRAP_UNLOCK_ALL ;
2007-11-05 18:39:46 +03:00
}
2014-01-31 18:57:43 +04:00
bool nss_wrapper_enabled ( void )
2007-11-05 18:39:46 +03:00
{
nwrap_init ( ) ;
2014-01-31 18:57:43 +04:00
if ( nwrap_pw_global . cache - > path = = NULL | |
nwrap_pw_global . cache - > path [ 0 ] = = ' \0 ' ) {
2007-11-05 18:41:23 +03:00
return false ;
}
2014-01-31 18:57:43 +04:00
if ( nwrap_gr_global . cache - > path = = NULL | |
nwrap_gr_global . cache - > path [ 0 ] = = ' \0 ' ) {
2007-11-05 18:41:23 +03:00
return false ;
}
2007-11-05 18:39:46 +03:00
return true ;
}
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2015-09-17 11:37:50 +03:00
bool nss_wrapper_shadow_enabled ( void )
{
nwrap_init ( ) ;
if ( nwrap_sp_global . cache - > path = = NULL | |
nwrap_sp_global . cache - > path [ 0 ] = = ' \0 ' ) {
return false ;
}
return true ;
}
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-09-17 11:37:50 +03:00
2014-01-31 18:57:43 +04:00
bool nss_wrapper_hosts_enabled ( void )
2007-11-05 18:39:46 +03:00
{
2014-01-31 18:57:43 +04:00
nwrap_init ( ) ;
2007-11-05 18:39:46 +03:00
2014-01-31 18:57:43 +04:00
if ( nwrap_he_global . cache - > path = = NULL | |
nwrap_he_global . cache - > path [ 0 ] = = ' \0 ' ) {
return false ;
}
return true ;
}
static bool nwrap_hostname_enabled ( void )
{
nwrap_init ( ) ;
if ( getenv ( " NSS_WRAPPER_HOSTNAME " ) = = NULL ) {
return false ;
}
return true ;
}
static bool nwrap_parse_file ( struct nwrap_cache * nwrap )
{
2015-03-23 16:39:28 +03:00
char * line = NULL ;
ssize_t n ;
/* Unused but getline needs it */
size_t len ;
bool ok ;
2014-01-31 18:57:43 +04:00
if ( nwrap - > st . st_size = = 0 ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG , " size == 0 " ) ;
2015-03-23 16:39:28 +03:00
return true ;
2007-11-05 18:39:46 +03:00
}
2015-03-23 16:39:28 +03:00
/* Support for 32-bit system I guess */
2007-11-05 18:39:46 +03:00
if ( nwrap - > st . st_size > INT32_MAX ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Size[%u] larger than INT32_MAX " ,
( unsigned ) nwrap - > st . st_size ) ;
2015-03-23 16:39:28 +03:00
return false ;
2007-11-05 18:39:46 +03:00
}
2015-03-23 16:39:28 +03:00
rewind ( nwrap - > fp ) ;
2007-11-05 18:39:46 +03:00
2015-03-23 16:39:28 +03:00
do {
n = getline ( & line , & len , nwrap - > fp ) ;
if ( n < 0 ) {
2015-10-08 12:36:33 +03:00
SAFE_FREE ( line ) ;
2015-03-23 16:39:28 +03:00
if ( feof ( nwrap - > fp ) ) {
break ;
}
2007-11-05 18:39:46 +03:00
2015-03-23 16:39:28 +03:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to read line from file: %s " ,
nwrap - > path ) ;
return false ;
}
2007-11-05 18:39:46 +03:00
2015-03-23 16:39:28 +03:00
if ( line [ n - 1 ] = = ' \n ' ) {
line [ n - 1 ] = ' \0 ' ;
2007-11-05 18:39:46 +03:00
}
2015-03-23 16:39:28 +03:00
if ( line [ 0 ] = = ' \0 ' ) {
SAFE_FREE ( line ) ;
2007-11-05 18:39:46 +03:00
continue ;
}
ok = nwrap - > parse_line ( nwrap , line ) ;
if ( ! ok ) {
2015-03-23 16:39:28 +03:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to parse line file: %s " ,
line ) ;
SAFE_FREE ( line ) ;
return false ;
2007-11-05 18:39:46 +03:00
}
2015-03-23 16:39:28 +03:00
/* Line is parsed without issues so add it to list */
ok = nwrap_vector_add_item ( & ( nwrap - > lines ) , ( void * const ) line ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to add line to vector " ) ;
return false ;
}
/* This forces getline to allocate new memory for line. */
line = NULL ;
} while ( ! feof ( nwrap - > fp ) ) ;
2007-11-05 18:39:46 +03:00
2015-03-23 16:39:28 +03:00
return true ;
2007-11-05 18:39:46 +03:00
}
2009-06-06 03:14:04 +04:00
static void nwrap_files_cache_unload ( struct nwrap_cache * nwrap )
2007-11-05 18:39:46 +03:00
{
nwrap - > unload ( nwrap ) ;
2015-03-23 16:39:28 +03:00
nwrap_lines_unload ( nwrap ) ;
2007-11-05 18:39:46 +03:00
}
2015-11-11 14:33:12 +03:00
static bool nwrap_files_cache_reload ( struct nwrap_cache * nwrap )
2007-11-05 18:39:46 +03:00
{
struct stat st ;
int ret ;
bool ok ;
bool retried = false ;
2015-03-23 16:39:28 +03:00
assert ( nwrap ! = NULL ) ;
2007-11-05 18:39:46 +03:00
reopen :
if ( nwrap - > fd < 0 ) {
2015-03-23 16:39:28 +03:00
nwrap - > fp = fopen ( nwrap - > path , " re " ) ;
if ( nwrap - > fp = = NULL ) {
nwrap - > fd = - 1 ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to open '%s' readonly %d:%s " ,
nwrap - > path , nwrap - > fd ,
strerror ( errno ) ) ;
2015-11-11 14:33:12 +03:00
return false ;
2015-03-23 16:39:28 +03:00
2007-11-05 18:39:46 +03:00
}
2015-03-23 16:39:28 +03:00
nwrap - > fd = fileno ( nwrap - > fp ) ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Open '%s' " , nwrap - > path ) ;
2007-11-05 18:39:46 +03:00
}
ret = fstat ( nwrap - > fd , & st ) ;
if ( ret ! = 0 ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" fstat(%s) - %d:%s " ,
nwrap - > path ,
ret ,
strerror ( errno ) ) ;
2015-03-23 16:39:28 +03:00
fclose ( nwrap - > fp ) ;
nwrap - > fp = NULL ;
nwrap - > fd = - 1 ;
2015-11-11 14:33:12 +03:00
return false ;
2007-11-05 18:39:46 +03:00
}
if ( retried = = false & & st . st_nlink = = 0 ) {
/* maybe someone has replaced the file... */
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE ,
" st_nlink == 0, reopen %s " ,
nwrap - > path ) ;
2007-11-05 18:39:46 +03:00
retried = true ;
memset ( & nwrap - > st , 0 , sizeof ( nwrap - > st ) ) ;
2015-03-23 16:39:28 +03:00
fclose ( nwrap - > fp ) ;
nwrap - > fp = NULL ;
2007-11-05 18:39:46 +03:00
nwrap - > fd = - 1 ;
goto reopen ;
}
if ( st . st_mtime = = nwrap - > st . st_mtime ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE ,
" st_mtime[%u] hasn't changed, skip reload " ,
( unsigned ) st . st_mtime ) ;
2015-11-11 14:33:12 +03:00
return true ;
2007-11-05 18:39:46 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE ,
" st_mtime has changed [%u] => [%u], start reload " ,
( unsigned ) st . st_mtime ,
( unsigned ) nwrap - > st . st_mtime ) ;
2007-11-05 18:39:46 +03:00
nwrap - > st = st ;
2009-06-06 03:14:04 +04:00
nwrap_files_cache_unload ( nwrap ) ;
2007-11-05 18:39:46 +03:00
ok = nwrap_parse_file ( nwrap ) ;
if ( ! ok ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Failed to reload %s " , nwrap - > path ) ;
2009-06-06 03:14:04 +04:00
nwrap_files_cache_unload ( nwrap ) ;
2015-11-11 14:33:12 +03:00
return false ;
2007-11-05 18:39:46 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " Reloaded %s " , nwrap - > path ) ;
2015-11-11 14:33:12 +03:00
return true ;
2007-11-05 18:39:46 +03:00
}
/*
* the caller has to call nwrap_unload ( ) on failure
*/
static bool nwrap_pw_parse_line ( struct nwrap_cache * nwrap , char * line )
{
struct nwrap_pw * nwrap_pw ;
char * c ;
char * p ;
char * e ;
struct passwd * pw ;
size_t list_size ;
nwrap_pw = ( struct nwrap_pw * ) nwrap - > private_data ;
list_size = sizeof ( * nwrap_pw - > list ) * ( nwrap_pw - > num + 1 ) ;
pw = ( struct passwd * ) realloc ( nwrap_pw - > list , list_size ) ;
if ( ! pw ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" realloc(%u) failed " ,
( unsigned ) list_size ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
nwrap_pw - > list = pw ;
pw = & nwrap_pw - > list [ nwrap_pw - > num ] ;
c = line ;
/* name */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' " ,
line ,
c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
pw - > pw_name = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " name[%s] \n " , pw - > pw_name ) ;
2007-11-05 18:39:46 +03:00
/* password */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
pw - > pw_passwd = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " password[%s] \n " , pw - > pw_passwd ) ;
2007-11-05 18:39:46 +03:00
/* uid */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
e = NULL ;
pw - > pw_uid = ( uid_t ) strtoul ( c , & e , 10 ) ;
if ( c = = e ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
if ( e = = NULL ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " uid[%u] " , pw - > pw_uid ) ;
2007-11-05 18:39:46 +03:00
/* gid */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
e = NULL ;
pw - > pw_gid = ( gid_t ) strtoul ( c , & e , 10 ) ;
if ( c = = e ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
if ( e = = NULL ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " gid[%u] \n " , pw - > pw_gid ) ;
2007-11-05 18:39:46 +03:00
/* gecos */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
pw - > pw_gecos = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " gecos[%s] " , pw - > pw_gecos ) ;
2007-11-05 18:39:46 +03:00
/* dir */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " '%s' " , c ) ;
2007-11-05 18:39:46 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
pw - > pw_dir = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " dir[%s] " , pw - > pw_dir ) ;
2007-11-05 18:39:46 +03:00
/* shell */
pw - > pw_shell = c ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " shell[%s] " , pw - > pw_shell ) ;
2007-11-05 18:39:46 +03:00
2014-01-31 18:57:43 +04:00
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 ) ;
2007-11-05 18:39:46 +03:00
nwrap_pw - > num + + ;
return true ;
}
static void nwrap_pw_unload ( struct nwrap_cache * nwrap )
{
struct nwrap_pw * nwrap_pw ;
nwrap_pw = ( struct nwrap_pw * ) nwrap - > private_data ;
2014-11-29 15:22:46 +03:00
SAFE_FREE ( nwrap_pw - > list ) ;
2007-11-05 18:39:46 +03:00
nwrap_pw - > num = 0 ;
nwrap_pw - > idx = 0 ;
}
static int nwrap_pw_copy_r ( const struct passwd * src , struct passwd * dst ,
2007-11-06 15:11:35 +03:00
char * buf , size_t buflen , struct passwd * * dstp )
2007-11-05 18:39:46 +03:00
{
char * first ;
char * last ;
off_t ofs ;
first = src - > pw_name ;
last = src - > pw_shell ;
while ( * last ) last + + ;
ofs = PTR_DIFF ( last + 1 , first ) ;
2014-01-31 18:57:43 +04:00
if ( ofs > ( off_t ) buflen ) {
2007-11-05 18:39:46 +03:00
return ERANGE ;
}
memcpy ( buf , first , ofs ) ;
ofs = PTR_DIFF ( src - > pw_name , first ) ;
dst - > pw_name = buf + ofs ;
ofs = PTR_DIFF ( src - > pw_passwd , first ) ;
dst - > pw_passwd = buf + ofs ;
dst - > pw_uid = src - > pw_uid ;
dst - > pw_gid = src - > pw_gid ;
ofs = PTR_DIFF ( src - > pw_gecos , first ) ;
dst - > pw_gecos = buf + ofs ;
ofs = PTR_DIFF ( src - > pw_dir , first ) ;
dst - > pw_dir = buf + ofs ;
ofs = PTR_DIFF ( src - > pw_shell , first ) ;
dst - > pw_shell = buf + ofs ;
2007-11-06 15:11:35 +03:00
if ( dstp ) {
* dstp = dst ;
}
2007-11-05 18:39:46 +03:00
return 0 ;
}
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2015-09-17 11:33:58 +03:00
static bool nwrap_sp_parse_line ( struct nwrap_cache * nwrap , char * line )
{
struct nwrap_sp * nwrap_sp ;
struct spwd * sp ;
size_t list_size ;
char * c ;
char * e ;
char * p ;
nwrap_sp = ( struct nwrap_sp * ) nwrap - > private_data ;
list_size = sizeof ( * nwrap_sp - > list ) * ( nwrap_sp - > num + 1 ) ;
sp = ( struct spwd * ) realloc ( nwrap_sp - > list , list_size ) ;
if ( sp = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" realloc(%u) failed " ,
( unsigned ) list_size ) ;
return false ;
}
nwrap_sp - > list = sp ;
sp = & nwrap_sp - > list [ nwrap_sp - > num ] ;
c = line ;
/* name */
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" name -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_namp = c ;
c = p ;
NWRAP_LOG ( NWRAP_LOG_TRACE , " name[%s] \n " , sp - > sp_namp ) ;
/* pwd */
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" pwd -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_pwdp = c ;
c = p ;
/* lstchg (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_lstchg = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" lstchg -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_lstchg = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" lstchg -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" lstchg -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" lstchg -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
/* min (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_min = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" min -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_min = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" min -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" min -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" min -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
/* max (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_max = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" max -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_max = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" max -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" max -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" max -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
/* warn (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_warn = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" warn -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_warn = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" warn -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" warn -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" warn -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
/* inact (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_inact = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" inact -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_inact = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" inact -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" inact -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" inact -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
/* expire (long) */
if ( c [ 0 ] = = ' : ' ) {
sp - > sp_expire = - 1 ;
p + + ;
} else {
p = strchr ( c , ' : ' ) ;
if ( p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" expire -- Invalid line[%s]: '%s' " ,
line ,
c ) ;
return false ;
}
* p = ' \0 ' ;
p + + ;
sp - > sp_expire = strtol ( c , & e , 10 ) ;
if ( c = = e ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" expire -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" expire -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" expire -- Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
return false ;
}
}
c = p ;
nwrap_sp - > num + + ;
return true ;
}
static void nwrap_sp_unload ( struct nwrap_cache * nwrap )
{
struct nwrap_sp * nwrap_sp ;
nwrap_sp = ( struct nwrap_sp * ) nwrap - > private_data ;
SAFE_FREE ( nwrap_sp - > list ) ;
nwrap_sp - > num = 0 ;
nwrap_sp - > idx = 0 ;
}
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-09-17 11:33:58 +03:00
2007-11-05 18:41:23 +03:00
/*
* the caller has to call nwrap_unload ( ) on failure
*/
static bool nwrap_gr_parse_line ( struct nwrap_cache * nwrap , char * line )
{
struct nwrap_gr * nwrap_gr ;
char * c ;
char * p ;
char * e ;
struct group * gr ;
size_t list_size ;
unsigned nummem ;
nwrap_gr = ( struct nwrap_gr * ) nwrap - > private_data ;
list_size = sizeof ( * nwrap_gr - > list ) * ( nwrap_gr - > num + 1 ) ;
gr = ( struct group * ) realloc ( nwrap_gr - > list , list_size ) ;
if ( ! gr ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " realloc failed " ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
nwrap_gr - > list = gr ;
gr = & nwrap_gr - > list [ nwrap_gr - > num ] ;
c = line ;
/* name */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
gr - > gr_name = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " name[%s] " , gr - > gr_name ) ;
2007-11-05 18:41:23 +03:00
/* password */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
gr - > gr_passwd = c ;
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " password[%s] " , gr - > gr_passwd ) ;
2007-11-05 18:41:23 +03:00
/* gid */
p = strchr ( c , ' : ' ) ;
if ( ! p ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Invalid line[%s]: '%s' " , line , c ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
* p = ' \0 ' ;
p + + ;
e = NULL ;
gr - > gr_gid = ( gid_t ) strtoul ( c , & e , 10 ) ;
if ( c = = e ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
if ( e = = NULL ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
if ( e [ 0 ] ! = ' \0 ' ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' - %s " ,
line , c , strerror ( errno ) ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
c = p ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE , " gid[%u] " , gr - > gr_gid ) ;
2007-11-05 18:41:23 +03:00
/* members */
gr - > gr_mem = ( char * * ) malloc ( sizeof ( char * ) ) ;
if ( ! gr - > gr_mem ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Out of memory " ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
gr - > gr_mem [ 0 ] = NULL ;
for ( nummem = 0 ; p ; nummem + + ) {
char * * m ;
size_t m_size ;
c = p ;
p = strchr ( c , ' , ' ) ;
if ( p ) {
* p = ' \0 ' ;
p + + ;
}
if ( strlen ( c ) = = 0 ) {
break ;
}
m_size = sizeof ( char * ) * ( nummem + 2 ) ;
m = ( char * * ) realloc ( gr - > gr_mem , m_size ) ;
if ( ! m ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" realloc(%zd) failed " ,
m_size ) ;
2007-11-05 18:41:23 +03:00
return false ;
}
gr - > gr_mem = m ;
gr - > gr_mem [ nummem ] = c ;
gr - > gr_mem [ nummem + 1 ] = NULL ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_TRACE ,
" member[%u]: '%s' " ,
nummem , gr - > gr_mem [ nummem ] ) ;
2007-11-05 18:41:23 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Added group[%s:%s:%u:] with %u members " ,
gr - > gr_name , gr - > gr_passwd , gr - > gr_gid , nummem ) ;
2007-11-05 18:41:23 +03:00
nwrap_gr - > num + + ;
return true ;
}
static void nwrap_gr_unload ( struct nwrap_cache * nwrap )
{
int i ;
struct nwrap_gr * nwrap_gr ;
nwrap_gr = ( struct nwrap_gr * ) nwrap - > private_data ;
if ( nwrap_gr - > list ) {
for ( i = 0 ; i < nwrap_gr - > num ; i + + ) {
2014-11-29 15:22:46 +03:00
SAFE_FREE ( nwrap_gr - > list [ i ] . gr_mem ) ;
2007-11-05 18:41:23 +03:00
}
2014-11-29 15:22:46 +03:00
SAFE_FREE ( nwrap_gr - > list ) ;
2007-11-05 18:41:23 +03:00
}
nwrap_gr - > num = 0 ;
nwrap_gr - > idx = 0 ;
}
static int nwrap_gr_copy_r ( const struct group * src , struct group * dst ,
2007-11-06 15:11:35 +03:00
char * buf , size_t buflen , struct group * * dstp )
2007-11-05 18:41:23 +03:00
{
char * first ;
char * * lastm ;
2009-06-05 17:41:46 +04:00
char * last = NULL ;
2007-11-05 18:41:23 +03:00
off_t ofsb ;
off_t ofsm ;
off_t ofs ;
unsigned i ;
first = src - > gr_name ;
lastm = src - > gr_mem ;
2009-06-05 17:41:46 +04:00
while ( * lastm ) {
last = * lastm ;
lastm + + ;
}
2007-11-05 18:41:23 +03:00
2009-06-05 17:41:46 +04:00
if ( last = = NULL ) {
last = src - > gr_passwd ;
}
2007-11-05 18:41:23 +03:00
while ( * last ) last + + ;
ofsb = PTR_DIFF ( last + 1 , first ) ;
ofsm = PTR_DIFF ( lastm + 1 , src - > gr_mem ) ;
2014-01-31 18:57:43 +04:00
if ( ( ofsb + ofsm ) > ( off_t ) buflen ) {
2007-11-05 18:41:23 +03:00
return ERANGE ;
}
memcpy ( buf , first , ofsb ) ;
memcpy ( buf + ofsb , src - > gr_mem , ofsm ) ;
ofs = PTR_DIFF ( src - > gr_name , first ) ;
dst - > gr_name = buf + ofs ;
ofs = PTR_DIFF ( src - > gr_passwd , first ) ;
dst - > gr_passwd = buf + ofs ;
dst - > gr_gid = src - > gr_gid ;
dst - > gr_mem = ( char * * ) ( buf + ofsb ) ;
for ( i = 0 ; src - > gr_mem [ i ] ; i + + ) {
ofs = PTR_DIFF ( src - > gr_mem [ i ] , first ) ;
dst - > gr_mem [ i ] = buf + ofs ;
}
2007-11-06 15:11:35 +03:00
if ( dstp ) {
* dstp = dst ;
}
2007-11-05 18:41:23 +03:00
return 0 ;
}
2015-11-11 12:27:50 +03:00
static struct nwrap_entlist * nwrap_entlist_init ( struct nwrap_entdata * ed )
{
struct nwrap_entlist * el ;
if ( ed = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" entry is NULL, can't create list item " ) ;
return NULL ;
}
el = ( struct nwrap_entlist * ) malloc ( sizeof ( struct nwrap_entlist ) ) ;
if ( el = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " malloc failed " ) ;
return NULL ;
}
el - > next = NULL ;
el - > ed = ed ;
return el ;
}
2015-11-12 10:29:57 +03:00
static bool nwrap_ed_inventarize_add_new ( char * const h_name ,
struct nwrap_entdata * const ed )
2015-07-15 16:05:28 +03:00
{
ENTRY e ;
ENTRY * p ;
2015-11-11 12:27:50 +03:00
struct nwrap_entlist * el ;
2015-11-19 03:00:16 +03:00
bool ok ;
2015-11-11 12:27:50 +03:00
2015-11-11 14:25:30 +03:00
if ( h_name = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " h_name NULL - can't add " ) ;
return false ;
}
2015-11-11 12:27:50 +03:00
el = nwrap_entlist_init ( ed ) ;
if ( el = = NULL ) {
return false ;
}
2015-07-15 16:05:28 +03:00
e . key = h_name ;
2015-11-11 12:27:50 +03:00
e . data = ( void * ) el ;
2015-07-15 16:05:28 +03:00
p = hsearch ( e , ENTER ) ;
if ( p = = NULL ) {
2015-11-11 13:30:13 +03:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Hash table is full! " ) ;
2015-07-15 16:05:28 +03:00
return false ;
}
2015-11-19 03:00:16 +03:00
ok = nwrap_vector_add_item ( & ( nwrap_he_global . lists ) , ( void * ) el ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Failed to add list entry to vector. " ) ;
return false ;
}
2015-07-15 16:05:28 +03:00
return true ;
}
2015-11-12 10:29:57 +03:00
static bool nwrap_ed_inventarize_add_to_existing ( struct nwrap_entdata * const ed ,
struct nwrap_entlist * const el )
2015-07-15 16:05:28 +03:00
{
2015-11-11 12:27:50 +03:00
struct nwrap_entlist * cursor ;
struct nwrap_entlist * el_new ;
2015-11-11 14:26:02 +03:00
if ( el = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " list is NULL, can not add " ) ;
return false ;
}
2015-11-11 12:27:50 +03:00
for ( cursor = el ; cursor - > next ! = NULL ; cursor = cursor - > next )
{
if ( cursor - > ed = = ed ) {
2015-11-24 19:32:47 +03:00
/* The entry already exists in this list. */
return true ;
2015-07-15 16:05:28 +03:00
}
}
2015-11-11 12:27:50 +03:00
if ( cursor - > ed = = ed ) {
2015-11-24 19:32:47 +03:00
/* The entry already exists in this list. */
return true ;
2015-11-17 01:38:51 +03:00
}
el_new = nwrap_entlist_init ( ed ) ;
if ( el_new = = NULL ) {
2015-11-11 13:56:59 +03:00
return false ;
2015-11-11 12:27:50 +03:00
}
cursor - > next = el_new ;
2015-11-11 13:56:59 +03:00
return true ;
2015-07-15 16:05:28 +03:00
}
2015-11-12 10:29:57 +03:00
static bool nwrap_ed_inventarize ( char * const name ,
struct nwrap_entdata * const ed )
2015-07-15 16:05:28 +03:00
{
ENTRY e ;
ENTRY * p ;
2015-11-11 14:27:33 +03:00
bool ok ;
2015-07-15 16:05:28 +03:00
2015-11-12 10:29:57 +03:00
e . key = name ;
2015-07-15 16:05:28 +03:00
e . data = NULL ;
2015-11-12 10:29:57 +03:00
2015-07-15 16:05:28 +03:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Searching name: %s " , e . key ) ;
2015-11-12 10:29:57 +03:00
2015-07-15 16:05:28 +03:00
p = hsearch ( e , FIND ) ;
if ( p = = NULL ) {
2015-11-12 10:29:57 +03:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Name %s not found. Adding... " , name ) ;
ok = nwrap_ed_inventarize_add_new ( name , ed ) ;
2015-07-15 16:05:28 +03:00
} else {
2015-11-11 12:27:50 +03:00
struct nwrap_entlist * el = ( struct nwrap_entlist * ) p - > data ;
2015-07-15 16:05:28 +03:00
2015-11-12 10:29:57 +03:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Name %s found. Add record to list. " , name ) ;
ok = nwrap_ed_inventarize_add_to_existing ( ed , el ) ;
2015-07-15 16:05:28 +03:00
}
2015-11-11 14:27:33 +03:00
return ok ;
2015-07-15 16:05:28 +03:00
}
2015-11-09 19:36:37 +03:00
static bool nwrap_add_hname ( struct nwrap_entdata * const ed )
2015-07-15 16:05:28 +03:00
{
2015-11-09 19:36:37 +03:00
char * const h_name = ( char * const ) ( ed - > ht . h_name ) ;
2015-07-15 16:05:28 +03:00
unsigned i ;
2015-11-11 14:28:58 +03:00
bool ok ;
2015-07-15 16:05:28 +03:00
2015-11-12 10:29:57 +03:00
ok = nwrap_ed_inventarize ( h_name , ed ) ;
2015-11-11 14:28:58 +03:00
if ( ! ok ) {
return false ;
2015-07-15 16:05:28 +03:00
}
if ( ed - > ht . h_aliases = = NULL ) {
return true ;
}
/* Itemize aliases */
for ( i = 0 ; ed - > ht . h_aliases [ i ] ! = NULL ; + + i ) {
2015-11-09 19:41:43 +03:00
char * h_name_alias ;
2015-07-15 16:05:28 +03:00
h_name_alias = ed - > ht . h_aliases [ i ] ;
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Add alias: %s " , h_name_alias ) ;
2015-11-12 10:29:57 +03:00
if ( ! nwrap_ed_inventarize ( h_name_alias , ed ) ) {
2015-11-11 14:29:55 +03:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
2015-07-15 16:05:28 +03:00
" Unable to add alias: %s " , h_name_alias ) ;
2015-11-11 14:28:58 +03:00
return false ;
2015-07-15 16:05:28 +03:00
}
}
return true ;
}
2014-01-31 18:57:43 +04:00
static bool nwrap_he_parse_line ( struct nwrap_cache * nwrap , char * line )
{
struct nwrap_he * nwrap_he = ( struct nwrap_he * ) nwrap - > private_data ;
bool do_aliases = true ;
2015-07-15 16:00:02 +03:00
ssize_t aliases_count = 0 ;
2014-01-31 18:57:43 +04:00
char * p ;
char * i ;
char * n ;
2015-07-16 17:10:20 +03:00
char * ip ;
2015-11-11 14:30:36 +03:00
bool ok ;
2014-01-31 18:57:43 +04:00
2015-07-16 17:10:20 +03:00
struct nwrap_entdata * ed = ( struct nwrap_entdata * )
malloc ( sizeof ( struct nwrap_entdata ) ) ;
2014-01-31 18:57:43 +04:00
if ( ed = = NULL ) {
2015-07-16 17:10:20 +03:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to allocate memory for nwrap_entdata " ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
2015-07-16 17:10:20 +03:00
ZERO_STRUCTP ( ed ) ;
2014-01-31 18:57:43 +04:00
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 ) ;
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
}
for ( i = p ; ! isspace ( ( int ) * p ) ; p + + ) {
if ( * p = = ' \0 ' ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' " ,
line , i ) ;
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
}
* p = ' \0 ' ;
2015-07-16 17:10:20 +03:00
if ( inet_pton ( AF_INET , i , ed - > addr . host_addr ) ) {
2014-01-31 18:57:43 +04:00
ed - > ht . h_addrtype = AF_INET ;
ed - > ht . h_length = 4 ;
# ifdef HAVE_IPV6
2015-07-16 17:10:20 +03:00
} else if ( inet_pton ( AF_INET6 , i , ed - > addr . host_addr ) ) {
2014-01-31 18:57:43 +04:00
ed - > ht . h_addrtype = AF_INET6 ;
ed - > ht . h_length = 16 ;
# endif
} else {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Invalid line[%s]: '%s' " ,
line , i ) ;
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
2015-07-16 17:10:20 +03:00
ip = i ;
2014-01-31 18:57:43 +04:00
2015-11-19 02:34:54 +03:00
ok = nwrap_vector_add_item ( & ( ed - > nwrap_addrdata ) ,
( void * const ) ed - > addr . host_addr ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Unable to add addrdata to vector " ) ;
free ( ed ) ;
return false ;
}
2015-07-16 17:10:20 +03:00
ed - > ht . h_addr_list = nwrap_vector_head ( & ed - > nwrap_addrdata ) ;
2014-01-31 18:57:43 +04:00
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 ) ;
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
}
for ( n = p ; ! isspace ( ( int ) * p ) ; p + + ) {
if ( * p = = ' \0 ' ) {
do_aliases = false ;
break ;
}
}
* p = ' \0 ' ;
2015-07-16 17:10:20 +03:00
/* Convert to lowercase. This operate on same memory region */
str_tolower ( n , n ) ;
2014-01-31 18:57:43 +04:00
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 ) {
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
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 ) {
2015-07-16 17:10:20 +03:00
free ( ed ) ;
2014-01-31 18:57:43 +04:00
return false ;
}
ed - > ht . h_aliases = aliases ;
2015-07-16 17:10:20 +03:00
str_tolower ( a , a ) ;
2014-01-31 18:57:43 +04:00
aliases [ aliases_count ] = a ;
aliases [ aliases_count + 1 ] = NULL ;
2015-07-16 17:10:20 +03:00
aliases_count + = 1 ;
2014-01-31 18:57:43 +04:00
}
2015-11-19 02:34:54 +03:00
ok = nwrap_vector_add_item ( & ( nwrap_he - > entries ) , ( void * const ) ed ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Unable to add entry to vector " ) ;
free ( ed ) ;
return false ;
}
2015-07-16 17:10:20 +03:00
ed - > aliases_count = aliases_count ;
/* Inventarize item */
2015-11-11 14:30:36 +03:00
ok = nwrap_add_hname ( ed ) ;
if ( ! ok ) {
return false ;
}
2015-11-12 10:34:39 +03:00
ok = nwrap_ed_inventarize ( ip , ed ) ;
2015-11-11 14:30:36 +03:00
if ( ! ok ) {
return false ;
}
2015-07-16 17:10:20 +03:00
2014-01-31 18:57:43 +04:00
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 ;
2015-07-16 17:10:20 +03:00
struct nwrap_entdata * ed ;
2015-11-19 03:00:16 +03:00
struct nwrap_entlist * el ;
2015-07-16 17:10:20 +03:00
size_t i ;
2015-12-17 10:46:33 +03:00
int rc ;
2014-01-31 18:57:43 +04:00
2015-11-19 02:30:17 +03:00
nwrap_vector_foreach ( ed , nwrap_he - > entries , i )
2015-07-16 17:10:20 +03:00
{
2015-10-08 16:00:33 +03:00
SAFE_FREE ( ed - > nwrap_addrdata . items ) ;
2015-07-16 17:10:20 +03:00
SAFE_FREE ( ed - > ht . h_aliases ) ;
SAFE_FREE ( ed ) ;
2014-01-31 18:57:43 +04:00
}
2015-11-19 02:30:17 +03:00
SAFE_FREE ( nwrap_he - > entries . items ) ;
nwrap_he - > entries . count = nwrap_he - > entries . capacity = 0 ;
2014-01-31 18:57:43 +04:00
2015-11-19 03:00:16 +03:00
nwrap_vector_foreach ( el , nwrap_he - > lists , i )
{
while ( el ! = NULL ) {
struct nwrap_entlist * el_next ;
el_next = el - > next ;
SAFE_FREE ( el ) ;
el = el_next ;
}
}
SAFE_FREE ( nwrap_he - > lists . items ) ;
nwrap_he - > lists . count = nwrap_he - > lists . capacity = 0 ;
2014-01-31 18:57:43 +04:00
nwrap_he - > num = 0 ;
nwrap_he - > idx = 0 ;
2015-12-17 10:46:33 +03:00
/*
* If we unload the file , the pointers in the hash table point to
* invalid memory . So we need to destroy the hash table and recreate
* it .
*/
hdestroy ( ) ;
rc = hcreate ( max_hostents ) ;
if ( rc = = 0 ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Failed to initialize hash table " ) ;
exit ( - 1 ) ;
}
2014-01-31 18:57:43 +04:00
}
2007-11-05 18:38:36 +03:00
/* user functions */
2009-06-03 13:10:13 +04:00
static struct passwd * nwrap_files_getpwnam ( struct nwrap_backend * b ,
const char * name )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:39:46 +03:00
int i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2007-11-05 18:39:46 +03:00
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Lookup user %s in files " , name ) ;
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_pw_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading passwd file " ) ;
return NULL ;
}
2007-11-05 18:39:46 +03:00
for ( i = 0 ; i < nwrap_pw_global . num ; i + + ) {
if ( strcmp ( nwrap_pw_global . list [ i ] . pw_name , name ) = = 0 ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " user[%s] found " , name ) ;
2007-11-05 18:39:46 +03:00
return & nwrap_pw_global . list [ i ] ;
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" user[%s] does not match [%s] " ,
name ,
nwrap_pw_global . list [ i ] . pw_name ) ;
2007-11-05 18:39:46 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " user[%s] not found \n " , name ) ;
2007-11-05 18:39:46 +03:00
errno = ENOENT ;
return NULL ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getpwnam_r ( struct nwrap_backend * b ,
const char * name , struct passwd * pwdst ,
2009-05-27 20:38:10 +04:00
char * buf , size_t buflen , struct passwd * * pwdstp )
{
struct passwd * pw ;
2009-06-03 13:10:13 +04:00
pw = nwrap_files_getpwnam ( b , name ) ;
2007-11-05 18:39:46 +03:00
if ( ! pw ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_pw_copy_r ( pw , pwdst , buf , buflen , pwdstp ) ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static struct passwd * nwrap_files_getpwuid ( struct nwrap_backend * b ,
uid_t uid )
2009-05-27 20:38:10 +04:00
{
int i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2009-05-27 20:38:10 +04:00
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_pw_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading passwd file " ) ;
return NULL ;
}
2007-11-05 18:39:46 +03:00
for ( i = 0 ; i < nwrap_pw_global . num ; i + + ) {
if ( nwrap_pw_global . list [ i ] . pw_uid = = uid ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " uid[%u] found " , uid ) ;
2007-11-05 18:39:46 +03:00
return & nwrap_pw_global . list [ i ] ;
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" uid[%u] does not match [%u] " ,
uid ,
nwrap_pw_global . list [ i ] . pw_uid ) ;
2007-11-05 18:39:46 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " uid[%u] not found \n " , uid ) ;
2007-11-05 18:39:46 +03:00
errno = ENOENT ;
return NULL ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getpwuid_r ( struct nwrap_backend * b ,
uid_t uid , struct passwd * pwdst ,
2009-05-27 20:38:10 +04:00
char * buf , size_t buflen , struct passwd * * pwdstp )
{
struct passwd * pw ;
2009-06-03 13:10:13 +04:00
pw = nwrap_files_getpwuid ( b , uid ) ;
2007-11-05 18:39:46 +03:00
if ( ! pw ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_pw_copy_r ( pw , pwdst , buf , buflen , pwdstp ) ;
2007-11-05 18:38:36 +03:00
}
/* user enum functions */
2009-06-03 13:10:13 +04:00
static void nwrap_files_setpwent ( struct nwrap_backend * b )
2009-05-27 20:38:10 +04:00
{
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2009-05-27 20:38:10 +04:00
nwrap_pw_global . idx = 0 ;
}
2009-06-03 13:10:13 +04:00
static struct passwd * nwrap_files_getpwent ( struct nwrap_backend * b )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:39:46 +03:00
struct passwd * pw ;
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2007-11-05 18:39:46 +03:00
if ( nwrap_pw_global . idx = = 0 ) {
2015-11-11 14:47:15 +03:00
bool ok ;
ok = nwrap_files_cache_reload ( nwrap_pw_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading passwd file " ) ;
return NULL ;
}
2007-11-05 18:39:46 +03:00
}
if ( nwrap_pw_global . idx > = nwrap_pw_global . num ) {
errno = ENOENT ;
return NULL ;
}
pw = & nwrap_pw_global . list [ nwrap_pw_global . idx + + ] ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" return user[%s] uid[%u] " ,
pw - > pw_name , pw - > pw_uid ) ;
2007-11-05 18:39:46 +03:00
return pw ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getpwent_r ( struct nwrap_backend * b ,
struct passwd * pwdst , char * buf ,
2009-05-27 20:38:10 +04:00
size_t buflen , struct passwd * * pwdstp )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:39:46 +03:00
struct passwd * pw ;
2009-06-03 13:10:13 +04:00
pw = nwrap_files_getpwent ( b ) ;
2009-05-27 20:38:10 +04:00
if ( ! pw ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_pw_copy_r ( pw , pwdst , buf , buflen , pwdstp ) ;
}
2009-06-03 13:10:13 +04:00
static void nwrap_files_endpwent ( struct nwrap_backend * b )
2009-05-27 20:38:10 +04:00
{
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2009-05-27 20:38:10 +04:00
nwrap_pw_global . idx = 0 ;
2007-11-05 18:38:36 +03:00
}
2015-09-17 11:38:49 +03:00
/* shadow */
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
# ifdef HAVE_SETSPENT
2015-09-17 11:38:49 +03:00
static void nwrap_files_setspent ( void )
{
nwrap_sp_global . idx = 0 ;
}
static struct spwd * nwrap_files_getspent ( void )
{
struct spwd * sp ;
if ( nwrap_sp_global . idx = = 0 ) {
2015-11-11 14:47:15 +03:00
bool ok ;
ok = nwrap_files_cache_reload ( nwrap_sp_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading shadow file " ) ;
return NULL ;
}
2015-09-17 11:38:49 +03:00
}
if ( nwrap_sp_global . idx > = nwrap_sp_global . num ) {
errno = ENOENT ;
return NULL ;
}
sp = & nwrap_sp_global . list [ nwrap_sp_global . idx + + ] ;
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" return user[%s] " ,
sp - > sp_namp ) ;
return sp ;
}
static void nwrap_files_endspent ( void )
{
nwrap_sp_global . idx = 0 ;
}
2015-10-06 11:34:20 +03:00
# endif /* HAVE_SETSPENT */
2015-09-17 11:38:49 +03:00
2015-09-17 11:39:15 +03:00
static struct spwd * nwrap_files_getspnam ( const char * name )
{
int i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2015-09-17 11:39:15 +03:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Lookup user %s in files " , name ) ;
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_sp_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading shadow file " ) ;
return NULL ;
}
2015-09-17 11:39:15 +03:00
for ( i = 0 ; i < nwrap_sp_global . num ; i + + ) {
if ( strcmp ( nwrap_sp_global . list [ i ] . sp_namp , name ) = = 0 ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG , " user[%s] found " , name ) ;
return & nwrap_sp_global . list [ i ] ;
}
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" user[%s] does not match [%s] " ,
name ,
nwrap_sp_global . list [ i ] . sp_namp ) ;
}
NWRAP_LOG ( NWRAP_LOG_DEBUG , " user[%s] not found \n " , name ) ;
errno = ENOENT ;
return NULL ;
}
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-09-17 11:39:15 +03:00
2007-11-05 18:38:36 +03:00
/* misc functions */
2009-06-03 13:10:13 +04:00
static int nwrap_files_initgroups ( struct nwrap_backend * b ,
2015-09-11 14:37:57 +03:00
const char * user ,
gid_t group )
2009-05-27 20:38:10 +04:00
{
2015-09-11 14:37:57 +03:00
struct group * grp ;
gid_t * groups ;
int size = 1 ;
int rc ;
groups = ( gid_t * ) malloc ( size * sizeof ( gid_t ) ) ;
if ( groups = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Out of memory " ) ;
errno = ENOMEM ;
return - 1 ;
}
groups [ 0 ] = group ;
nwrap_files_setgrent ( b ) ;
while ( ( grp = nwrap_files_getgrent ( b ) ) ! = NULL ) {
int i = 0 ;
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 ( group ! = grp - > gr_gid & &
( strcmp ( user , grp - > gr_mem [ i ] ) = = 0 ) ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" %s is member of %s " ,
user ,
grp - > gr_name ) ;
groups = ( gid_t * ) realloc ( groups ,
( size + 1 ) * sizeof ( gid_t ) ) ;
if ( groups = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Out of memory " ) ;
errno = ENOMEM ;
return - 1 ;
}
groups [ size ] = grp - > gr_gid ;
size + + ;
}
}
}
nwrap_files_endgrent ( b ) ;
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" %s is member of %d groups " ,
user , size ) ;
/* This really only works if uid_wrapper is loaded */
rc = setgroups ( size , groups ) ;
free ( groups ) ;
2014-01-31 18:57:43 +04:00
2015-09-11 14:37:57 +03:00
return rc ;
2009-05-27 20:38:10 +04:00
}
2007-11-05 18:38:36 +03:00
/* group functions */
2009-06-03 13:10:13 +04:00
static struct group * nwrap_files_getgrnam ( struct nwrap_backend * b ,
const char * name )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:41:23 +03:00
int i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2007-11-05 18:41:23 +03:00
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_gr_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading group file " ) ;
return NULL ;
}
2007-11-05 18:41:23 +03:00
for ( i = 0 ; i < nwrap_gr_global . num ; i + + ) {
if ( strcmp ( nwrap_gr_global . list [ i ] . gr_name , name ) = = 0 ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " group[%s] found " , name ) ;
2007-11-05 18:41:23 +03:00
return & nwrap_gr_global . list [ i ] ;
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" group[%s] does not match [%s] " ,
name ,
nwrap_gr_global . list [ i ] . gr_name ) ;
2007-11-05 18:41:23 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " group[%s] not found " , name ) ;
2007-11-05 18:41:23 +03:00
errno = ENOENT ;
return NULL ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getgrnam_r ( struct nwrap_backend * b ,
const char * name , struct group * grdst ,
2009-05-27 20:38:10 +04:00
char * buf , size_t buflen , struct group * * grdstp )
{
struct group * gr ;
2009-06-03 13:10:13 +04:00
gr = nwrap_files_getgrnam ( b , name ) ;
2007-11-05 18:41:23 +03:00
if ( ! gr ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_gr_copy_r ( gr , grdst , buf , buflen , grdstp ) ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static struct group * nwrap_files_getgrgid ( struct nwrap_backend * b ,
gid_t gid )
2009-05-27 20:38:10 +04:00
{
int i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2009-05-27 20:38:10 +04:00
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_gr_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading group file " ) ;
return NULL ;
}
2007-11-05 18:41:23 +03:00
for ( i = 0 ; i < nwrap_gr_global . num ; i + + ) {
if ( nwrap_gr_global . list [ i ] . gr_gid = = gid ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " gid[%u] found " , gid ) ;
2007-11-05 18:41:23 +03:00
return & nwrap_gr_global . list [ i ] ;
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" gid[%u] does not match [%u] " ,
gid ,
nwrap_gr_global . list [ i ] . gr_gid ) ;
2007-11-05 18:41:23 +03:00
}
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " gid[%u] not found " , gid ) ;
2007-11-05 18:41:23 +03:00
errno = ENOENT ;
return NULL ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getgrgid_r ( struct nwrap_backend * b ,
gid_t gid , struct group * grdst ,
2009-05-27 20:38:10 +04:00
char * buf , size_t buflen , struct group * * grdstp )
{
struct group * gr ;
2009-06-03 13:10:13 +04:00
gr = nwrap_files_getgrgid ( b , gid ) ;
2007-11-05 18:41:23 +03:00
if ( ! gr ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_gr_copy_r ( gr , grdst , buf , buflen , grdstp ) ;
2007-11-05 18:38:36 +03:00
}
/* group enum functions */
2009-06-03 13:10:13 +04:00
static void nwrap_files_setgrent ( struct nwrap_backend * b )
2009-05-27 20:38:10 +04:00
{
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2009-05-27 20:38:10 +04:00
nwrap_gr_global . idx = 0 ;
}
2009-06-03 13:10:13 +04:00
static struct group * nwrap_files_getgrent ( struct nwrap_backend * b )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:41:23 +03:00
struct group * gr ;
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2007-11-05 18:41:23 +03:00
if ( nwrap_gr_global . idx = = 0 ) {
2015-11-11 14:47:15 +03:00
bool ok ;
ok = nwrap_files_cache_reload ( nwrap_gr_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading group file " ) ;
return NULL ;
}
2007-11-05 18:41:23 +03:00
}
if ( nwrap_gr_global . idx > = nwrap_gr_global . num ) {
errno = ENOENT ;
return NULL ;
}
gr = & nwrap_gr_global . list [ nwrap_gr_global . idx + + ] ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" return group[%s] gid[%u] " ,
gr - > gr_name , gr - > gr_gid ) ;
2007-11-05 18:41:23 +03:00
return gr ;
2007-11-05 18:38:36 +03:00
}
2009-06-03 13:10:13 +04:00
static int nwrap_files_getgrent_r ( struct nwrap_backend * b ,
struct group * grdst , char * buf ,
2009-05-27 20:38:10 +04:00
size_t buflen , struct group * * grdstp )
2007-11-05 18:38:36 +03:00
{
2007-11-05 18:41:23 +03:00
struct group * gr ;
2009-06-03 13:10:13 +04:00
gr = nwrap_files_getgrent ( b ) ;
2009-05-27 20:38:10 +04:00
if ( ! gr ) {
if ( errno = = 0 ) {
return ENOENT ;
}
return errno ;
}
return nwrap_gr_copy_r ( gr , grdst , buf , buflen , grdstp ) ;
}
2009-06-03 13:10:13 +04:00
static void nwrap_files_endgrent ( struct nwrap_backend * b )
2009-05-27 20:38:10 +04:00
{
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
2009-05-27 20:38:10 +04:00
nwrap_gr_global . idx = 0 ;
2007-11-05 18:38:36 +03:00
}
2014-01-31 18:57:43 +04:00
/* hosts functions */
2015-07-16 17:10:20 +03:00
static int nwrap_files_gethostbyname ( const char * name , int af ,
struct hostent * result ,
struct nwrap_vector * addr_list )
2014-01-31 18:57:43 +04:00
{
2015-11-11 12:36:07 +03:00
struct nwrap_entlist * el ;
2014-01-31 18:57:43 +04:00
struct hostent * he ;
2015-07-16 17:10:20 +03:00
char * h_name_lower ;
ENTRY e ;
ENTRY * e_p ;
2014-10-09 11:16:33 +04:00
char canon_name [ DNS_NAME_MAX ] = { 0 } ;
2014-10-09 11:14:57 +04:00
size_t name_len ;
2015-07-16 17:10:20 +03:00
bool he_found = false ;
2015-11-11 14:47:15 +03:00
bool ok ;
2014-01-31 18:57:43 +04:00
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_he_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " error loading hosts file " ) ;
goto no_ent ;
}
2014-01-31 18:57:43 +04:00
2014-10-09 11:14:57 +04:00
name_len = strlen ( name ) ;
if ( name_len < sizeof ( canon_name ) & & name [ name_len - 1 ] = = ' . ' ) {
strncpy ( canon_name , name , name_len - 1 ) ;
name = canon_name ;
}
2015-07-16 17:10:20 +03:00
if ( ! str_tolower_copy ( & h_name_lower , name ) ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Out of memory while converting to lower case " ) ;
goto no_ent ;
}
/* Look at hash table for element */
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Searching for name: %s " , h_name_lower ) ;
e . key = h_name_lower ;
e . data = NULL ;
e_p = hsearch ( e , FIND ) ;
if ( e_p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Name %s not found. " , h_name_lower ) ;
SAFE_FREE ( h_name_lower ) ;
goto no_ent ;
}
SAFE_FREE ( h_name_lower ) ;
/* Always cleanup vector and results */
2015-10-08 16:27:47 +03:00
if ( ! nwrap_vector_is_initialized ( addr_list ) ) {
if ( ! nwrap_vector_init ( addr_list ) ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Unable to initialize memory for addr_list vector " ) ;
goto no_ent ;
}
} else {
/* When vector is initialized data are valid no more.
* Quick way how to free vector is : */
addr_list - > count = 0 ;
2015-07-16 17:10:20 +03:00
}
2014-01-31 18:57:43 +04:00
2015-07-16 17:10:20 +03:00
/* Iterate through results */
2015-11-11 12:36:07 +03:00
for ( el = ( struct nwrap_entlist * ) e_p - > data ; el ! = NULL ; el = el - > next )
{
he = & ( el - > ed - > ht ) ;
2014-01-31 18:57:43 +04:00
/* Filter by address familiy if provided */
if ( af ! = AF_UNSPEC & & he - > h_addrtype ! = af ) {
continue ;
}
2015-07-16 17:10:20 +03:00
/*
* GLIBC HACK ?
* glibc doesn ' t return ipv6 addresses when AF_UNSPEC is used
*/
if ( af = = AF_UNSPEC & & he - > h_addrtype ! = AF_INET ) {
2014-01-31 18:57:43 +04:00
continue ;
}
2015-07-16 17:10:20 +03:00
if ( ! he_found ) {
memcpy ( result , he , sizeof ( struct hostent ) ) ;
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Name found. Returning record for %s " ,
he - > h_name ) ;
he_found = true ;
2014-01-31 18:57:43 +04:00
}
2015-11-11 12:36:07 +03:00
nwrap_vector_merge ( addr_list , & el - > ed - > nwrap_addrdata ) ;
2015-07-16 17:10:20 +03:00
result - > h_addr_list = nwrap_vector_head ( addr_list ) ;
2014-01-31 18:57:43 +04:00
}
2015-07-16 17:10:20 +03:00
if ( he_found ) {
return 0 ;
}
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Name found in database. No records matches type. " ) ;
no_ent :
2014-01-31 18:57:43 +04:00
errno = ENOENT ;
2015-07-16 17:10:20 +03:00
return - 1 ;
2014-01-31 18:57:43 +04:00
}
# 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 )
{
2015-07-16 17:10:20 +03:00
struct nwrap_vector * addr_list = malloc ( sizeof ( struct nwrap_vector ) ) ;
int rc ;
if ( addr_list = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Unable to allocate memory for address list " ) ;
errno = ENOENT ;
return - 1 ;
}
ZERO_STRUCTP ( addr_list ) ;
rc = nwrap_files_gethostbyname ( name , AF_UNSPEC , ret , addr_list ) ;
if ( rc = = - 1 ) {
2014-01-31 18:57:43 +04:00
* h_errnop = h_errno ;
2015-07-16 17:10:20 +03:00
if ( addr_list - > items ! = NULL ) {
free ( addr_list - > items ) ;
}
SAFE_FREE ( addr_list ) ;
errno = ENOENT ;
2014-01-31 18:57:43 +04:00
return - 1 ;
}
2015-07-16 17:10:20 +03:00
2015-10-12 11:36:04 +03:00
if ( buflen < ( addr_list - > count * sizeof ( void * ) ) ) {
SAFE_FREE ( addr_list - > items ) ;
SAFE_FREE ( addr_list ) ;
return ERANGE ;
}
/* Copy all to user provided buffer and change
* pointers in returned structure .
* + 1 is for ending NULL pointer . */
memcpy ( buf , addr_list - > items , ( addr_list - > count + 1 ) * sizeof ( void * ) ) ;
free ( addr_list - > items ) ;
free ( addr_list ) ;
ret - > h_addr_list = ( char * * ) buf ;
2015-07-16 17:10:20 +03:00
* result = ret ;
return 0 ;
2014-01-31 18:57:43 +04:00
}
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
2015-11-11 15:02:59 +03:00
static int nwrap_files_getaddrinfo ( const char * name ,
unsigned short port ,
const struct addrinfo * hints ,
2015-11-12 12:20:37 +03:00
struct addrinfo * * ai )
2015-07-16 17:10:20 +03:00
{
2015-11-11 12:38:31 +03:00
struct nwrap_entlist * el ;
2015-07-16 17:10:20 +03:00
struct hostent * he ;
struct addrinfo * ai_head = NULL ;
2015-11-12 11:45:50 +03:00
struct addrinfo * ai_cur = NULL ;
2015-07-16 17:10:20 +03:00
char * h_name_lower ;
size_t name_len ;
char canon_name [ DNS_NAME_MAX ] = { 0 } ;
bool skip_canonname = false ;
2015-11-16 12:17:39 +03:00
ENTRY e = {
. key = NULL ,
} ;
2015-11-09 19:35:29 +03:00
ENTRY * e_p = NULL ;
2015-11-12 10:01:57 +03:00
int rc ;
2015-11-11 14:47:15 +03:00
bool ok ;
2015-07-16 17:10:20 +03:00
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_he_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " error loading hosts file " ) ;
2015-11-11 15:02:59 +03:00
return EAI_SYSTEM ;
2015-11-11 14:47:15 +03:00
}
2015-07-16 17:10:20 +03:00
name_len = strlen ( name ) ;
if ( name_len < DNS_NAME_MAX & & name [ name_len - 1 ] = = ' . ' ) {
strncpy ( canon_name , name , name_len - 1 ) ;
name = canon_name ;
}
if ( ! str_tolower_copy ( & h_name_lower , name ) ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Out of memory while converting to lower case " ) ;
2015-11-11 15:02:59 +03:00
return EAI_MEMORY ;
2015-07-16 17:10:20 +03:00
}
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Searching for name: %s " , h_name_lower ) ;
e . key = h_name_lower ;
e . data = NULL ;
e_p = hsearch ( e , FIND ) ;
if ( e_p = = NULL ) {
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Name %s not found. " , h_name_lower ) ;
SAFE_FREE ( h_name_lower ) ;
errno = ENOENT ;
2015-11-11 15:02:59 +03:00
return EAI_NONAME ;
2015-07-16 17:10:20 +03:00
}
NWRAP_LOG ( NWRAP_LOG_DEBUG , " Name: %s found. " , h_name_lower ) ;
SAFE_FREE ( h_name_lower ) ;
2015-11-12 10:01:57 +03:00
rc = EAI_NONAME ;
2015-11-11 12:38:31 +03:00
for ( el = ( struct nwrap_entlist * ) e_p - > data ; el ! = NULL ; el = el - > next )
{
2015-11-12 10:01:57 +03:00
int rc2 ;
2015-11-12 12:20:37 +03:00
struct addrinfo * ai_new = NULL ;
2015-07-16 17:10:20 +03:00
2015-11-11 12:38:31 +03:00
he = & ( el - > ed - > ht ) ;
2015-07-16 17:10:20 +03:00
if ( hints - > ai_family ! = AF_UNSPEC & &
2015-11-12 10:01:57 +03:00
he - > h_addrtype ! = hints - > ai_family )
{
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Entry found but with wrong AF - "
" remembering EAI_ADDRINFO. " ) ;
rc = EAI_ADDRFAMILY ;
2015-07-16 17:10:20 +03:00
continue ;
}
/* Function allocates memory and returns it in ai. */
2015-11-12 10:01:57 +03:00
rc2 = nwrap_convert_he_ai ( he ,
2015-07-16 17:10:20 +03:00
port ,
hints ,
2015-11-12 11:47:59 +03:00
& ai_new ,
2015-07-16 17:10:20 +03:00
skip_canonname ) ;
2015-11-12 10:01:57 +03:00
if ( rc2 ! = 0 ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error converting he to ai " ) ;
2015-11-12 11:46:29 +03:00
if ( ai_head ! = NULL ) {
freeaddrinfo ( ai_head ) ;
}
2015-11-12 10:01:57 +03:00
return rc2 ;
2015-07-16 17:10:20 +03:00
}
skip_canonname = true ;
if ( ai_head = = NULL ) {
2015-11-12 11:47:59 +03:00
ai_head = ai_new ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 11:45:50 +03:00
if ( ai_cur ! = NULL ) {
2015-11-12 11:47:59 +03:00
ai_cur - > ai_next = ai_new ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 11:47:59 +03:00
ai_cur = ai_new ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 10:01:57 +03:00
if ( ai_head ! = NULL ) {
rc = 0 ;
}
2015-11-11 15:02:59 +03:00
* ai = ai_head ;
2015-11-12 10:01:57 +03:00
return rc ;
2015-07-16 17:10:20 +03:00
}
2014-01-31 18:57:43 +04:00
static struct hostent * nwrap_files_gethostbyaddr ( const void * addr ,
socklen_t len , int type )
{
struct hostent * he ;
2015-03-25 11:36:10 +03:00
char ip [ NWRAP_INET_ADDRSTRLEN ] = { 0 } ;
2015-07-16 17:10:20 +03:00
struct nwrap_entdata * ed ;
2014-01-31 18:57:43 +04:00
const char * a ;
2015-07-16 17:10:20 +03:00
size_t i ;
2015-11-11 14:47:15 +03:00
bool ok ;
2014-01-31 18:57:43 +04:00
( void ) len ; /* unused */
2015-11-11 14:47:15 +03:00
ok = nwrap_files_cache_reload ( nwrap_he_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " error loading hosts file " ) ;
return NULL ;
}
2014-01-31 18:57:43 +04:00
a = inet_ntop ( type , addr , ip , sizeof ( ip ) ) ;
if ( a = = NULL ) {
errno = EINVAL ;
return NULL ;
}
2015-11-19 02:30:17 +03:00
nwrap_vector_foreach ( ed , nwrap_he_global . entries , i )
2015-07-16 17:10:20 +03:00
{
he = & ( ed - > ht ) ;
2014-01-31 18:57:43 +04:00
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 ) {
2015-11-11 14:47:15 +03:00
bool ok ;
ok = nwrap_files_cache_reload ( nwrap_he_global . cache ) ;
if ( ! ok ) {
NWRAP_LOG ( NWRAP_LOG_ERROR , " Error loading hosts file " ) ;
return NULL ;
}
2014-01-31 18:57:43 +04:00
}
if ( nwrap_he_global . idx > = nwrap_he_global . num ) {
errno = ENOENT ;
return NULL ;
}
2015-11-19 02:30:17 +03:00
he = & ( ( struct nwrap_entdata * ) nwrap_he_global . entries . items [ nwrap_he_global . idx + + ] ) - > ht ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " return hosts[%s] " , he - > h_name ) ;
return he ;
}
static void nwrap_files_endhostent ( void )
{
nwrap_he_global . idx = 0 ;
}
2009-06-04 14:17:39 +04:00
/*
* module backend
*/
2009-06-04 14:25:14 +04:00
2009-06-04 14:17:39 +04:00
static struct passwd * nwrap_module_getpwnam ( struct nwrap_backend * b ,
const char * name )
{
2009-06-04 14:25:14 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getpwnam_r ) {
return NULL ;
}
status = b - > fns - > _nss_getpwnam_r ( name , & pwd , buf , sizeof ( buf ) , & errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
return NULL ;
}
2014-01-31 18:57:43 +04:00
2009-06-04 14:25:14 +04:00
return & pwd ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getpwnam_r ( struct nwrap_backend * b ,
const char * name , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) b ; /* unused */
( void ) pwdst ; /* unused */
( void ) pwdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getpwnam_r ) {
return NSS_STATUS_NOTFOUND ;
}
ret = b - > fns - > _nss_getpwnam_r ( name , pwdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static struct passwd * nwrap_module_getpwuid ( struct nwrap_backend * b ,
uid_t uid )
{
2009-06-04 14:25:14 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getpwuid_r ) {
return NULL ;
}
status = b - > fns - > _nss_getpwuid_r ( uid , & pwd , buf , sizeof ( buf ) , & errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
return NULL ;
}
return & pwd ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getpwuid_r ( struct nwrap_backend * b ,
uid_t uid , struct passwd * pwdst ,
char * buf , size_t buflen , struct passwd * * pwdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) pwdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getpwuid_r ) {
return ENOENT ;
}
ret = b - > fns - > _nss_getpwuid_r ( uid , pwdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static void nwrap_module_setpwent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_setpwent ) {
return ;
}
b - > fns - > _nss_setpwent ( ) ;
2009-06-04 14:17:39 +04:00
}
static struct passwd * nwrap_module_getpwent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getpwent_r ) {
return NULL ;
}
status = b - > fns - > _nss_getpwent_r ( & pwd , buf , sizeof ( buf ) , & errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
return NULL ;
}
return & pwd ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getpwent_r ( struct nwrap_backend * b ,
struct passwd * pwdst , char * buf ,
size_t buflen , struct passwd * * pwdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) pwdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getpwent_r ) {
return ENOENT ;
}
ret = b - > fns - > _nss_getpwent_r ( pwdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static void nwrap_module_endpwent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_endpwent ) {
return ;
}
b - > fns - > _nss_endpwent ( ) ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_initgroups ( struct nwrap_backend * b ,
const char * user , gid_t group )
{
2009-06-04 14:25:14 +04:00
gid_t * groups ;
long int start ;
long int size ;
if ( ! b - > fns - > _nss_initgroups ) {
return NSS_STATUS_UNAVAIL ;
}
return b - > fns - > _nss_initgroups ( user , group , & start , & size , & groups , 0 , & errno ) ;
2009-06-04 14:17:39 +04:00
}
static struct group * nwrap_module_getgrnam ( struct nwrap_backend * b ,
const char * name )
{
2009-06-04 14:25:14 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1000 ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getgrnam_r ) {
return NULL ;
}
if ( ! buf ) {
buf = ( char * ) malloc ( buflen ) ;
}
again :
status = b - > fns - > _nss_getgrnam_r ( name , & grp , buf , buflen , & errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
buflen * = 2 ;
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
return NULL ;
}
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
return & grp ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getgrnam_r ( struct nwrap_backend * b ,
const char * name , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) grdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getgrnam_r ) {
return ENOENT ;
}
ret = b - > fns - > _nss_getgrnam_r ( name , grdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static struct group * nwrap_module_getgrgid ( struct nwrap_backend * b ,
gid_t gid )
{
2009-06-04 14:25:14 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1000 ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getgrgid_r ) {
return NULL ;
}
if ( ! buf ) {
buf = ( char * ) malloc ( buflen ) ;
}
again :
status = b - > fns - > _nss_getgrgid_r ( gid , & grp , buf , buflen , & errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
buflen * = 2 ;
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
return NULL ;
}
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
return & grp ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getgrgid_r ( struct nwrap_backend * b ,
gid_t gid , struct group * grdst ,
char * buf , size_t buflen , struct group * * grdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) grdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getgrgid_r ) {
return ENOENT ;
}
ret = b - > fns - > _nss_getgrgid_r ( gid , grdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static void nwrap_module_setgrent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_setgrent ) {
return ;
}
b - > fns - > _nss_setgrent ( ) ;
2009-06-04 14:17:39 +04:00
}
static struct group * nwrap_module_getgrent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1024 ;
NSS_STATUS status ;
if ( ! b - > fns - > _nss_getgrent_r ) {
return NULL ;
}
if ( ! buf ) {
buf = ( char * ) malloc ( buflen ) ;
}
again :
status = b - > fns - > _nss_getgrent_r ( & grp , buf , buflen , & errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
buflen * = 2 ;
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
return NULL ;
}
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
SAFE_FREE ( buf ) ;
return NULL ;
}
return & grp ;
2009-06-04 14:17:39 +04:00
}
static int nwrap_module_getgrent_r ( struct nwrap_backend * b ,
struct group * grdst , char * buf ,
size_t buflen , struct group * * grdstp )
{
2009-06-04 14:25:14 +04:00
int ret ;
2014-01-31 18:57:43 +04:00
( void ) grdstp ; /* unused */
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_getgrent_r ) {
return ENOENT ;
}
ret = b - > fns - > _nss_getgrent_r ( grdst , buf , buflen , & errno ) ;
switch ( ret ) {
case NSS_STATUS_SUCCESS :
return 0 ;
case NSS_STATUS_NOTFOUND :
if ( errno ! = 0 ) {
return errno ;
}
return ENOENT ;
case NSS_STATUS_TRYAGAIN :
if ( errno ! = 0 ) {
return errno ;
}
return ERANGE ;
default :
if ( errno ! = 0 ) {
return errno ;
}
return ret ;
}
2009-06-04 14:17:39 +04:00
}
static void nwrap_module_endgrent ( struct nwrap_backend * b )
{
2009-06-04 14:25:14 +04:00
if ( ! b - > fns - > _nss_endgrent ) {
return ;
}
b - > fns - > _nss_endgrent ( ) ;
2009-06-04 14:17:39 +04:00
}
2014-01-31 18:57:43 +04:00
/****************************************************************************
* GETPWNAM
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-31 04:20:29 +04:00
2014-01-31 18:57:43 +04:00
static struct passwd * nwrap_getpwnam ( const char * name )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct passwd * pwd ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
pwd = b - > ops - > nw_getpwnam ( b , name ) ;
if ( pwd ) {
return pwd ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct passwd * getpwnam ( const char * name )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getpwnam ( name ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getpwnam_r ( b , name , pwdst , buf , buflen , pwdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# 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 )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct passwd * pwd ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
pwd = b - > ops - > nw_getpwuid ( b , uid ) ;
if ( pwd ) {
return pwd ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct passwd * getpwuid ( uid_t uid )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getpwuid ( uid ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getpwuid_r ( b , uid , pwdst , buf , buflen , pwdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# 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
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getpwuid_r ( uid , pwdst , buf , buflen , pwdstp ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
return nwrap_getpwuid_r ( uid , pwdst , buf , buflen , pwdstp ) ;
}
/****************************************************************************
* SETPWENT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void nwrap_setpwent ( void )
{
int i ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
b - > ops - > nw_setpwent ( b ) ;
}
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
void setpwent ( void )
{
if ( ! nss_wrapper_enabled ( ) ) {
libc_setpwent ( ) ;
return ;
}
nwrap_setpwent ( ) ;
}
/****************************************************************************
* GETPWENT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct passwd * nwrap_getpwent ( void )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct passwd * pwd ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
pwd = b - > ops - > nw_getpwent ( b ) ;
if ( pwd ) {
return pwd ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct passwd * getpwent ( void )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getpwent ( ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
return nwrap_getpwent ( ) ;
}
/****************************************************************************
* GETPWENT_R
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int nwrap_getpwent_r ( struct passwd * pwdst , char * buf ,
size_t buflen , struct passwd * * pwdstp )
{
int i , ret ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getpwent_r ( b , pwdst , buf , buflen , pwdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# ifdef HAVE_SOLARIS_GETPWENT_R
struct passwd * getpwent_r ( struct passwd * pwdst , char * buf , int buflen )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
struct passwd * pwdstp = NULL ;
int rc ;
2009-06-03 13:10:13 +04:00
2014-01-31 18:57:43 +04:00
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 ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
return nwrap_getpwent_r ( pwdst , buf , buflen , pwdstp ) ;
}
# endif /* HAVE_SOLARIS_GETPWENT_R */
/****************************************************************************
* ENDPWENT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void nwrap_endpwent ( void )
{
int i ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
b - > ops - > nw_endpwent ( b ) ;
}
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
void endpwent ( void )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
libc_endpwent ( ) ;
return ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
nwrap_endpwent ( ) ;
}
/****************************************************************************
* INITGROUPS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int nwrap_initgroups ( const char * user , gid_t group )
{
int i ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
2014-01-31 18:57:43 +04:00
int rc ;
rc = b - > ops - > nw_initgroups ( b , user , group ) ;
if ( rc = = 0 ) {
return 0 ;
}
2009-06-03 13:10:13 +04:00
}
errno = ENOENT ;
return - 1 ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct group * grp ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
grp = b - > ops - > nw_getgrnam ( b , name ) ;
if ( grp ) {
return grp ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct group * getgrnam ( const char * name )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getgrnam ( name ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getgrnam_r ( b , name , grdst , buf , buflen , grdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# 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 )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct group * grp ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
grp = b - > ops - > nw_getgrgid ( b , gid ) ;
if ( grp ) {
return grp ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct group * getgrgid ( gid_t gid )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getgrgid ( gid ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getgrgid_r ( b , gid , grdst , buf , buflen , grdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# 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 */
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getgrgid_r ( gid , grdst , buf , buflen , grdstp ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
return nwrap_getgrgid_r ( gid , grdst , buf , buflen , grdstp ) ;
}
# endif
/****************************************************************************
* SETGRENT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void nwrap_setgrent ( void )
{
int i ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
b - > ops - > nw_setgrent ( b ) ;
}
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# 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 )
2009-05-31 04:20:29 +04:00
{
2009-06-03 13:10:13 +04:00
int i ;
struct group * grp ;
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
grp = b - > ops - > nw_getgrent ( b ) ;
if ( grp ) {
return grp ;
}
}
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
struct group * getgrent ( void )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getgrent ( ) ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
return nwrap_getgrent ( ) ;
}
/****************************************************************************
* GETGRENT_R
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int nwrap_getgrent_r ( struct group * grdst , char * buf ,
size_t buflen , struct group * * grdstp )
{
int i , ret ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
ret = b - > ops - > nw_getgrent_r ( b , grdst , buf , buflen , grdstp ) ;
if ( ret = = ENOENT ) {
continue ;
}
return ret ;
}
return ENOENT ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
# ifdef HAVE_SOLARIS_GETGRENT_R
struct group * getgrent_r ( struct group * src , char * buf , int buflen )
2009-05-31 04:20:29 +04:00
{
2014-01-31 18:57:43 +04:00
struct group * grdstp = NULL ;
int rc ;
2009-06-03 13:10:13 +04:00
2014-01-31 18:57:43 +04:00
if ( ! nss_wrapper_enabled ( ) ) {
return libc_getgrent_r ( src , buf , buflen ) ;
}
rc = nwrap_getgrent_r ( src , buf , buflen , & grdstp ) ;
if ( rc < 0 ) {
return NULL ;
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 ;
2009-06-03 13:10:13 +04:00
for ( i = 0 ; i < nwrap_main_global - > num_backends ; i + + ) {
struct nwrap_backend * b = & nwrap_main_global - > backends [ i ] ;
b - > ops - > nw_endgrent ( b ) ;
}
2009-05-31 04:20:29 +04:00
}
2014-01-31 18:57:43 +04:00
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 )
2009-05-29 11:19:16 +04:00
{
2009-06-04 22:12:27 +04:00
struct group * grp ;
gid_t * groups_tmp ;
int count = 1 ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG , " getgrouplist called for %s " , user ) ;
2009-06-04 22:12:27 +04:00
groups_tmp = ( gid_t * ) malloc ( count * sizeof ( gid_t ) ) ;
if ( ! groups_tmp ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR , " Out of memory " ) ;
2009-06-04 22:12:27 +04:00
errno = ENOMEM ;
return - 1 ;
}
2015-09-14 15:57:40 +03:00
groups_tmp [ 0 ] = group ;
2009-06-04 22:12:27 +04:00
nwrap_setgrent ( ) ;
while ( ( grp = nwrap_getgrent ( ) ) ! = NULL ) {
int i = 0 ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" Inspecting %s for group membership " ,
grp - > gr_name ) ;
2009-06-04 22:12:27 +04:00
for ( i = 0 ; grp - > gr_mem & & grp - > gr_mem [ i ] ! = NULL ; i + + ) {
2015-09-14 15:52:51 +03:00
if ( group ! = grp - > gr_gid & &
( strcmp ( user , grp - > gr_mem [ i ] ) = = 0 ) ) {
2009-06-04 22:12:27 +04:00
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" %s is member of %s " ,
user ,
grp - > gr_name ) ;
2009-06-04 22:12:27 +04:00
groups_tmp = ( gid_t * ) realloc ( groups_tmp , ( count + 1 ) * sizeof ( gid_t ) ) ;
if ( ! groups_tmp ) {
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_ERROR ,
" Out of memory " ) ;
2009-06-04 22:12:27 +04:00
errno = ENOMEM ;
return - 1 ;
}
2015-09-14 15:57:40 +03:00
groups_tmp [ count ] = grp - > gr_gid ;
2009-06-04 22:12:27 +04:00
count + + ;
}
}
}
2009-06-03 13:10:13 +04:00
2009-06-04 22:12:27 +04:00
nwrap_endgrent ( ) ;
2014-01-31 18:57:43 +04:00
NWRAP_LOG ( NWRAP_LOG_DEBUG ,
" %s is member of %d groups " ,
user , * ngroups ) ;
2009-06-04 22:12:27 +04:00
if ( * ngroups < count ) {
* ngroups = count ;
free ( groups_tmp ) ;
return - 1 ;
}
* ngroups = count ;
memcpy ( groups , groups_tmp , count * sizeof ( gid_t ) ) ;
free ( groups_tmp ) ;
return count ;
2009-05-29 11:19:16 +04:00
}
2014-01-31 18:57:43 +04:00
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
2015-09-17 11:38:49 +03:00
/**********************************************************
* SHADOW
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-10-06 11:34:20 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
# ifdef HAVE_SETSPENT
2015-09-17 11:38:49 +03:00
static void nwrap_setspent ( void )
{
nwrap_files_setspent ( ) ;
}
void setspent ( void )
{
if ( ! nss_wrapper_shadow_enabled ( ) ) {
return ;
}
nwrap_setspent ( ) ;
}
static struct spwd * nwrap_getspent ( void )
{
return nwrap_files_getspent ( ) ;
}
struct spwd * getspent ( void )
{
if ( ! nss_wrapper_shadow_enabled ( ) ) {
return NULL ;
}
return nwrap_getspent ( ) ;
}
static void nwrap_endspent ( void )
{
nwrap_files_endspent ( ) ;
}
void endspent ( void )
{
if ( ! nss_wrapper_shadow_enabled ( ) ) {
return ;
}
nwrap_endspent ( ) ;
}
2015-10-06 11:34:20 +03:00
# endif /* HAVE_SETSPENT */
2015-09-17 11:38:49 +03:00
2015-09-17 11:39:15 +03:00
static struct spwd * nwrap_getspnam ( const char * name )
{
return nwrap_files_getspnam ( name ) ;
}
struct spwd * getspnam ( const char * name )
{
if ( ! nss_wrapper_shadow_enabled ( ) ) {
return NULL ;
}
return nwrap_getspnam ( name ) ;
}
2015-10-06 11:34:20 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2014-01-31 18:57:43 +04:00
/**********************************************************
* 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 */
2015-03-27 17:51:11 +03:00
# ifdef BSD
/* BSD implementation stores data in thread local storage but GLIBC does not */
static __thread struct hostent user_he ;
static __thread struct nwrap_vector user_addrlist ;
# else
2015-07-16 17:10:20 +03:00
static struct hostent user_he ;
static struct nwrap_vector user_addrlist ;
2015-03-27 17:51:11 +03:00
# endif /* BSD */
2014-01-31 18:57:43 +04:00
static struct hostent * nwrap_gethostbyname ( const char * name )
{
2015-07-16 17:10:20 +03:00
if ( nwrap_files_gethostbyname ( name , AF_UNSPEC , & user_he , & user_addrlist ) = = - 1 ) {
return NULL ;
}
return & user_he ;
2014-01-31 18:57:43 +04:00
}
struct hostent * gethostbyname ( const char * name )
{
if ( ! nss_wrapper_hosts_enabled ( ) ) {
return libc_gethostbyname ( name ) ;
}
return nwrap_gethostbyname ( name ) ;
}
2015-03-27 17:51:11 +03:00
/* This is a GNU extension - Also can be found on BSD systems */
2014-01-31 18:57:43 +04:00
# ifdef HAVE_GETHOSTBYNAME2
2015-03-27 17:51:11 +03:00
# ifdef BSD
/* BSD implementation stores data in thread local storage but GLIBC not */
static __thread struct hostent user_he2 ;
static __thread struct nwrap_vector user_addrlist2 ;
# else
2015-07-16 17:10:20 +03:00
static struct hostent user_he2 ;
static struct nwrap_vector user_addrlist2 ;
2015-03-27 17:51:11 +03:00
# endif /* BSD */
2014-01-31 18:57:43 +04:00
static struct hostent * nwrap_gethostbyname2 ( const char * name , int af )
{
2015-07-16 17:10:20 +03:00
if ( nwrap_files_gethostbyname ( name , af , & user_he2 , & user_addrlist2 ) = = - 1 ) {
return NULL ;
}
return & user_he2 ;
2014-01-31 18:57:43 +04:00
}
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 ,
2015-07-16 17:10:20 +03:00
struct addrinfo * * pai ,
bool skip_canonname )
2014-01-31 18:57:43 +04:00
{
struct addrinfo * ai ;
socklen_t socklen ;
2015-07-16 17:10:20 +03:00
if ( he = = NULL ) {
return EAI_MEMORY ;
}
2014-01-31 18:57:43 +04:00
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 ;
}
2015-11-12 13:15:03 +03:00
ai - > ai_flags = hints - > ai_flags ;
2014-01-31 18:57:43 +04:00
ai - > ai_family = he - > h_addrtype ;
ai - > ai_socktype = hints - > ai_socktype ;
ai - > ai_protocol = hints - > ai_protocol ;
2015-07-16 17:10:20 +03:00
ai - > ai_canonname = NULL ;
2014-01-31 18:57:43 +04:00
2015-11-12 13:15:03 +03:00
if ( ai - > ai_socktype = = 0 ) {
ai - > ai_socktype = SOCK_DGRAM ;
}
if ( ai - > ai_protocol = = 0 ) {
if ( ai - > ai_socktype = = SOCK_DGRAM ) {
ai - > ai_protocol = IPPROTO_UDP ;
} else if ( ai - > ai_socktype = = SOCK_STREAM ) {
ai - > ai_protocol = IPPROTO_TCP ;
}
}
2014-01-31 18:57:43 +04:00
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 ;
2015-07-16 17:10:20 +03:00
memcpy ( & sin6p - > sin6_addr ,
he - > h_addr_list [ 0 ] ,
he - > h_length ) ;
2014-01-31 18:57:43 +04:00
}
break ;
# endif
}
ai - > ai_next = NULL ;
2015-07-16 17:10:20 +03:00
if ( he - > h_name & & ! skip_canonname ) {
2014-01-31 18:57:43 +04:00
ai - > ai_canonname = strdup ( he - > h_name ) ;
if ( ai - > ai_canonname = = NULL ) {
freeaddrinfo ( ai ) ;
return EAI_MEMORY ;
}
}
* pai = ai ;
return 0 ;
}
static int nwrap_getaddrinfo ( const char * node ,
const char * service ,
const struct addrinfo * hints ,
struct addrinfo * * res )
{
struct addrinfo * ai = NULL ;
unsigned short port = 0 ;
2014-10-09 11:15:59 +04:00
struct {
int family ;
union {
struct in_addr v4 ;
# ifdef HAVE_IPV6
struct in6_addr v6 ;
} in ;
# endif
2014-10-09 11:17:07 +04:00
} addr = {
. family = AF_UNSPEC ,
} ;
2015-11-11 15:02:59 +03:00
int rc ;
2014-01-31 18:57:43 +04:00
if ( node = = NULL & & service = = NULL ) {
return EAI_NONAME ;
}
2015-07-16 17:10:20 +03:00
if ( hints = = NULL ) {
hints = & default_hints ;
}
/* EAI_BADFLAGS
hints . ai_flags contains invalid flags ; or , hints . ai_flags
included AI_CANONNAME and name was NULL .
*/
if ( ( hints - > ai_flags & AI_CANONNAME ) & & ( node = = NULL ) ) {
return EAI_BADFLAGS ;
}
2014-01-31 18:57:43 +04:00
/* If no node has been specified, let glibc deal with it */
if ( node = = NULL ) {
2015-11-06 13:43:04 +03:00
int ret ;
struct addrinfo * p = NULL ;
ret = libc_getaddrinfo ( node , service , hints , & p ) ;
if ( ret = = 0 ) {
* res = p ;
}
2014-01-31 18:57:43 +04:00
return ret ;
}
if ( service ! = NULL & & service [ 0 ] ! = ' \0 ' ) {
2015-10-13 15:41:14 +03:00
const char * proto = NULL ;
struct servent * s ;
char * end_ptr ;
long sl ;
errno = 0 ;
sl = strtol ( service , & end_ptr , 10 ) ;
2015-11-06 12:22:10 +03:00
if ( * end_ptr = = ' \0 ' ) {
2015-10-13 15:41:14 +03:00
port = sl ;
goto valid_port ;
} else if ( hints - > ai_flags & AI_NUMERICSERV ) {
2015-11-06 12:45:15 +03:00
return EAI_NONAME ;
2015-10-13 15:41:14 +03:00
}
2014-01-31 18:57:43 +04:00
2015-10-13 15:41:14 +03:00
if ( hints - > ai_protocol ! = 0 ) {
struct protoent * pent ;
2014-01-31 18:57:43 +04:00
2015-10-13 15:41:14 +03:00
pent = getprotobynumber ( hints - > ai_protocol ) ;
if ( pent ! = NULL ) {
proto = pent - > p_name ;
2014-01-31 18:57:43 +04:00
}
2015-10-13 15:41:14 +03:00
}
2014-01-31 18:57:43 +04:00
2015-10-13 15:41:14 +03:00
s = getservbyname ( service , proto ) ;
2015-11-09 02:55:00 +03:00
if ( s = = NULL ) {
2015-11-06 13:00:54 +03:00
return EAI_NONAME ;
2014-01-31 18:57:43 +04:00
}
2015-11-09 02:55:00 +03:00
port = ntohs ( s - > s_port ) ;
2014-01-31 18:57:43 +04:00
}
2015-10-13 15:41:14 +03:00
valid_port :
2015-11-12 10:16:18 +03:00
rc = inet_pton ( AF_INET , node , & addr . in . v4 ) ;
if ( rc = = 1 ) {
addr . family = AF_INET ;
2014-01-31 18:57:43 +04:00
}
# ifdef HAVE_IPV6
2015-11-06 13:52:08 +03:00
if ( addr . family = = AF_UNSPEC ) {
2015-11-11 15:02:59 +03:00
rc = inet_pton ( AF_INET6 , node , & addr . in . v6 ) ;
2014-01-31 18:57:43 +04:00
if ( rc = = 1 ) {
2014-10-09 11:15:59 +04:00
addr . family = AF_INET6 ;
2014-01-31 18:57:43 +04:00
}
}
2015-11-06 13:52:08 +03:00
# endif
2014-01-31 18:57:43 +04:00
2015-11-09 02:29:23 +03:00
if ( addr . family = = AF_UNSPEC ) {
if ( hints - > ai_flags & AI_NUMERICHOST ) {
return EAI_NONAME ;
}
} else if ( ( hints - > ai_family ! = AF_UNSPEC ) & &
( hints - > ai_family ! = addr . family ) )
2015-11-12 10:16:18 +03:00
{
return EAI_ADDRFAMILY ;
}
2015-11-12 12:20:37 +03:00
rc = nwrap_files_getaddrinfo ( node , port , hints , & ai ) ;
2015-11-11 15:02:59 +03:00
if ( rc ! = 0 ) {
2015-11-06 13:43:04 +03:00
int ret ;
struct addrinfo * p = NULL ;
ret = libc_getaddrinfo ( node , service , hints , & p ) ;
2015-11-06 13:31:09 +03:00
if ( ret = = 0 ) {
/*
* nwrap_files_getaddrinfo failed , but libc was
* successful - - use the result from libc .
*/
2015-11-06 13:43:04 +03:00
* res = p ;
2015-11-06 13:31:09 +03:00
return 0 ;
}
2015-11-11 15:02:59 +03:00
return rc ;
2014-01-31 18:57:43 +04:00
}
2015-11-12 13:17:21 +03:00
/*
* If the socktype was not specified , duplicate
* each ai returned , so that we have variants for
* both UDP and TCP .
*/
2014-01-31 18:57:43 +04:00
if ( hints - > ai_socktype = = 0 ) {
2015-11-12 13:35:07 +03:00
struct addrinfo * ai_cur ;
2015-07-16 17:10:20 +03:00
2015-11-12 13:35:07 +03:00
/* freeaddrinfo() frees ai_canonname and ai so allocate them */
for ( ai_cur = ai ; ai_cur ! = NULL ; ai_cur = ai_cur - > ai_next ) {
struct addrinfo * ai_new ;
/* duplicate the current entry */
ai_new = malloc ( sizeof ( struct addrinfo ) ) ;
if ( ai_new = = NULL ) {
freeaddrinfo ( ai ) ;
return EAI_MEMORY ;
2015-07-16 17:10:20 +03:00
}
2014-01-31 18:57:43 +04:00
2015-11-12 13:35:07 +03:00
memcpy ( ai_new , ai_cur , sizeof ( struct addrinfo ) ) ;
ai_new - > ai_next = NULL ;
/* We need a deep copy or freeaddrinfo() will blow up */
if ( ai_cur - > ai_canonname ! = NULL ) {
ai_new - > ai_canonname =
strdup ( ai_cur - > ai_canonname ) ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 13:35:07 +03:00
if ( ai_cur - > ai_socktype = = SOCK_DGRAM ) {
ai_new - > ai_socktype = SOCK_STREAM ;
} else if ( ai_cur - > ai_socktype = = SOCK_STREAM ) {
ai_new - > ai_socktype = SOCK_DGRAM ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 13:35:07 +03:00
if ( ai_cur - > ai_protocol = = IPPROTO_TCP ) {
ai_new - > ai_protocol = IPPROTO_UDP ;
} else if ( ai_cur - > ai_protocol = = IPPROTO_UDP ) {
ai_new - > ai_protocol = IPPROTO_TCP ;
2015-07-16 17:10:20 +03:00
}
2015-11-12 13:08:47 +03:00
2015-11-12 13:35:07 +03:00
/* now insert the new entry */
2015-07-16 17:10:20 +03:00
2015-11-12 13:35:07 +03:00
ai_new - > ai_next = ai_cur - > ai_next ;
ai_cur - > ai_next = ai_new ;
/* and move on (don't duplicate the new entry) */
ai_cur = ai_new ;
}
2014-01-31 18:57:43 +04:00
}
* 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 ) {
2014-06-21 12:47:28 +04:00
case AF_INET :
if ( salen < sizeof ( struct sockaddr_in ) )
return EAI_FAMILY ;
2014-06-21 12:48:56 +04:00
addr = & ( ( const struct sockaddr_in * ) sa ) - > sin_addr ;
addrlen = sizeof ( ( ( const struct sockaddr_in * ) sa ) - > sin_addr ) ;
port = ntohs ( ( ( const struct sockaddr_in * ) sa ) - > sin_port ) ;
2014-06-21 12:47:28 +04:00
break ;
2014-01-31 18:57:43 +04:00
# ifdef HAVE_IPV6
2014-06-21 12:47:28 +04:00
case AF_INET6 :
if ( salen < sizeof ( struct sockaddr_in6 ) )
2014-01-31 18:57:43 +04:00
return EAI_FAMILY ;
2014-06-21 12:48:56 +04:00
addr = & ( ( const struct sockaddr_in6 * ) sa ) - > sin6_addr ;
addrlen = sizeof ( ( ( const struct sockaddr_in6 * ) sa ) - > sin6_addr ) ;
port = ntohs ( ( ( const struct sockaddr_in6 * ) sa ) - > sin6_port ) ;
2014-06-21 12:47:28 +04:00
break ;
# endif
default :
return EAI_FAMILY ;
2014-01-31 18:57:43 +04:00
}
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 ;
2015-03-24 19:54:34 +03:00
NWRAP_LOCK_ALL ;
2014-01-31 18:57:43 +04:00
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 ) {
2015-03-23 16:39:28 +03:00
fclose ( c - > fp ) ;
c - > fd = - 1 ;
2014-01-31 18:57:43 +04:00
}
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 ) {
2015-03-23 16:39:28 +03:00
fclose ( c - > fp ) ;
c - > fd = - 1 ;
2014-01-31 18:57:43 +04:00
}
SAFE_FREE ( nwrap_gr_global . list ) ;
nwrap_pw_global . num = 0 ;
}
2015-11-20 10:51:49 +03:00
# if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
2015-11-19 11:02:46 +03:00
if ( nwrap_sp_global . cache ! = NULL ) {
struct nwrap_cache * c = nwrap_sp_global . cache ;
nwrap_files_cache_unload ( c ) ;
if ( c - > fd > = 0 ) {
fclose ( c - > fp ) ;
c - > fd = - 1 ;
}
2015-11-20 11:01:01 +03:00
nwrap_sp_global . num = 0 ;
2015-11-19 11:02:46 +03:00
}
2015-11-20 10:51:49 +03:00
# endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
2015-11-19 11:02:46 +03:00
2014-01-31 18:57:43 +04:00
if ( nwrap_he_global . cache ! = NULL ) {
struct nwrap_cache * c = nwrap_he_global . cache ;
nwrap_files_cache_unload ( c ) ;
if ( c - > fd > = 0 ) {
2015-03-23 16:39:28 +03:00
fclose ( c - > fp ) ;
c - > fd = - 1 ;
2014-01-31 18:57:43 +04:00
}
nwrap_he_global . num = 0 ;
}
2015-07-15 16:01:48 +03:00
2015-11-20 11:38:16 +03:00
free ( user_addrlist . items ) ;
2015-11-23 10:33:02 +03:00
# ifdef HAVE_GETHOSTBYNAME2
2015-11-20 11:38:16 +03:00
free ( user_addrlist2 . items ) ;
2015-11-23 10:33:02 +03:00
# endif
2015-11-20 11:38:16 +03:00
2015-07-15 16:01:48 +03:00
hdestroy ( ) ;
2015-03-24 19:54:34 +03:00
NWRAP_UNLOCK_ALL ;
2014-01-31 18:57:43 +04:00
}