2008-12-16 12:06:04 +03:00
/*
2003-08-13 05:53:07 +04:00
Unix SMB / CIFS implementation .
nss tester for winbindd
Copyright ( C ) Andrew Tridgell 2001
2010-10-20 16:52:30 +04:00
Copyright ( C ) Tim Potter 2003
2008-12-16 12:06:04 +03:00
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
2008-12-16 12:06:04 +03:00
2003-08-13 05:53:07 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2008-12-16 12:06:04 +03:00
2003-08-13 05:53:07 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
2011-01-04 10:42:16 +03:00
# include "replace.h"
2007-06-14 10:05:27 +04:00
# include "nsswitch/nsstest.h"
2007-06-09 11:17:24 +04:00
2018-02-11 01:54:33 +03:00
# define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
2003-08-13 05:53:07 +04:00
static const char * so_path = " /lib/libnss_winbind.so " ;
static const char * nss_name = " winbind " ;
static int nss_errno ;
static NSS_STATUS last_error ;
static int total_errors ;
static void * find_fn ( const char * name )
{
2010-10-20 16:52:30 +04:00
char * s ;
2003-08-13 05:53:07 +04:00
static void * h ;
void * res ;
2010-10-20 16:52:30 +04:00
if ( asprintf ( & s , " _nss_%s_%s " , nss_name , name ) < 0 ) {
exit ( 1 ) ;
}
2003-08-13 05:53:07 +04:00
if ( ! h ) {
2007-06-09 11:17:24 +04:00
h = dlopen ( so_path , RTLD_LAZY ) ;
2003-08-13 05:53:07 +04:00
}
if ( ! h ) {
printf ( " Can't open shared library %s \n " , so_path ) ;
exit ( 1 ) ;
}
2007-06-09 11:17:24 +04:00
res = dlsym ( h , s ) ;
2003-08-13 05:53:07 +04:00
if ( ! res ) {
printf ( " Can't find function %s \n " , s ) ;
2010-10-20 16:52:30 +04:00
total_errors + + ;
2018-02-11 01:54:33 +03:00
SAFE_FREE ( s ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
2018-02-11 01:54:33 +03:00
SAFE_FREE ( s ) ;
2003-08-13 05:53:07 +04:00
return res ;
}
static void report_nss_error ( const char * who , NSS_STATUS status )
{
last_error = status ;
total_errors + + ;
2008-12-16 12:06:04 +03:00
printf ( " ERROR %s: NSS_STATUS=%d %d (nss_errno=%d) \n " ,
2003-08-13 05:53:07 +04:00
who , status , NSS_STATUS_SUCCESS , nss_errno ) ;
}
static struct passwd * nss_getpwent ( void )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getpwent_r ) ( struct passwd * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( struct passwd * , char * ,
size_t , int * ) ) find_fn ( " getpwent_r " ) ;
2003-08-13 05:53:07 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_getpwent_r )
return NULL ;
2003-08-13 05:53:07 +04:00
status = _nss_getpwent_r ( & pwd , buf , sizeof ( buf ) , & nss_errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getpwent " , status ) ;
return NULL ;
}
return & pwd ;
}
static struct passwd * nss_getpwnam ( const char * name )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getpwnam_r ) ( const char * , struct passwd * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( const char * , struct passwd * , char * ,
size_t , int * ) ) find_fn ( " getpwnam_r " ) ;
2003-08-13 05:53:07 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
2008-12-16 12:06:04 +03:00
2010-10-20 16:52:30 +04:00
if ( ! _nss_getpwnam_r )
return NULL ;
2003-08-13 05:53:07 +04:00
status = _nss_getpwnam_r ( name , & pwd , buf , sizeof ( buf ) , & nss_errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getpwnam " , status ) ;
return NULL ;
}
return & pwd ;
}
static struct passwd * nss_getpwuid ( uid_t uid )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getpwuid_r ) ( uid_t , struct passwd * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( uid_t , struct passwd * , char * ,
size_t , int * ) ) find_fn ( " getpwuid_r " ) ;
2003-08-13 05:53:07 +04:00
static struct passwd pwd ;
static char buf [ 1000 ] ;
NSS_STATUS status ;
2008-12-16 12:06:04 +03:00
2010-10-20 16:52:30 +04:00
if ( ! _nss_getpwuid_r )
return NULL ;
2003-08-13 05:53:07 +04:00
status = _nss_getpwuid_r ( uid , & pwd , buf , sizeof ( buf ) , & nss_errno ) ;
if ( status = = NSS_STATUS_NOTFOUND ) {
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getpwuid " , status ) ;
return NULL ;
}
return & pwd ;
}
2020-07-23 08:42:09 +03:00
static void samba_nss_setpwent ( void )
2003-08-13 05:53:07 +04:00
{
2010-10-20 16:52:30 +04:00
NSS_STATUS ( * _nss_setpwent ) ( void ) =
( NSS_STATUS ( * ) ( void ) ) find_fn ( " setpwent " ) ;
2003-08-13 05:53:07 +04:00
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_setpwent )
return ;
2003-08-13 05:53:07 +04:00
status = _nss_setpwent ( ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " setpwent " , status ) ;
}
}
2020-07-23 08:42:09 +03:00
static void samba_nss_endpwent ( void )
2003-08-13 05:53:07 +04:00
{
2010-10-20 16:52:30 +04:00
NSS_STATUS ( * _nss_endpwent ) ( void ) =
( NSS_STATUS ( * ) ( void ) ) find_fn ( " endpwent " ) ;
2003-08-13 05:53:07 +04:00
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_endpwent )
return ;
2003-08-13 05:53:07 +04:00
status = _nss_endpwent ( ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " endpwent " , status ) ;
}
}
static struct group * nss_getgrent ( void )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getgrent_r ) ( struct group * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( struct group * , char * ,
size_t , int * ) ) find_fn ( " getgrent_r " ) ;
2003-08-13 05:53:07 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1024 ;
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_getgrent_r )
return NULL ;
if ( ! buf )
buf = ( char * ) malloc ( buflen ) ;
2003-08-13 05:53:07 +04:00
2008-12-16 12:06:04 +03:00
again :
2003-08-13 05:53:07 +04:00
status = _nss_getgrent_r ( & grp , buf , buflen , & nss_errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
2019-05-22 14:09:41 +03:00
char * oldbuf = buf ;
2003-08-13 05:53:07 +04:00
buflen * = 2 ;
2010-10-20 16:52:30 +04:00
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
2019-05-22 14:09:41 +03:00
SAFE_FREE ( oldbuf ) ;
2010-10-20 16:52:30 +04:00
return NULL ;
}
2003-08-13 05:53:07 +04:00
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getgrent " , status ) ;
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
return & grp ;
}
static struct group * nss_getgrnam ( const char * name )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getgrnam_r ) ( const char * , struct group * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( const char * , struct group * , char * ,
size_t , int * ) ) find_fn ( " getgrnam_r " ) ;
2003-08-13 05:53:07 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1000 ;
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_getgrnam_r )
return NULL ;
if ( ! buf )
buf = ( char * ) malloc ( buflen ) ;
2008-12-16 12:06:04 +03:00
again :
2003-08-13 05:53:07 +04:00
status = _nss_getgrnam_r ( name , & grp , buf , buflen , & nss_errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
2019-05-22 14:09:41 +03:00
char * oldbuf = buf ;
2003-08-13 05:53:07 +04:00
buflen * = 2 ;
2010-10-20 16:52:30 +04:00
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
2019-05-22 14:09:41 +03:00
SAFE_FREE ( oldbuf ) ;
2010-10-20 16:52:30 +04:00
return NULL ;
}
2003-08-13 05:53:07 +04:00
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getgrnam " , status ) ;
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
return & grp ;
}
static struct group * nss_getgrgid ( gid_t gid )
{
2008-12-16 12:06:04 +03:00
NSS_STATUS ( * _nss_getgrgid_r ) ( gid_t , struct group * , char * ,
2010-10-20 16:52:30 +04:00
size_t , int * ) =
( NSS_STATUS ( * ) ( gid_t , struct group * , char * ,
size_t , int * ) ) find_fn ( " getgrgid_r " ) ;
2003-08-13 05:53:07 +04:00
static struct group grp ;
static char * buf ;
static int buflen = 1000 ;
NSS_STATUS status ;
2008-12-16 12:06:04 +03:00
2010-10-20 16:52:30 +04:00
if ( ! _nss_getgrgid_r )
return NULL ;
if ( ! buf )
buf = ( char * ) malloc ( buflen ) ;
2008-12-16 12:06:04 +03:00
again :
2003-08-13 05:53:07 +04:00
status = _nss_getgrgid_r ( gid , & grp , buf , buflen , & nss_errno ) ;
if ( status = = NSS_STATUS_TRYAGAIN ) {
2019-05-22 14:09:41 +03:00
char * oldbuf = buf ;
2003-08-13 05:53:07 +04:00
buflen * = 2 ;
2010-10-20 16:52:30 +04:00
buf = ( char * ) realloc ( buf , buflen ) ;
if ( ! buf ) {
2019-05-22 14:09:41 +03:00
SAFE_FREE ( oldbuf ) ;
2010-10-20 16:52:30 +04:00
return NULL ;
}
2003-08-13 05:53:07 +04:00
goto again ;
}
if ( status = = NSS_STATUS_NOTFOUND ) {
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " getgrgid " , status ) ;
2018-02-11 01:54:33 +03:00
SAFE_FREE ( buf ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
return & grp ;
}
2020-07-23 08:42:09 +03:00
static void samba_nss_setgrent ( void )
2003-08-13 05:53:07 +04:00
{
2010-10-20 16:52:30 +04:00
NSS_STATUS ( * _nss_setgrent ) ( void ) =
( NSS_STATUS ( * ) ( void ) ) find_fn ( " setgrent " ) ;
2003-08-13 05:53:07 +04:00
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_setgrent )
return ;
2003-08-13 05:53:07 +04:00
status = _nss_setgrent ( ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " setgrent " , status ) ;
}
}
2020-07-23 08:42:09 +03:00
static void samba_nss_endgrent ( void )
2003-08-13 05:53:07 +04:00
{
2010-10-20 16:52:30 +04:00
NSS_STATUS ( * _nss_endgrent ) ( void ) =
( NSS_STATUS ( * ) ( void ) ) find_fn ( " endgrent " ) ;
2003-08-13 05:53:07 +04:00
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_endgrent )
return ;
2003-08-13 05:53:07 +04:00
status = _nss_endgrent ( ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " endgrent " , status ) ;
}
}
static int nss_initgroups ( char * user , gid_t group , gid_t * * groups , long int * start , long int * size )
{
NSS_STATUS ( * _nss_initgroups ) ( char * , gid_t , long int * ,
2008-12-16 12:06:04 +03:00
long int * , gid_t * * , long int , int * ) =
2010-10-20 16:52:30 +04:00
( NSS_STATUS ( * ) ( char * , gid_t , long int * ,
long int * , gid_t * * ,
long int , int * ) ) find_fn ( " initgroups_dyn " ) ;
2003-08-13 05:53:07 +04:00
NSS_STATUS status ;
2010-10-20 16:52:30 +04:00
if ( ! _nss_initgroups )
return NSS_STATUS_UNAVAIL ;
2003-08-13 05:53:07 +04:00
status = _nss_initgroups ( user , group , start , size , groups , 0 , & nss_errno ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
report_nss_error ( " initgroups " , status ) ;
}
return status ;
}
static void print_passwd ( struct passwd * pwd )
{
2010-10-20 16:52:30 +04:00
printf ( " %s:%s:%lu:%lu:%s:%s:%s \n " ,
2003-08-13 05:53:07 +04:00
pwd - > pw_name ,
pwd - > pw_passwd ,
2010-10-20 16:52:30 +04:00
( unsigned long ) pwd - > pw_uid ,
( unsigned long ) pwd - > pw_gid ,
2003-08-13 05:53:07 +04:00
pwd - > pw_gecos ,
pwd - > pw_dir ,
pwd - > pw_shell ) ;
}
static void print_group ( struct group * grp )
{
int i ;
2010-10-20 16:52:30 +04:00
printf ( " %s:%s:%lu: " ,
2003-08-13 05:53:07 +04:00
grp - > gr_name ,
grp - > gr_passwd ,
2010-10-20 16:52:30 +04:00
( unsigned long ) grp - > gr_gid ) ;
2008-12-16 12:06:04 +03:00
2003-08-13 05:53:07 +04:00
if ( ! grp - > gr_mem [ 0 ] ) {
printf ( " \n " ) ;
return ;
}
2008-12-16 12:06:04 +03:00
2003-08-13 05:53:07 +04:00
for ( i = 0 ; grp - > gr_mem [ i + 1 ] ; i + + ) {
2010-10-20 16:52:30 +04:00
printf ( " %s, " , grp - > gr_mem [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
printf ( " %s \n " , grp - > gr_mem [ i ] ) ;
}
static void nss_test_initgroups ( char * name , gid_t gid )
{
long int size = 16 ;
long int start = 1 ;
gid_t * groups = NULL ;
int i ;
NSS_STATUS status ;
2012-02-20 06:46:29 +04:00
groups = ( gid_t * ) malloc ( sizeof ( gid_t ) * size ) ;
2013-07-18 02:30:35 +04:00
if ( groups = = NULL ) {
printf ( " Unable to allocate memory for groups \n " ) ;
return ;
}
2003-08-13 05:53:07 +04:00
groups [ 0 ] = gid ;
status = nss_initgroups ( name , gid , & groups , & start , & size ) ;
if ( status = = NSS_STATUS_UNAVAIL ) {
printf ( " No initgroups fn \n " ) ;
return ;
}
for ( i = 0 ; i < start - 1 ; i + + ) {
2010-10-20 16:52:30 +04:00
printf ( " %lu, " , ( unsigned long ) groups [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
2010-10-20 16:52:30 +04:00
printf ( " %lu \n " , ( unsigned long ) groups [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
static void nss_test_users ( void )
{
struct passwd * pwd ;
2020-07-23 08:42:09 +03:00
samba_nss_setpwent ( ) ;
2003-08-13 05:53:07 +04:00
/* loop over all users */
while ( ( pwd = nss_getpwent ( ) ) ) {
printf ( " Testing user %s \n " , pwd - > pw_name ) ;
printf ( " getpwent: " ) ; print_passwd ( pwd ) ;
pwd = nss_getpwuid ( pwd - > pw_uid ) ;
if ( ! pwd ) {
total_errors + + ;
printf ( " ERROR: can't getpwuid \n " ) ;
continue ;
}
printf ( " getpwuid: " ) ; print_passwd ( pwd ) ;
pwd = nss_getpwnam ( pwd - > pw_name ) ;
if ( ! pwd ) {
total_errors + + ;
printf ( " ERROR: can't getpwnam \n " ) ;
continue ;
}
printf ( " getpwnam: " ) ; print_passwd ( pwd ) ;
printf ( " initgroups: " ) ; nss_test_initgroups ( pwd - > pw_name , pwd - > pw_gid ) ;
printf ( " \n " ) ;
}
2020-07-23 08:42:09 +03:00
samba_nss_endpwent ( ) ;
2003-08-13 05:53:07 +04:00
}
static void nss_test_groups ( void )
{
struct group * grp ;
2020-07-23 08:42:09 +03:00
samba_nss_setgrent ( ) ;
2003-08-13 05:53:07 +04:00
/* loop over all groups */
while ( ( grp = nss_getgrent ( ) ) ) {
printf ( " Testing group %s \n " , grp - > gr_name ) ;
printf ( " getgrent: " ) ; print_group ( grp ) ;
grp = nss_getgrnam ( grp - > gr_name ) ;
if ( ! grp ) {
total_errors + + ;
printf ( " ERROR: can't getgrnam \n " ) ;
continue ;
}
printf ( " getgrnam: " ) ; print_group ( grp ) ;
grp = nss_getgrgid ( grp - > gr_gid ) ;
if ( ! grp ) {
total_errors + + ;
printf ( " ERROR: can't getgrgid \n " ) ;
continue ;
}
printf ( " getgrgid: " ) ; print_group ( grp ) ;
printf ( " \n " ) ;
}
2020-07-23 08:42:09 +03:00
samba_nss_endgrent ( ) ;
2003-08-13 05:53:07 +04:00
}
static void nss_test_errors ( void )
{
struct passwd * pwd ;
struct group * grp ;
pwd = getpwnam ( " nosuchname " ) ;
if ( pwd | | last_error ! = NSS_STATUS_NOTFOUND ) {
total_errors + + ;
2012-06-11 19:24:20 +04:00
printf ( " ERROR Non existent user gave error %d \n " , last_error ) ;
2003-08-13 05:53:07 +04:00
}
2021-11-12 10:53:30 +03:00
pwd = getpwuid ( 0xFF00 ) ;
2003-08-13 05:53:07 +04:00
if ( pwd | | last_error ! = NSS_STATUS_NOTFOUND ) {
total_errors + + ;
2012-06-11 19:24:20 +04:00
printf ( " ERROR Non existent uid gave error %d \n " , last_error ) ;
2003-08-13 05:53:07 +04:00
}
grp = getgrnam ( " nosuchgroup " ) ;
if ( grp | | last_error ! = NSS_STATUS_NOTFOUND ) {
total_errors + + ;
2012-06-11 19:24:20 +04:00
printf ( " ERROR Non existent group gave error %d \n " , last_error ) ;
2003-08-13 05:53:07 +04:00
}
grp = getgrgid ( 0xFFF0 ) ;
if ( grp | | last_error ! = NSS_STATUS_NOTFOUND ) {
total_errors + + ;
2012-06-11 19:24:20 +04:00
printf ( " ERROR Non existent gid gave error %d \n " , last_error ) ;
2003-08-13 05:53:07 +04:00
}
}
int main ( int argc , char * argv [ ] )
2008-12-16 12:06:04 +03:00
{
2003-08-13 05:53:07 +04:00
if ( argc > 1 ) so_path = argv [ 1 ] ;
if ( argc > 2 ) nss_name = argv [ 2 ] ;
nss_test_users ( ) ;
nss_test_groups ( ) ;
nss_test_errors ( ) ;
printf ( " total_errors=%d \n " , total_errors ) ;
return total_errors ;
}