2000-05-09 15:43:00 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-05-09 15:43:00 +04:00
Windows NT Domain nsswitch module
Copyright ( C ) Tim Potter 2000
This library is free software ; you can redistribute it and / or
2007-07-10 08:04:46 +04:00
modify it under the terms of the GNU Lesser General Public
2000-05-09 15:43:00 +04:00
License as published by the Free Software Foundation ; either
2007-07-10 06:31:50 +04:00
version 3 of the License , or ( at your option ) any later version .
2000-05-09 15:43:00 +04:00
This library 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
Library General Public License for more details .
2007-07-10 08:04:46 +04:00
You should have received a copy of the GNU Lesser General Public License
2007-07-10 06:31:50 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-05-09 15:43:00 +04:00
*/
2002-09-07 09:41:23 +04:00
# include "winbind_client.h"
2000-05-09 15:43:00 +04:00
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD_H
# include <pthread.h>
# endif
# if HAVE_PTHREAD
static pthread_mutex_t winbind_nss_mutex = PTHREAD_MUTEX_INITIALIZER ;
# endif
2003-03-31 08:36:01 +04:00
/* Maximum number of users to pass back over the unix domain socket
per call . This is not a static limit on the total number of users
or groups returned in total . */
2001-12-22 03:51:32 +03:00
# define MAX_GETPWENT_USERS 250
# define MAX_GETGRENT_USERS 250
2006-12-20 04:10:04 +03:00
NSS_STATUS _nss_winbind_setpwent ( void ) ;
NSS_STATUS _nss_winbind_endpwent ( void ) ;
NSS_STATUS _nss_winbind_getpwent_r ( struct passwd * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_getpwuid_r ( uid_t uid , struct passwd * result ,
char * buffer , size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_getpwnam_r ( const char * name , struct passwd * result ,
char * buffer , size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_setgrent ( void ) ;
NSS_STATUS _nss_winbind_endgrent ( void ) ;
NSS_STATUS _nss_winbind_getgrent_r ( struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_getgrlst_r ( struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_getgrnam_r ( const char * name , struct group * result ,
char * buffer , size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_getgrgid_r ( gid_t gid , struct group * result , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_initgroups_dyn ( char * user , gid_t group , long int * start ,
long int * size , gid_t * * groups ,
long int limit , int * errnop ) ;
NSS_STATUS _nss_winbind_getusersids ( const char * user_sid , char * * group_sids ,
int * num_groups , char * buffer , size_t buf_size ,
int * errnop ) ;
NSS_STATUS _nss_winbind_nametosid ( const char * name , char * * sid , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_sidtoname ( const char * sid , char * * name , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_sidtouid ( const char * sid , uid_t * uid , int * errnop ) ;
NSS_STATUS _nss_winbind_sidtogid ( const char * sid , gid_t * gid , int * errnop ) ;
NSS_STATUS _nss_winbind_uidtosid ( uid_t uid , char * * sid , char * buffer ,
size_t buflen , int * errnop ) ;
NSS_STATUS _nss_winbind_gidtosid ( gid_t gid , char * * sid , char * buffer ,
size_t buflen , int * errnop ) ;
2001-12-22 03:51:32 +03:00
/* Prototypes from wb_common.c */
2000-05-09 15:43:00 +04:00
/* Allocate some space from the nss static buffer. The buffer and buflen
are the pointers passed in by the C library to the _nss_ntdom_ *
functions . */
2004-02-03 00:14:55 +03:00
static char * get_static ( char * * buffer , size_t * buflen , size_t len )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
char * result ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Error check. We return false if things aren't set up right, or
there isn ' t enough buffer space left . */
2007-12-08 04:32:32 +03:00
2001-04-25 09:47:50 +04:00
if ( ( buffer = = NULL ) | | ( buflen = = NULL ) | | ( * buflen < len ) ) {
return NULL ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Return an index into the static buffer */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
result = * buffer ;
* buffer + = len ;
* buflen - = len ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return result ;
2000-05-09 15:43:00 +04:00
}
2007-12-08 04:32:32 +03:00
/* I've copied the strtok() replacement function next_token_Xalloc() from
2000-05-09 15:43:00 +04:00
lib / util_str . c as I really don ' t want to have to link in any other
objects if I can possibly avoid it . */
2007-12-08 04:32:32 +03:00
static bool next_token_alloc ( const char * * ptr ,
char * * pp_buff ,
const char * sep )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
char * s ;
2007-12-08 04:32:32 +03:00
char * saved_s ;
char * pbuf ;
2007-09-13 18:14:02 +04:00
bool quoted ;
2001-04-25 09:47:50 +04:00
size_t len = 1 ;
2001-06-21 13:10:42 +04:00
2007-12-08 04:32:32 +03:00
* pp_buff = NULL ;
if ( ! ptr ) {
return ( false ) ;
}
2001-06-21 13:10:42 +04:00
2007-12-08 04:32:32 +03:00
s = ( char * ) * ptr ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
/* default to simple separators */
2007-12-08 04:32:32 +03:00
if ( ! sep ) {
sep = " \t \n \r " ;
}
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
/* find the first non sep char */
2007-12-08 04:32:32 +03:00
while ( * s & & strchr ( sep , * s ) ) {
s + + ;
}
2001-04-25 09:47:50 +04:00
/* nothing left? */
2007-12-08 04:32:32 +03:00
if ( ! * s ) {
return false ;
}
/* When restarting we need to go from here. */
saved_s = s ;
/* Work out the length needed. */
for ( quoted = false ; * s & &
( quoted | | ! strchr ( sep , * s ) ) ; s + + ) {
2001-04-25 09:47:50 +04:00
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
len + + ;
}
}
2007-12-08 04:32:32 +03:00
/* We started with len = 1 so we have space for the nul. */
2008-04-06 14:26:15 +04:00
* pp_buff = ( char * ) malloc ( len ) ;
2007-12-08 04:32:32 +03:00
if ( ! * pp_buff ) {
return false ;
}
/* copy over the token */
pbuf = * pp_buff ;
s = saved_s ;
for ( quoted = false ; * s & &
( quoted | | ! strchr ( sep , * s ) ) ; s + + ) {
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
* pbuf + + = * s ;
}
}
* ptr = ( * s ) ? s + 1 : s ;
* pbuf = 0 ;
2007-09-13 18:14:02 +04:00
return true ;
2000-05-09 15:43:00 +04:00
}
/* Fill a pwent structure from a winbindd_response structure. We use
the static data passed to us by libc to put strings and stuff in .
2001-04-25 09:47:50 +04:00
Return NSS_STATUS_TRYAGAIN if we run out of memory . */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
static NSS_STATUS fill_pwent ( struct passwd * result ,
struct winbindd_pw * pw ,
2002-07-15 14:54:35 +04:00
char * * buffer , size_t * buflen )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
/* User name */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( result - > pw_name =
get_static ( buffer , buflen , strlen ( pw - > pw_name ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > pw_name , pw - > pw_name ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Password */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( result - > pw_passwd =
get_static ( buffer , buflen , strlen ( pw - > pw_passwd ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > pw_passwd , pw - > pw_passwd ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* [ug]id */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
result - > pw_uid = pw - > pw_uid ;
result - > pw_gid = pw - > pw_gid ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* GECOS */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( result - > pw_gecos =
get_static ( buffer , buflen , strlen ( pw - > pw_gecos ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > pw_gecos , pw - > pw_gecos ) ;
/* Home directory */
if ( ( result - > pw_dir =
get_static ( buffer , buflen , strlen ( pw - > pw_dir ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > pw_dir , pw - > pw_dir ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Logon shell */
if ( ( result - > pw_shell =
get_static ( buffer , buflen , strlen ( pw - > pw_shell ) + 1 ) ) = = NULL ) {
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > pw_shell , pw - > pw_shell ) ;
2000-05-09 15:43:00 +04:00
2002-05-10 07:02:22 +04:00
/* The struct passwd for Solaris has some extra fields which must
be initialised or nscd crashes . */
# if HAVE_PASSWD_PW_COMMENT
result - > pw_comment = " " ;
# endif
# if HAVE_PASSWD_PW_AGE
result - > pw_age = " " ;
# endif
2001-04-25 09:47:50 +04:00
return NSS_STATUS_SUCCESS ;
2000-05-09 15:43:00 +04:00
}
/* Fill a grent structure from a winbindd_response structure. We use
the static data passed to us by libc to put strings and stuff in .
2001-04-25 09:47:50 +04:00
Return NSS_STATUS_TRYAGAIN if we run out of memory . */
2000-05-09 15:43:00 +04:00
2002-07-15 14:54:35 +04:00
static NSS_STATUS fill_grent ( struct group * result , struct winbindd_gr * gr ,
char * gr_mem , char * * buffer , size_t * buflen )
2000-05-09 15:43:00 +04:00
{
2007-12-08 04:32:32 +03:00
char * name ;
2001-04-25 09:47:50 +04:00
int i ;
2001-12-22 03:51:32 +03:00
char * tst ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Group name */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( result - > gr_name =
get_static ( buffer , buflen , strlen ( gr - > gr_name ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > gr_name , gr - > gr_name ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Password */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( result - > gr_passwd =
get_static ( buffer , buflen , strlen ( gr - > gr_passwd ) + 1 ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
return NSS_STATUS_TRYAGAIN ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strcpy ( result - > gr_passwd , gr - > gr_passwd ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* gid */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
result - > gr_gid = gr - > gr_gid ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Group membership */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( gr - > num_gr_mem < 0 ) | | ! gr_mem ) {
gr - > num_gr_mem = 0 ;
}
2000-05-09 15:43:00 +04:00
2001-12-22 03:51:32 +03:00
/* this next value is a pointer to a pointer so let's align it */
/* Calculate number of extra bytes needed to align on pointer size boundry */
2002-07-15 14:54:35 +04:00
if ( ( i = ( unsigned long ) ( * buffer ) % sizeof ( char * ) ) ! = 0 )
2001-12-22 03:51:32 +03:00
i = sizeof ( char * ) - i ;
2007-12-08 04:32:32 +03:00
if ( ( tst = get_static ( buffer , buflen , ( ( gr - > num_gr_mem + 1 ) *
2001-12-22 03:51:32 +03:00
sizeof ( char * ) + i ) ) ) = = NULL ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Out of memory */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return NSS_STATUS_TRYAGAIN ;
}
2001-12-22 03:51:32 +03:00
result - > gr_mem = ( char * * ) ( tst + i ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( gr - > num_gr_mem = = 0 ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Group is empty */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
* ( result - > gr_mem ) = NULL ;
return NSS_STATUS_SUCCESS ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Start looking at extra data */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
i = 0 ;
2000-05-09 15:43:00 +04:00
2007-12-08 04:32:32 +03:00
while ( next_token_alloc ( ( const char * * ) & gr_mem , & name , " , " ) ) {
2001-04-25 09:47:50 +04:00
/* Allocate space for member */
2007-12-08 04:32:32 +03:00
if ( ( ( result - > gr_mem ) [ i ] =
2001-04-25 09:47:50 +04:00
get_static ( buffer , buflen , strlen ( name ) + 1 ) ) = = NULL ) {
2007-12-08 04:32:32 +03:00
free ( name ) ;
2001-04-25 09:47:50 +04:00
/* Out of memory */
return NSS_STATUS_TRYAGAIN ;
2007-12-08 04:32:32 +03:00
}
2001-04-25 09:47:50 +04:00
strcpy ( ( result - > gr_mem ) [ i ] , name ) ;
2007-12-08 04:32:32 +03:00
free ( name ) ;
2001-04-25 09:47:50 +04:00
i + + ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Terminate list */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
( result - > gr_mem ) [ i ] = NULL ;
return NSS_STATUS_SUCCESS ;
2000-05-09 15:43:00 +04:00
}
/*
* NSS user functions
*/
2001-04-25 09:47:50 +04:00
static struct winbindd_response getpwent_response ;
static int ndx_pw_cache ; /* Current index into pwd cache */
static int num_pw_cache ; /* Current size of pwd cache */
2000-05-09 15:43:00 +04:00
/* Rewind "file pointer" to start of ntdom password database */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_setpwent ( void )
2000-05-09 15:43:00 +04:00
{
2007-02-15 14:44:06 +03:00
NSS_STATUS ret ;
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setpwent \n " , getpid ( ) ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
if ( num_pw_cache > 0 ) {
ndx_pw_cache = num_pw_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getpwent_response ) ;
2001-04-25 09:47:50 +04:00
}
2007-02-15 14:44:06 +03:00
ret = winbindd_request_response ( WINBINDD_SETPWENT , NULL , NULL ) ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setpwent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2007-02-15 14:44:06 +03:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Close ntdom password database "file pointer" */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_endpwent ( void )
2000-05-09 15:43:00 +04:00
{
2007-02-15 14:44:06 +03:00
NSS_STATUS ret ;
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: endpwent \n " , getpid ( ) ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
if ( num_pw_cache > 0 ) {
ndx_pw_cache = num_pw_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getpwent_response ) ;
2001-04-25 09:47:50 +04:00
}
2007-02-15 14:44:06 +03:00
ret = winbindd_request_response ( WINBINDD_ENDPWENT , NULL , NULL ) ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: endpwent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2007-02-15 14:44:06 +03:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Fetch the next password entry from ntdom password database */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getpwent_r ( struct passwd * result , char * buffer ,
2001-04-25 09:47:50 +04:00
size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
struct winbindd_request request ;
static int called_again ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getpwent \n " , getpid ( ) ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
/* Return an entry from the cache if we have one, or if we are
called again because we exceeded our static buffer . */
if ( ( ndx_pw_cache < num_pw_cache ) | | called_again ) {
goto return_result ;
}
/* Else call winbindd to get a bunch of entries */
if ( num_pw_cache > 0 ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getpwent_response ) ;
2001-04-25 09:47:50 +04:00
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( getpwent_response ) ;
request . data . num_entries = MAX_GETPWENT_USERS ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETPWENT , & request ,
2001-04-25 09:47:50 +04:00
& getpwent_response ) ;
if ( ret = = NSS_STATUS_SUCCESS ) {
struct winbindd_pw * pw_cache ;
/* Fill cache */
ndx_pw_cache = 0 ;
num_pw_cache = getpwent_response . data . num_entries ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Return a result */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return_result :
2006-08-01 16:45:12 +04:00
pw_cache = ( struct winbindd_pw * )
getpwent_response . extra_data . data ;
2001-04-25 09:47:50 +04:00
/* Check data is valid */
if ( pw_cache = = NULL ) {
2007-02-15 14:44:06 +03:00
ret = NSS_STATUS_NOTFOUND ;
goto done ;
2001-04-25 09:47:50 +04:00
}
ret = fill_pwent ( result , & pw_cache [ ndx_pw_cache ] ,
& buffer , & buflen ) ;
/* Out of memory - try again */
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
called_again = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
* errnop = errno = 0 ;
2007-09-13 18:14:02 +04:00
called_again = false ;
2001-04-25 09:47:50 +04:00
ndx_pw_cache + + ;
/* If we've finished with this lot of results free cache */
if ( ndx_pw_cache = = num_pw_cache ) {
ndx_pw_cache = num_pw_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getpwent_response ) ;
2001-04-25 09:47:50 +04:00
}
}
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getpwent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Return passwd struct from uid */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getpwuid_r ( uid_t uid , struct passwd * result , char * buffer ,
2001-04-25 09:47:50 +04:00
size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
static struct winbindd_response response ;
2000-05-09 15:43:00 +04:00
struct winbindd_request request ;
2007-09-28 22:12:22 +04:00
static int keep_response ;
2001-04-25 09:47:50 +04:00
2007-02-15 14:44:06 +03:00
# ifdef DEBUG_NSS
2007-09-28 22:12:22 +04:00
fprintf ( stderr , " [%5d]: getpwuid_r %d \n " , getpid ( ) , ( unsigned int ) uid ) ;
# endif
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
2007-02-15 14:44:06 +03:00
# endif
2001-04-25 09:47:50 +04:00
/* If our static buffer needs to be expanded we are called again */
2007-09-28 22:12:22 +04:00
if ( ! keep_response | | uid ! = response . data . pw . pw_uid ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Call for the first time */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
request . data . uid = uid ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETPWUID , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_pwent ( result , & response . data . pw ,
& buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
}
} else {
/* We've been called again */
ret = fill_pwent ( result , & response . data . pw , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
2007-09-13 18:14:02 +04:00
keep_response = false ;
2001-04-25 09:47:50 +04:00
* errnop = errno = 0 ;
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getpwuid %d returns %s (%d) \n " , getpid ( ) ,
( unsigned int ) uid , nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Return passwd struct from username */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getpwnam_r ( const char * name , struct passwd * result , char * buffer ,
2001-04-25 09:47:50 +04:00
size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
static struct winbindd_response response ;
2000-05-09 15:43:00 +04:00
struct winbindd_request request ;
2001-04-25 09:47:50 +04:00
static int keep_response ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
2007-09-28 22:12:22 +04:00
fprintf ( stderr , " [%5d]: getpwnam_r %s \n " , getpid ( ) , name ) ;
# endif
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
2001-04-25 09:47:50 +04:00
# endif
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* If our static buffer needs to be expanded we are called again */
2000-05-09 15:43:00 +04:00
2007-09-28 22:12:22 +04:00
if ( ! keep_response | | strcmp ( name , response . data . pw . pw_name ) ! = 0 ) {
2001-04-25 09:47:50 +04:00
/* Call for the first time */
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
strncpy ( request . data . username , name ,
sizeof ( request . data . username ) - 1 ) ;
request . data . username
[ sizeof ( request . data . username ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETPWNAM , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_pwent ( result , & response . data . pw , & buffer ,
& buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
}
} else {
/* We've been called again */
ret = fill_pwent ( result , & response . data . pw , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
2007-09-13 18:14:02 +04:00
keep_response = false ;
2001-04-25 09:47:50 +04:00
* errnop = errno = 0 ;
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getpwnam %s returns %s (%d) \n " , getpid ( ) ,
name , nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/*
* NSS group functions
*/
2001-04-25 09:47:50 +04:00
static struct winbindd_response getgrent_response ;
static int ndx_gr_cache ; /* Current index into grp cache */
static int num_gr_cache ; /* Current size of grp cache */
2000-05-09 15:43:00 +04:00
/* Rewind "file pointer" to start of ntdom group database */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_setgrent ( void )
2000-05-09 15:43:00 +04:00
{
2007-02-15 14:44:06 +03:00
NSS_STATUS ret ;
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setgrent \n " , getpid ( ) ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
if ( num_gr_cache > 0 ) {
ndx_gr_cache = num_gr_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getgrent_response ) ;
2001-04-25 09:47:50 +04:00
}
2007-02-15 14:44:06 +03:00
ret = winbindd_request_response ( WINBINDD_SETGRENT , NULL , NULL ) ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setgrent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2007-02-15 14:44:06 +03:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Close "file pointer" for ntdom group database */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_endgrent ( void )
2000-05-09 15:43:00 +04:00
{
2007-02-15 14:44:06 +03:00
NSS_STATUS ret ;
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: endgrent \n " , getpid ( ) ) ;
# endif
2000-05-09 15:43:00 +04:00
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
if ( num_gr_cache > 0 ) {
ndx_gr_cache = num_gr_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getgrent_response ) ;
2001-04-25 09:47:50 +04:00
}
2000-05-09 15:43:00 +04:00
2007-02-15 14:44:06 +03:00
ret = winbindd_request_response ( WINBINDD_ENDGRENT , NULL , NULL ) ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: endgrent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2007-02-15 14:44:06 +03:00
return ret ;
2001-04-25 09:47:50 +04:00
}
2000-05-09 15:43:00 +04:00
/* Get next entry from ntdom group database */
2002-07-15 03:45:55 +04:00
static NSS_STATUS
winbind_getgrent ( enum winbindd_cmd cmd ,
struct group * result ,
char * buffer , size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
static struct winbindd_request request ;
static int called_again ;
2002-07-15 03:45:55 +04:00
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrent \n " , getpid ( ) ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
/* Return an entry from the cache if we have one, or if we are
called again because we exceeded our static buffer . */
if ( ( ndx_gr_cache < num_gr_cache ) | | called_again ) {
goto return_result ;
}
/* Else call winbindd to get a bunch of entries */
if ( num_gr_cache > 0 ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getgrent_response ) ;
2001-04-25 09:47:50 +04:00
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( getgrent_response ) ;
request . data . num_entries = MAX_GETGRENT_USERS ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( cmd , & request ,
2001-04-25 09:47:50 +04:00
& getgrent_response ) ;
if ( ret = = NSS_STATUS_SUCCESS ) {
struct winbindd_gr * gr_cache ;
int mem_ofs ;
/* Fill cache */
ndx_gr_cache = 0 ;
num_gr_cache = getgrent_response . data . num_entries ;
/* Return a result */
return_result :
2006-08-01 16:45:12 +04:00
gr_cache = ( struct winbindd_gr * )
getgrent_response . extra_data . data ;
2001-04-25 09:47:50 +04:00
/* Check data is valid */
if ( gr_cache = = NULL ) {
2007-02-15 14:44:06 +03:00
ret = NSS_STATUS_NOTFOUND ;
goto done ;
2001-04-25 09:47:50 +04:00
}
/* Fill group membership. The offset into the extra data
for the group membership is the reported offset plus the
size of all the winbindd_gr records returned . */
mem_ofs = gr_cache [ ndx_gr_cache ] . gr_mem_ofs +
num_gr_cache * sizeof ( struct winbindd_gr ) ;
ret = fill_grent ( result , & gr_cache [ ndx_gr_cache ] ,
2006-04-12 18:10:39 +04:00
( ( char * ) getgrent_response . extra_data . data ) + mem_ofs ,
2001-06-05 06:00:47 +04:00
& buffer , & buflen ) ;
2001-04-25 09:47:50 +04:00
/* Out of memory - try again */
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
called_again = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
* errnop = 0 ;
2007-09-13 18:14:02 +04:00
called_again = false ;
2001-04-25 09:47:50 +04:00
ndx_gr_cache + + ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* If we've finished with this lot of results free cache */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ndx_gr_cache = = num_gr_cache ) {
ndx_gr_cache = num_gr_cache = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & getgrent_response ) ;
2001-04-25 09:47:50 +04:00
}
}
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrent returns %s (%d) \n " , getpid ( ) ,
nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
2002-07-15 03:45:55 +04:00
NSS_STATUS
_nss_winbind_getgrent_r ( struct group * result ,
char * buffer , size_t buflen , int * errnop )
{
return winbind_getgrent ( WINBINDD_GETGRENT , result , buffer , buflen , errnop ) ;
}
NSS_STATUS
_nss_winbind_getgrlst_r ( struct group * result ,
char * buffer , size_t buflen , int * errnop )
{
return winbind_getgrent ( WINBINDD_GETGRLST , result , buffer , buflen , errnop ) ;
}
2000-05-09 15:43:00 +04:00
/* Return group struct from group name */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getgrnam_r ( const char * name ,
2001-04-25 09:47:50 +04:00
struct group * result , char * buffer ,
size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
static struct winbindd_response response ;
2000-05-09 15:43:00 +04:00
struct winbindd_request request ;
2001-04-25 09:47:50 +04:00
static int keep_response ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrnam %s \n " , getpid ( ) , name ) ;
# endif
2000-05-09 15:43:00 +04:00
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
/* If our static buffer needs to be expanded we are called again */
2007-09-28 22:12:22 +04:00
/* Or if the stored response group name differs from the request. */
if ( ! keep_response | | strcmp ( name , response . data . gr . gr_name ) ! = 0 ) {
2001-04-25 09:47:50 +04:00
/* Call for the first time */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . groupname , name ,
sizeof ( request . data . groupname ) ) ;
request . data . groupname
[ sizeof ( request . data . groupname ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETGRNAM , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_grent ( result , & response . data . gr ,
2006-08-01 16:45:12 +04:00
( char * ) response . extra_data . data ,
2001-04-25 09:47:50 +04:00
& buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
}
} else {
2007-09-28 22:12:22 +04:00
2001-04-25 09:47:50 +04:00
/* We've been called again */
2007-09-28 22:12:22 +04:00
2001-04-25 09:47:50 +04:00
ret = fill_grent ( result , & response . data . gr ,
2006-08-01 16:45:12 +04:00
( char * ) response . extra_data . data , & buffer ,
& buflen ) ;
2007-09-28 22:12:22 +04:00
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
2007-09-13 18:14:02 +04:00
keep_response = false ;
2001-04-25 09:47:50 +04:00
* errnop = 0 ;
}
2000-05-09 15:43:00 +04:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrnam %s returns %s (%d) \n " , getpid ( ) ,
name , nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
/* Return group struct from gid */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getgrgid_r ( gid_t gid ,
2001-04-25 09:47:50 +04:00
struct group * result , char * buffer ,
size_t buflen , int * errnop )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
NSS_STATUS ret ;
static struct winbindd_response response ;
struct winbindd_request request ;
static int keep_response ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrgid %d \n " , getpid ( ) , gid ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
/* If our static buffer needs to be expanded we are called again */
2007-09-28 22:12:22 +04:00
/* Or if the stored response group name differs from the request. */
2001-04-25 09:47:50 +04:00
2007-09-28 22:12:22 +04:00
if ( ! keep_response | | gid ! = response . data . gr . gr_gid ) {
2001-04-25 09:47:50 +04:00
/* Call for the first time */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
request . data . gid = gid ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETGRGID , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_grent ( result , & response . data . gr ,
2006-08-01 16:45:12 +04:00
( char * ) response . extra_data . data ,
2001-04-25 09:47:50 +04:00
& buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
}
} else {
/* We've been called again */
ret = fill_grent ( result , & response . data . gr ,
2006-08-01 16:45:12 +04:00
( char * ) response . extra_data . data , & buffer ,
& buflen ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_TRYAGAIN ) {
2007-09-13 18:14:02 +04:00
keep_response = true ;
2001-04-25 09:47:50 +04:00
* errnop = errno = ERANGE ;
2007-02-15 14:44:06 +03:00
goto done ;
2001-04-25 09:47:50 +04:00
}
2007-09-13 18:14:02 +04:00
keep_response = false ;
2001-04-25 09:47:50 +04:00
* errnop = 0 ;
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-02-15 14:44:06 +03:00
done :
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrgid %d returns %s (%d) \n " , getpid ( ) ,
( unsigned int ) gid , nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
}
/* Initialise supplementary groups */
NSS_STATUS
2001-12-03 06:53:57 +03:00
_nss_winbind_initgroups_dyn ( char * user , gid_t group , long int * start ,
long int * size , gid_t * * groups , long int limit ,
int * errnop )
2001-04-25 09:47:50 +04:00
{
NSS_STATUS ret ;
2000-05-09 15:43:00 +04:00
struct winbindd_request request ;
2001-04-25 09:47:50 +04:00
struct winbindd_response response ;
int i ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: initgroups %s (%d) \n " , getpid ( ) ,
user , group ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
strncpy ( request . data . username , user ,
sizeof ( request . data . username ) - 1 ) ;
2000-05-09 15:43:00 +04:00
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETGROUPS , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
int num_gids = response . data . num_entries ;
2006-04-12 18:10:39 +04:00
gid_t * gid_list = ( gid_t * ) response . extra_data . data ;
2001-04-25 09:47:50 +04:00
2007-02-15 15:10:57 +03:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
" and %d gids \n " , getpid ( ) ,
user , num_gids ) ;
# endif
2007-02-16 20:25:54 +03:00
if ( gid_list = = NULL ) {
ret = NSS_STATUS_NOTFOUND ;
goto done ;
}
2007-02-15 15:10:57 +03:00
2001-04-25 09:47:50 +04:00
/* Copy group list to client */
for ( i = 0 ; i < num_gids ; i + + ) {
2007-02-15 15:10:57 +03:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: initgroups %s (%d): "
" processing gid %d \n " , getpid ( ) ,
user , group , gid_list [ i ] ) ;
# endif
2001-04-25 09:47:50 +04:00
/* Skip primary group */
2004-09-21 00:18:19 +04:00
if ( gid_list [ i ] = = group ) {
continue ;
}
2001-04-25 09:47:50 +04:00
2004-09-21 00:18:19 +04:00
/* Filled buffer ? If so, resize. */
if ( * start = = * size ) {
long int newsize ;
gid_t * newgroups ;
newsize = 2 * ( * size ) ;
if ( limit > 0 ) {
if ( * size = = limit ) {
goto done ;
}
2004-09-23 03:27:20 +04:00
if ( newsize > limit ) {
newsize = limit ;
}
2004-09-21 00:18:19 +04:00
}
2006-08-01 16:45:12 +04:00
newgroups = ( gid_t * )
realloc ( ( * groups ) ,
newsize * sizeof ( * * groups ) ) ;
2004-09-21 00:18:19 +04:00
if ( ! newgroups ) {
* errnop = ENOMEM ;
ret = NSS_STATUS_NOTFOUND ;
goto done ;
}
* groups = newgroups ;
* size = newsize ;
2001-04-25 09:47:50 +04:00
}
2004-09-21 00:18:19 +04:00
/* Add to buffer */
2001-12-03 06:53:57 +03:00
( * groups ) [ * start ] = gid_list [ i ] ;
2001-04-25 09:47:50 +04:00
* start + = 1 ;
}
}
/* Back to your regularly scheduled programming */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
done :
2007-02-15 14:44:06 +03:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: initgroups %s returns %s (%d) \n " , getpid ( ) ,
user , nss_err_str ( ret ) , ret ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2001-04-25 09:47:50 +04:00
return ret ;
2000-05-09 15:43:00 +04:00
}
2003-11-19 11:11:14 +03:00
/* return a list of group SIDs for a user SID */
NSS_STATUS
_nss_winbind_getusersids ( const char * user_sid , char * * group_sids ,
int * num_groups ,
char * buffer , size_t buf_size , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_request request ;
struct winbindd_response response ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getusersids %s \n " , getpid ( ) , user_sid ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2003-11-19 11:11:14 +03:00
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . sid , user_sid , sizeof ( request . data . sid ) - 1 ) ;
request . data . sid [ sizeof ( request . data . sid ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GETUSERSIDS , & request , & response ) ;
2003-11-19 11:11:14 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
goto done ;
}
if ( buf_size < response . length - sizeof ( response ) ) {
ret = NSS_STATUS_TRYAGAIN ;
errno = * errnop = ERANGE ;
goto done ;
}
* num_groups = response . data . num_entries ;
* group_sids = buffer ;
2006-04-12 18:10:39 +04:00
memcpy ( buffer , response . extra_data . data , response . length - sizeof ( response ) ) ;
2003-11-19 11:11:14 +03:00
errno = * errnop = 0 ;
done :
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2003-11-19 11:11:14 +03:00
return ret ;
}
/* map a user or group name to a SID string */
NSS_STATUS
_nss_winbind_nametosid ( const char * name , char * * sid , char * buffer ,
size_t buflen , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: nametosid %s \n " , getpid ( ) , name ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2003-11-19 11:11:14 +03:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
strncpy ( request . data . name . name , name ,
sizeof ( request . data . name . name ) - 1 ) ;
request . data . name . name [ sizeof ( request . data . name . name ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_LOOKUPNAME , & request , & response ) ;
2003-11-19 11:11:14 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
if ( buflen < strlen ( response . data . sid . sid ) + 1 ) {
ret = NSS_STATUS_TRYAGAIN ;
* errnop = errno = ERANGE ;
goto failed ;
}
* errnop = errno = 0 ;
* sid = buffer ;
strcpy ( * sid , response . data . sid . sid ) ;
failed :
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2003-11-19 11:11:14 +03:00
return ret ;
}
/* map a sid string to a user or group name */
NSS_STATUS
_nss_winbind_sidtoname ( const char * sid , char * * name , char * buffer ,
size_t buflen , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
static char sep_char ;
unsigned needed ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: sidtoname %s \n " , getpid ( ) , sid ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2005-02-10 16:36:18 +03:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-11-19 11:11:14 +03:00
/* we need to fetch the separator first time through */
if ( ! sep_char ) {
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_INFO , & request , & response ) ;
2003-11-19 11:11:14 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
sep_char = response . data . info . winbind_separator ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-11-19 11:11:14 +03:00
}
strncpy ( request . data . sid , sid ,
sizeof ( request . data . sid ) - 1 ) ;
request . data . sid [ sizeof ( request . data . sid ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_LOOKUPSID , & request , & response ) ;
2003-11-19 11:11:14 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
needed =
strlen ( response . data . name . dom_name ) +
strlen ( response . data . name . name ) + 2 ;
if ( buflen < needed ) {
ret = NSS_STATUS_TRYAGAIN ;
* errnop = errno = ERANGE ;
goto failed ;
}
snprintf ( buffer , needed , " %s%c%s " ,
response . data . name . dom_name ,
sep_char ,
response . data . name . name ) ;
* name = buffer ;
* errnop = errno = 0 ;
failed :
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2003-11-19 11:11:14 +03:00
return ret ;
}
2004-01-16 16:11:01 +03:00
/* map a sid to a uid */
NSS_STATUS
_nss_winbind_sidtouid ( const char * sid , uid_t * uid , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: sidtouid %s \n " , getpid ( ) , sid ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . sid , sid , sizeof ( request . data . sid ) - 1 ) ;
request . data . sid [ sizeof ( request . data . sid ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_SID_TO_UID , & request , & response ) ;
2004-01-16 16:11:01 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
* uid = response . data . uid ;
failed :
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
return ret ;
}
/* map a sid to a gid */
NSS_STATUS
_nss_winbind_sidtogid ( const char * sid , gid_t * gid , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: sidtogid %s \n " , getpid ( ) , sid ) ;
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . sid , sid , sizeof ( request . data . sid ) - 1 ) ;
request . data . sid [ sizeof ( request . data . sid ) - 1 ] = ' \0 ' ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_SID_TO_GID , & request , & response ) ;
2004-01-16 16:11:01 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
* gid = response . data . gid ;
failed :
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
2007-10-04 00:56:29 +04:00
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
2007-09-28 22:12:22 +04:00
# endif
2004-01-16 16:11:01 +03:00
return ret ;
}
/* map a uid to a SID string */
NSS_STATUS
_nss_winbind_uidtosid ( uid_t uid , char * * sid , char * buffer ,
size_t buflen , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
# ifdef DEBUG_NSS
2004-02-03 00:14:55 +03:00
fprintf ( stderr , " [%5u]: uidtosid %u \n " , ( unsigned int ) getpid ( ) , ( unsigned int ) uid ) ;
2004-01-16 16:11:01 +03:00
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
request . data . uid = uid ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_UID_TO_SID , & request , & response ) ;
2004-01-16 16:11:01 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
if ( buflen < strlen ( response . data . sid . sid ) + 1 ) {
ret = NSS_STATUS_TRYAGAIN ;
* errnop = errno = ERANGE ;
goto failed ;
}
* errnop = errno = 0 ;
* sid = buffer ;
strcpy ( * sid , response . data . sid . sid ) ;
failed :
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
return ret ;
}
/* map a gid to a SID string */
NSS_STATUS
_nss_winbind_gidtosid ( gid_t gid , char * * sid , char * buffer ,
size_t buflen , int * errnop )
{
NSS_STATUS ret ;
struct winbindd_response response ;
struct winbindd_request request ;
# ifdef DEBUG_NSS
2004-02-03 00:14:55 +03:00
fprintf ( stderr , " [%5u]: gidtosid %u \n " , ( unsigned int ) getpid ( ) , ( unsigned int ) gid ) ;
2004-01-16 16:11:01 +03:00
# endif
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_lock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
request . data . gid = gid ;
2005-06-25 00:25:18 +04:00
ret = winbindd_request_response ( WINBINDD_GID_TO_SID , & request , & response ) ;
2004-01-16 16:11:01 +03:00
if ( ret ! = NSS_STATUS_SUCCESS ) {
* errnop = errno = EINVAL ;
goto failed ;
}
if ( buflen < strlen ( response . data . sid . sid ) + 1 ) {
ret = NSS_STATUS_TRYAGAIN ;
* errnop = errno = ERANGE ;
goto failed ;
}
* errnop = errno = 0 ;
* sid = buffer ;
strcpy ( * sid , response . data . sid . sid ) ;
failed :
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2007-09-28 22:12:22 +04:00
# if HAVE_PTHREAD
pthread_mutex_unlock ( & winbind_nss_mutex ) ;
# endif
2004-01-16 16:11:01 +03:00
return ret ;
}