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
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
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 .
You should have received a copy of the GNU Library General Public
License along with this library ; if not , write to the
Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
Boston , MA 02111 - 1307 , USA .
*/
2000-05-10 18:17:21 +04:00
# include "winbind_nss_config.h"
# include "winbindd_nss.h"
2000-05-09 15:43:00 +04:00
2001-12-22 03:51:32 +03:00
# ifdef HAVE_NS_API_H
# undef VOLATILE
# include <ns_daemon.h>
# endif
# define MAX_GETPWENT_USERS 250
# define MAX_GETGRENT_USERS 250
/* Prototypes from wb_common.c */
extern int winbindd_fd ;
2001-04-25 09:47:50 +04:00
2000-05-09 15:43:00 +04:00
void init_request ( struct winbindd_request * req , int rq_type ) ;
2001-12-22 03:51:32 +03:00
NSS_STATUS winbindd_send_request ( int req_type ,
struct winbindd_request * request ) ;
NSS_STATUS winbindd_get_response ( struct winbindd_response * response ) ;
2001-04-25 09:47:50 +04:00
NSS_STATUS winbindd_request ( int req_type ,
struct winbindd_request * request ,
struct winbindd_response * response ) ;
2001-12-22 03:51:32 +03:00
int winbind_open_pipe_sock ( void ) ;
2000-05-09 15:43:00 +04:00
int write_sock ( void * buffer , int count ) ;
int read_reply ( struct winbindd_response * response ) ;
2001-04-25 09:47:50 +04:00
void free_response ( struct winbindd_response * response ) ;
2000-05-09 15:43:00 +04:00
2001-12-22 03:51:32 +03:00
# ifdef HAVE_NS_API_H
/* IRIX version */
static int send_next_request ( nsd_file_t * , struct winbindd_request * ) ;
static int do_list ( int state , nsd_file_t * rq ) ;
static nsd_file_t * current_rq = NULL ;
static int current_winbind_xid = 0 ;
static int next_winbind_xid = 0 ;
typedef struct winbind_xid {
int xid ;
nsd_file_t * rq ;
struct winbindd_request * request ;
struct winbind_xid * next ;
} winbind_xid_t ;
static winbind_xid_t * winbind_xids = ( winbind_xid_t * ) 0 ;
static int
winbind_xid_new ( int xid , nsd_file_t * rq , struct winbindd_request * request )
{
winbind_xid_t * new ;
nsd_logprintf ( NSD_LOG_LOW ,
" entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x \n " ,
xid , rq , request ) ;
new = ( winbind_xid_t * ) nsd_calloc ( 1 , sizeof ( winbind_xid_t ) ) ;
if ( ! new ) {
nsd_logprintf ( NSD_LOG_RESOURCE , " winbind_xid_new: failed malloc \n " ) ;
return NSD_ERROR ;
}
new - > xid = xid ;
new - > rq = rq ;
new - > request = request ;
new - > next = winbind_xids ;
winbind_xids = new ;
return NSD_CONTINUE ;
}
/*
* * This routine will look down the xid list and return the request
* * associated with an xid . We remove the record if it is found .
*/
nsd_file_t *
winbind_xid_lookup ( int xid , struct winbindd_request * * requestp )
{
winbind_xid_t * * last , * dx ;
nsd_file_t * result = 0 ;
for ( last = & winbind_xids , dx = winbind_xids ; dx & & ( dx - > xid ! = xid ) ;
last = & dx - > next , dx = dx - > next ) ;
if ( dx ) {
* last = dx - > next ;
result = dx - > rq ;
* requestp = dx - > request ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( dx ) ;
2001-12-22 03:51:32 +03:00
}
nsd_logprintf ( NSD_LOG_LOW ,
" entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x \n " ,
xid , result , dx - > request ) ;
return result ;
}
static int
winbind_startnext_timeout ( nsd_file_t * * rqp , nsd_times_t * to )
{
nsd_file_t * rq ;
struct winbindd_request * request ;
nsd_logprintf ( NSD_LOG_MIN , " timeout (winbind startnext) \n " ) ;
rq = to - > t_file ;
* rqp = rq ;
nsd_timeout_remove ( rq ) ;
request = to - > t_clientdata ;
return ( send_next_request ( rq , request ) ) ;
}
static void
dequeue_request ( )
{
nsd_file_t * rq ;
struct winbindd_request * request ;
/*
* Check for queued requests
*/
if ( winbind_xids ) {
nsd_logprintf ( NSD_LOG_MIN , " timeout (winbind) unqueue xid %d \n " ,
current_winbind_xid ) ;
rq = winbind_xid_lookup ( current_winbind_xid + + , & request ) ;
/* cause a timeout on the queued request so we can send it */
nsd_timeout_new ( rq , 1 , winbind_startnext_timeout , request ) ;
}
}
static int
do_request ( nsd_file_t * rq , struct winbindd_request * request )
{
if ( winbind_xids = = NULL ) {
/*
* No outstanding requests .
* Send off the request to winbindd
*/
nsd_logprintf ( NSD_LOG_MIN , " lookup (winbind) sending request \n " ) ;
return ( send_next_request ( rq , request ) ) ;
} else {
/*
* Just queue it up for now - previous callout or timout
* will start it up
*/
nsd_logprintf ( NSD_LOG_MIN ,
" lookup (winbind): queue request xid = %d \n " ,
next_winbind_xid ) ;
return ( winbind_xid_new ( next_winbind_xid + + , rq , request ) ) ;
}
}
static int
winbind_callback ( nsd_file_t * * rqp , int fd )
{
struct winbindd_response response ;
struct winbindd_pw * pw = & response . data . pw ;
struct winbindd_gr * gr = & response . data . gr ;
nsd_file_t * rq ;
NSS_STATUS status ;
2002-03-29 18:37:39 +03:00
fstring result ;
2001-12-22 03:51:32 +03:00
char * members ;
2002-03-29 18:37:39 +03:00
int i , maxlen ;
2001-12-22 03:51:32 +03:00
dequeue_request ( ) ;
nsd_logprintf ( NSD_LOG_MIN , " entering callback (winbind) \n " ) ;
rq = current_rq ;
* rqp = rq ;
nsd_timeout_remove ( rq ) ;
nsd_callback_remove ( fd ) ;
ZERO_STRUCT ( response ) ;
status = winbindd_get_response ( & response ) ;
if ( status ! = NSS_STATUS_SUCCESS ) {
/* free any extra data area in response structure */
free_response ( & response ) ;
nsd_logprintf ( NSD_LOG_MIN ,
" callback (winbind) returning not found, status = %d \n " ,
status ) ;
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
2002-03-29 18:37:39 +03:00
maxlen = sizeof ( result ) - 1 ;
2001-12-22 03:51:32 +03:00
switch ( ( int ) rq - > f_cmd_data ) {
2002-03-29 18:37:39 +03:00
case WINBINDD_WINS_BYNAME :
case WINBINDD_WINS_BYIP :
snprintf ( result , maxlen , " %s \n " , response . data . winsresp ) ;
break ;
2002-01-10 21:49:37 +03:00
case WINBINDD_GETPWUID :
case WINBINDD_GETPWNAM :
2002-03-29 18:37:39 +03:00
snprintf ( result , maxlen , " %s:%s:%d:%d:%s:%s:%s \n " ,
2001-12-22 03:51:32 +03:00
pw - > pw_name ,
pw - > pw_passwd ,
pw - > pw_uid ,
pw - > pw_gid ,
pw - > pw_gecos ,
pw - > pw_dir ,
pw - > pw_shell ) ;
break ;
2002-01-10 21:49:37 +03:00
case WINBINDD_GETGRNAM :
case WINBINDD_GETGRGID :
2001-12-22 03:51:32 +03:00
if ( gr - > num_gr_mem & & response . extra_data )
members = response . extra_data ;
else
members = " " ;
2002-03-29 18:37:39 +03:00
snprintf ( result , maxlen , " %s:%s:%d:%s \n " ,
2001-12-22 03:51:32 +03:00
gr - > gr_name , gr - > gr_passwd , gr - > gr_gid , members ) ;
break ;
case WINBINDD_SETGRENT :
case WINBINDD_SETPWENT :
nsd_logprintf ( NSD_LOG_MIN , " callback (winbind) - SETPWENT/SETGRENT \n " ) ;
free_response ( & response ) ;
return ( do_list ( 1 , rq ) ) ;
case WINBINDD_GETGRENT :
nsd_logprintf ( NSD_LOG_MIN ,
" callback (winbind) - %d GETGRENT responses \n " ,
response . data . num_entries ) ;
if ( response . data . num_entries ) {
gr = ( struct winbindd_gr * ) response . extra_data ;
if ( ! gr ) {
nsd_logprintf ( NSD_LOG_MIN , " no extra_data \n " ) ;
free_response ( & response ) ;
return NSD_ERROR ;
}
members = ( char * ) response . extra_data +
( response . data . num_entries * sizeof ( struct winbindd_gr ) ) ;
for ( i = 0 ; i < response . data . num_entries ; i + + ) {
2002-03-29 18:37:39 +03:00
snprintf ( result , maxlen , " %s:%s:%d:%s \n " ,
2001-12-22 03:51:32 +03:00
gr - > gr_name , gr - > gr_passwd , gr - > gr_gid ,
& members [ gr - > gr_mem_ofs ] ) ;
nsd_logprintf ( NSD_LOG_MIN , " GETGRENT %s \n " , result ) ;
nsd_append_element ( rq , NS_SUCCESS , result , strlen ( result ) ) ;
gr + + ;
}
}
i = response . data . num_entries ;
free_response ( & response ) ;
if ( i < MAX_GETPWENT_USERS )
return ( do_list ( 2 , rq ) ) ;
else
return ( do_list ( 1 , rq ) ) ;
case WINBINDD_GETPWENT :
nsd_logprintf ( NSD_LOG_MIN ,
" callback (winbind) - %d GETPWENT responses \n " ,
response . data . num_entries ) ;
if ( response . data . num_entries ) {
pw = ( struct winbindd_pw * ) response . extra_data ;
if ( ! pw ) {
nsd_logprintf ( NSD_LOG_MIN , " no extra_data \n " ) ;
free_response ( & response ) ;
return NSD_ERROR ;
}
for ( i = 0 ; i < response . data . num_entries ; i + + ) {
2002-03-29 18:37:39 +03:00
snprintf ( result , maxlen , " %s:%s:%d:%d:%s:%s:%s " ,
2001-12-22 03:51:32 +03:00
pw - > pw_name ,
pw - > pw_passwd ,
pw - > pw_uid ,
pw - > pw_gid ,
pw - > pw_gecos ,
pw - > pw_dir ,
pw - > pw_shell ) ;
nsd_logprintf ( NSD_LOG_MIN , " GETPWENT %s \n " , result ) ;
nsd_append_element ( rq , NS_SUCCESS , result , strlen ( result ) ) ;
pw + + ;
}
}
i = response . data . num_entries ;
free_response ( & response ) ;
if ( i < MAX_GETPWENT_USERS )
return ( do_list ( 2 , rq ) ) ;
else
return ( do_list ( 1 , rq ) ) ;
case WINBINDD_ENDGRENT :
case WINBINDD_ENDPWENT :
nsd_logprintf ( NSD_LOG_MIN , " callback (winbind) - ENDPWENT/ENDGRENT \n " ) ;
nsd_append_element ( rq , NS_SUCCESS , " \n " , 1 ) ;
free_response ( & response ) ;
return NSD_NEXT ;
default :
free_response ( & response ) ;
nsd_logprintf ( NSD_LOG_MIN , " callback (winbind) - no valid command \n " ) ;
return NSD_NEXT ;
}
nsd_logprintf ( NSD_LOG_MIN , " callback (winbind) %s \n " , result ) ;
/* free any extra data area in response structure */
free_response ( & response ) ;
nsd_set_result ( rq , NS_SUCCESS , result , strlen ( result ) , VOLATILE ) ;
return NSD_OK ;
}
static int
winbind_timeout ( nsd_file_t * * rqp , nsd_times_t * to )
{
nsd_file_t * rq ;
dequeue_request ( ) ;
nsd_logprintf ( NSD_LOG_MIN , " timeout (winbind) \n " ) ;
rq = to - > t_file ;
* rqp = rq ;
/* Remove the callback and timeout */
nsd_callback_remove ( winbindd_fd ) ;
nsd_timeout_remove ( rq ) ;
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
static int
send_next_request ( nsd_file_t * rq , struct winbindd_request * request )
{
NSS_STATUS status ;
long timeout ;
timeout = 1000 ;
nsd_logprintf ( NSD_LOG_MIN , " send_next_request (winbind) %d to = %d \n " ,
rq - > f_cmd_data , timeout ) ;
status = winbindd_send_request ( ( int ) rq - > f_cmd_data , request ) ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( request ) ;
2001-12-22 03:51:32 +03:00
if ( status ! = NSS_STATUS_SUCCESS ) {
nsd_logprintf ( NSD_LOG_MIN ,
" send_next_request (winbind) error status = %d \n " , status ) ;
rq - > f_status = status ;
return NSD_NEXT ;
}
current_rq = rq ;
/*
* Set up callback and timeouts
*/
nsd_logprintf ( NSD_LOG_MIN , " send_next_request (winbind) fd = %d \n " , winbindd_fd ) ;
nsd_callback_new ( winbindd_fd , winbind_callback , NSD_READ ) ;
nsd_timeout_new ( rq , timeout , winbind_timeout , ( void * ) 0 ) ;
return NSD_CONTINUE ;
}
int init ( void )
{
nsd_logprintf ( NSD_LOG_MIN , " entering init (winbind) \n " ) ;
return ( NSD_OK ) ;
}
int lookup ( nsd_file_t * rq )
{
char * map ;
char * key ;
struct winbindd_request * request ;
nsd_logprintf ( NSD_LOG_MIN , " entering lookup (winbind) \n " ) ;
if ( ! rq )
return NSD_ERROR ;
map = nsd_attr_fetch_string ( rq - > f_attrs , " table " , ( char * ) 0 ) ;
key = nsd_attr_fetch_string ( rq - > f_attrs , " key " , ( char * ) 0 ) ;
if ( ! map | | ! key ) {
nsd_logprintf ( NSD_LOG_MIN , " lookup (winbind) table or key not defined \n " ) ;
rq - > f_status = NS_BADREQ ;
return NSD_ERROR ;
}
nsd_logprintf ( NSD_LOG_MIN , " lookup (winbind %s) \n " , map ) ;
request = ( struct winbindd_request * ) nsd_calloc ( 1 , sizeof ( struct winbindd_request ) ) ;
if ( ! request ) {
nsd_logprintf ( NSD_LOG_RESOURCE ,
" lookup (winbind): failed malloc \n " ) ;
return NSD_ERROR ;
}
if ( strcasecmp ( map , " passwd.byuid " ) = = 0 ) {
request - > data . uid = atoi ( key ) ;
2002-01-10 21:49:37 +03:00
rq - > f_cmd_data = ( void * ) WINBINDD_GETPWUID ;
2001-12-22 03:51:32 +03:00
} else if ( strcasecmp ( map , " passwd.byname " ) = = 0 ) {
strncpy ( request - > data . username , key ,
sizeof ( request - > data . username ) - 1 ) ;
request - > data . username [ sizeof ( request - > data . username ) - 1 ] = ' \0 ' ;
2002-01-10 21:49:37 +03:00
rq - > f_cmd_data = ( void * ) WINBINDD_GETPWNAM ;
2001-12-22 03:51:32 +03:00
} else if ( strcasecmp ( map , " group.byname " ) = = 0 ) {
strncpy ( request - > data . groupname , key ,
sizeof ( request - > data . groupname ) - 1 ) ;
request - > data . groupname [ sizeof ( request - > data . groupname ) - 1 ] = ' \0 ' ;
2002-01-10 21:49:37 +03:00
rq - > f_cmd_data = ( void * ) WINBINDD_GETGRNAM ;
2001-12-22 03:51:32 +03:00
} else if ( strcasecmp ( map , " group.bygid " ) = = 0 ) {
request - > data . gid = atoi ( key ) ;
2002-01-10 21:49:37 +03:00
rq - > f_cmd_data = ( void * ) WINBINDD_GETGRGID ;
2002-03-29 18:37:39 +03:00
} else if ( strcasecmp ( map , " hosts.byname " ) = = 0 ) {
strncpy ( request - > data . winsreq , key , sizeof ( request - > data . winsreq ) - 1 ) ;
request - > data . winsreq [ sizeof ( request - > data . winsreq ) - 1 ] = ' \0 ' ;
rq - > f_cmd_data = ( void * ) WINBINDD_WINS_BYNAME ;
} else if ( strcasecmp ( map , " hosts.byaddr " ) = = 0 ) {
strncpy ( request - > data . winsreq , key , sizeof ( request - > data . winsreq ) - 1 ) ;
request - > data . winsreq [ sizeof ( request - > data . winsreq ) - 1 ] = ' \0 ' ;
rq - > f_cmd_data = ( void * ) WINBINDD_WINS_BYIP ;
2001-12-22 03:51:32 +03:00
} else {
/*
* Don ' t understand this map - just return not found
*/
nsd_logprintf ( NSD_LOG_MIN , " lookup (winbind) unknown table \n " ) ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( request ) ;
2001-12-22 03:51:32 +03:00
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
return ( do_request ( rq , request ) ) ;
}
int list ( nsd_file_t * rq )
{
char * map ;
nsd_logprintf ( NSD_LOG_MIN , " entering list (winbind) \n " ) ;
if ( ! rq )
return NSD_ERROR ;
map = nsd_attr_fetch_string ( rq - > f_attrs , " table " , ( char * ) 0 ) ;
if ( ! map ) {
nsd_logprintf ( NSD_LOG_MIN , " list (winbind) table not defined \n " ) ;
rq - > f_status = NS_BADREQ ;
return NSD_ERROR ;
}
nsd_logprintf ( NSD_LOG_MIN , " list (winbind %s) \n " , map ) ;
return ( do_list ( 0 , rq ) ) ;
}
static int
do_list ( int state , nsd_file_t * rq )
{
char * map ;
struct winbindd_request * request ;
nsd_logprintf ( NSD_LOG_MIN , " entering do_list (winbind) state = %d \n " , state ) ;
map = nsd_attr_fetch_string ( rq - > f_attrs , " table " , ( char * ) 0 ) ;
request = ( struct winbindd_request * ) nsd_calloc ( 1 , sizeof ( struct winbindd_request ) ) ;
if ( ! request ) {
nsd_logprintf ( NSD_LOG_RESOURCE ,
" do_list (winbind): failed malloc \n " ) ;
return NSD_ERROR ;
}
if ( strcasecmp ( map , " passwd.byname " ) = = 0 ) {
switch ( state ) {
case 0 :
rq - > f_cmd_data = ( void * ) WINBINDD_SETPWENT ;
break ;
case 1 :
request - > data . num_entries = MAX_GETPWENT_USERS ;
rq - > f_cmd_data = ( void * ) WINBINDD_GETPWENT ;
break ;
case 2 :
rq - > f_cmd_data = ( void * ) WINBINDD_ENDPWENT ;
break ;
default :
nsd_logprintf ( NSD_LOG_MIN , " do_list (winbind) unknown state \n " ) ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( request ) ;
2001-12-22 03:51:32 +03:00
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
} else if ( strcasecmp ( map , " group.byname " ) = = 0 ) {
switch ( state ) {
case 0 :
rq - > f_cmd_data = ( void * ) WINBINDD_SETGRENT ;
break ;
case 1 :
request - > data . num_entries = MAX_GETGRENT_USERS ;
rq - > f_cmd_data = ( void * ) WINBINDD_GETGRENT ;
break ;
case 2 :
rq - > f_cmd_data = ( void * ) WINBINDD_ENDGRENT ;
break ;
default :
nsd_logprintf ( NSD_LOG_MIN , " do_list (winbind) unknown state \n " ) ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( request ) ;
2001-12-22 03:51:32 +03:00
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
} else {
/*
* Don ' t understand this map - just return not found
*/
nsd_logprintf ( NSD_LOG_MIN , " do_list (winbind) unknown table \n " ) ;
2002-03-29 18:37:39 +03:00
SAFE_FREE ( request ) ;
2001-12-22 03:51:32 +03:00
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
}
return ( do_request ( rq , request ) ) ;
}
# else
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 . */
static char * get_static ( char * * buffer , int * buflen , int len )
{
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 . */
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
}
/* I've copied the strtok() replacement function next_token() from
lib / util_str . c as I really don ' t want to have to link in any other
objects if I can possibly avoid it . */
2001-06-21 13:10:42 +04:00
BOOL next_token ( char * * ptr , char * buff , char * sep , size_t bufsize )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
char * s ;
BOOL quoted ;
size_t len = 1 ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
if ( ! ptr ) return ( False ) ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
s = * ptr ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
/* default to simple separators */
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 */
2001-07-19 01:50:20 +04:00
while ( * s & & strchr ( sep , * s ) ) s + + ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
/* nothing left? */
if ( ! * s ) return ( False ) ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
/* copy over the token */
2001-07-19 01:50:20 +04:00
for ( quoted = False ; len < bufsize & & * s & & ( quoted | | ! strchr ( sep , * s ) ) ; s + + ) {
2001-04-25 09:47:50 +04:00
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
len + + ;
* buff + + = * s ;
}
}
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
* ptr = ( * s ) ? s + 1 : s ;
* buff = 0 ;
2001-06-21 13:10:42 +04:00
2001-04-25 09:47:50 +04:00
return ( True ) ;
2000-05-09 15:43:00 +04:00
}
2001-06-21 13:10:42 +04:00
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 ,
char * * buffer , int * 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
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
2001-04-25 09:47:50 +04:00
static int fill_grent ( struct group * result , struct winbindd_gr * gr ,
char * gr_mem , char * * buffer , int * buflen )
2000-05-09 15:43:00 +04:00
{
2001-04-25 09:47:50 +04:00
fstring name ;
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 */
2001-12-22 04:15:58 +03:00
if ( ( i = ( int ) * buffer % sizeof ( char * ) ) ! = 0 )
2001-12-22 03:51:32 +03:00
i = sizeof ( char * ) - i ;
if ( ( tst = get_static ( buffer , buflen , ( ( gr - > num_gr_mem + 1 ) *
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
2001-04-25 09:47:50 +04:00
while ( next_token ( ( char * * ) & gr_mem , name , " , " , sizeof ( fstring ) ) ) {
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
/* Allocate space for member */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
if ( ( ( result - > gr_mem ) [ i ] =
get_static ( buffer , buflen , strlen ( 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_mem ) [ i ] , name ) ;
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
{
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setpwent \n " , getpid ( ) ) ;
# endif
if ( num_pw_cache > 0 ) {
ndx_pw_cache = num_pw_cache = 0 ;
free_response ( & getpwent_response ) ;
}
return winbindd_request ( WINBINDD_SETPWENT , NULL , NULL ) ;
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
{
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: endpwent \n " , getpid ( ) ) ;
# endif
if ( num_pw_cache > 0 ) {
ndx_pw_cache = num_pw_cache = 0 ;
free_response ( & getpwent_response ) ;
}
return winbindd_request ( WINBINDD_ENDPWENT , NULL , NULL ) ;
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
/* 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 ) {
free_response ( & getpwent_response ) ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( getpwent_response ) ;
request . data . num_entries = MAX_GETPWENT_USERS ;
ret = winbindd_request ( WINBINDD_GETPWENT , & request ,
& 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 :
pw_cache = getpwent_response . extra_data ;
/* Check data is valid */
if ( pw_cache = = NULL ) {
return NSS_STATUS_NOTFOUND ;
}
ret = fill_pwent ( result , & pw_cache [ ndx_pw_cache ] ,
& buffer , & buflen ) ;
/* Out of memory - try again */
if ( ret = = NSS_STATUS_TRYAGAIN ) {
called_again = True ;
* errnop = errno = ERANGE ;
return ret ;
}
* errnop = errno = 0 ;
called_again = False ;
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 ;
free_response ( & getpwent_response ) ;
}
}
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 ;
2001-04-25 09:47:50 +04:00
static int keep_response = 0 ;
/* If our static buffer needs to be expanded we are called again */
if ( ! keep_response ) {
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 ;
2002-01-10 09:20:03 +03:00
ret = winbindd_request ( 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 ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
}
} else {
/* We've been called again */
ret = fill_pwent ( result , & response . data . pw , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
keep_response = False ;
* errnop = errno = 0 ;
}
free_response ( & response ) ;
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
fprintf ( stderr , " [%5d]: getpwnam %s \n " , getpid ( ) , name ) ;
# 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
2001-04-25 09:47:50 +04:00
if ( ! keep_response ) {
/* 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 ' ;
2002-01-10 09:20:03 +03:00
ret = winbindd_request ( 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 ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
}
} else {
/* We've been called again */
ret = fill_pwent ( result , & response . data . pw , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
keep_response = False ;
* errnop = errno = 0 ;
}
free_response ( & response ) ;
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
{
2001-04-25 09:47:50 +04:00
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: setgrent \n " , getpid ( ) ) ;
# endif
if ( num_gr_cache > 0 ) {
ndx_gr_cache = num_gr_cache = 0 ;
free_response ( & getgrent_response ) ;
}
return winbindd_request ( WINBINDD_SETGRENT , NULL , NULL ) ;
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
{
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
2001-04-25 09:47:50 +04:00
if ( num_gr_cache > 0 ) {
ndx_gr_cache = num_gr_cache = 0 ;
free_response ( & getgrent_response ) ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
return winbindd_request ( WINBINDD_ENDGRENT , NULL , NULL ) ;
}
2000-05-09 15:43:00 +04:00
/* Get next entry from ntdom group database */
2001-04-25 09:47:50 +04:00
NSS_STATUS
2000-05-10 18:48:33 +04:00
_nss_winbind_getgrent_r ( struct group * result ,
2001-04-25 09:47:50 +04:00
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 ;
# ifdef DEBUG_NSS
fprintf ( stderr , " [%5d]: getgrent \n " , getpid ( ) ) ;
# endif
/* 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 ) {
free_response ( & getgrent_response ) ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( getgrent_response ) ;
request . data . num_entries = MAX_GETGRENT_USERS ;
ret = winbindd_request ( WINBINDD_GETGRENT , & request ,
& 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 :
gr_cache = getgrent_response . extra_data ;
/* Check data is valid */
if ( gr_cache = = NULL ) {
return NSS_STATUS_NOTFOUND ;
}
/* 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 ] ,
2001-06-05 06:00:47 +04:00
( ( char * ) getgrent_response . extra_data ) + mem_ofs ,
& buffer , & buflen ) ;
2001-04-25 09:47:50 +04:00
/* Out of memory - try again */
if ( ret = = NSS_STATUS_TRYAGAIN ) {
called_again = True ;
* errnop = errno = ERANGE ;
return ret ;
}
* errnop = 0 ;
called_again = False ;
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 ;
free_response ( & getgrent_response ) ;
}
}
return ret ;
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
2001-04-25 09:47:50 +04:00
/* If our static buffer needs to be expanded we are called again */
if ( ! keep_response ) {
/* 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 ' ;
2002-01-10 09:20:03 +03:00
ret = winbindd_request ( WINBINDD_GETGRNAM , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_grent ( result , & response . data . gr ,
response . extra_data ,
& buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
}
} else {
/* We've been called again */
ret = fill_grent ( result , & response . data . gr ,
response . extra_data , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
keep_response = False ;
* errnop = 0 ;
}
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
free_response ( & response ) ;
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
/* If our static buffer needs to be expanded we are called again */
if ( ! keep_response ) {
/* Call for the first time */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
request . data . gid = gid ;
2002-01-10 09:20:03 +03:00
ret = winbindd_request ( WINBINDD_GETGRGID , & request , & response ) ;
2001-04-25 09:47:50 +04:00
if ( ret = = NSS_STATUS_SUCCESS ) {
ret = fill_grent ( result , & response . data . gr ,
response . extra_data ,
& buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
}
} else {
/* We've been called again */
ret = fill_grent ( result , & response . data . gr ,
response . extra_data , & buffer , & buflen ) ;
if ( ret = = NSS_STATUS_TRYAGAIN ) {
keep_response = True ;
* errnop = errno = ERANGE ;
return ret ;
}
keep_response = False ;
* errnop = 0 ;
}
free_response ( & response ) ;
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
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
2001-04-25 09:47:50 +04:00
ret = winbindd_request ( WINBINDD_GETGROUPS , & request , & response ) ;
if ( ret = = NSS_STATUS_SUCCESS ) {
int num_gids = response . data . num_entries ;
gid_t * gid_list = ( gid_t * ) response . extra_data ;
/* Copy group list to client */
for ( i = 0 ; i < num_gids ; i + + ) {
/* Skip primary group */
if ( gid_list [ i ] = = group ) continue ;
/* Add to buffer */
if ( * start = = * size & & limit < = 0 ) {
2001-12-03 06:53:57 +03:00
( * groups ) = realloc (
( * groups ) , ( 2 * ( * size ) + 1 ) * sizeof ( * * groups ) ) ;
if ( ! * groups ) goto done ;
* size = 2 * ( * size ) + 1 ;
2001-04-25 09:47:50 +04:00
}
2001-12-03 06:53:57 +03:00
if ( * start = = * size ) goto done ;
( * groups ) [ * start ] = gid_list [ i ] ;
2001-04-25 09:47:50 +04:00
* start + = 1 ;
/* Filled buffer? */
if ( * start = = limit ) goto done ;
}
}
/* Back to your regularly scheduled programming */
2000-05-09 15:43:00 +04:00
2001-04-25 09:47:50 +04:00
done :
return ret ;
2000-05-09 15:43:00 +04:00
}
2001-12-22 03:51:32 +03:00
# endif