2003-04-14 07:49:45 +04:00
/*
Unix SMB / CIFS implementation .
AIX loadable authentication mmodule , providing identification
routines against Samba winbind / Windows NT Domain
Copyright ( C ) Tim Potter 2003
Copyright ( C ) Steve Roylance 2003
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 .
*/
2003-04-02 10:16:15 +04:00
# include <stdlib.h>
# include <string.h>
# include <usersec.h>
# include <errno.h>
# include "winbind_client.h"
# define MAX_GETPWENT_USERS 250
# define MAX_GETGRENT_USERS 250
2003-04-14 07:49:45 +04:00
/* #define WB_AIX_DEBUG */
2003-04-02 10:16:15 +04:00
static struct passwd * fill_pwent ( struct winbindd_pw * pw )
{
struct passwd * result ;
2003-04-14 07:49:45 +04:00
if ( ! ( result = malloc ( sizeof ( struct passwd ) ) ) )
goto out ;
ZERO_STRUCTP ( result ) ;
2003-04-02 10:16:15 +04:00
/* User name */
2003-04-14 07:49:45 +04:00
if ( ( result - > pw_name = malloc ( strlen ( pw - > pw_name ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > pw_name , pw - > pw_name ) ;
/* Password */
2003-04-14 07:49:45 +04:00
if ( ( result - > pw_passwd = malloc ( strlen ( pw - > pw_passwd ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > pw_passwd , pw - > pw_passwd ) ;
/* [ug]id */
result - > pw_uid = pw - > pw_uid ;
result - > pw_gid = pw - > pw_gid ;
/* GECOS */
2003-04-14 07:49:45 +04:00
if ( ( result - > pw_gecos = malloc ( strlen ( pw - > pw_gecos ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > pw_gecos , pw - > pw_gecos ) ;
/* Home directory */
2003-04-14 07:49:45 +04:00
if ( ( result - > pw_dir = malloc ( strlen ( pw - > pw_dir ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > pw_dir , pw - > pw_dir ) ;
/* Logon shell */
2003-04-14 07:49:45 +04:00
if ( ( result - > pw_shell = malloc ( strlen ( pw - > pw_shell ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > pw_shell , pw - > pw_shell ) ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returning filled pwent %s, %d \n " , result - > pw_name , result - > pw_uid ) ;
# endif
2003-04-02 10:16:15 +04:00
return result ;
2003-04-14 07:49:45 +04:00
/* A memory allocation failed, undo succesfull allocations and
return NULL */
out :
SAFE_FREE ( result - > pw_dir ) ;
SAFE_FREE ( result - > pw_gecos ) ;
SAFE_FREE ( result - > pw_passwd ) ;
SAFE_FREE ( result - > pw_name ) ;
SAFE_FREE ( result ) ;
return NULL ;
}
static BOOL next_token ( char * * ptr , char * buff , char * sep , size_t bufsize )
{
char * s ;
BOOL quoted ;
size_t len = 1 ;
if ( ! ptr ) return ( False ) ;
s = * ptr ;
/* default to simple separators */
if ( ! sep ) sep = " \t \n \r " ;
/* find the first non sep char */
while ( * s & & strchr ( sep , * s ) ) s + + ;
/* nothing left? */
if ( ! * s ) return ( False ) ;
/* copy over the token */
for ( quoted = False ; len < bufsize & & * s & & ( quoted | | ! strchr ( sep , * s ) ) ; s + + ) {
if ( * s = = ' \" ' ) {
quoted = ! quoted ;
} else {
len + + ;
* buff + + = * s ;
}
}
* ptr = ( * s ) ? s + 1 : s ;
* buff = 0 ;
return ( True ) ;
2003-04-02 10:16:15 +04:00
}
static struct group * fill_grent ( struct winbindd_gr * gr , char * gr_mem )
{
fstring name ;
int i ;
char * tst ;
struct group * result ;
2003-04-14 07:49:45 +04:00
if ( ! ( result = malloc ( sizeof ( struct group ) ) ) )
goto out ;
2003-04-02 10:16:15 +04:00
2003-04-14 07:49:45 +04:00
ZERO_STRUCTP ( result ) ;
2003-04-02 10:16:15 +04:00
2003-04-14 07:49:45 +04:00
/* Group name */
2003-04-02 10:16:15 +04:00
2003-04-14 07:49:45 +04:00
if ( ( result - > gr_name = malloc ( strlen ( gr - > gr_name ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > gr_name , gr - > gr_name ) ;
/* Password */
2003-04-14 07:49:45 +04:00
if ( ( result - > gr_passwd = malloc ( strlen ( gr - > gr_passwd ) + 1 ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
strcpy ( result - > gr_passwd , gr - > gr_passwd ) ;
/* gid */
result - > gr_gid = gr - > gr_gid ;
/* Group membership */
if ( ( gr - > num_gr_mem < 0 ) | | ! gr_mem ) {
gr - > num_gr_mem = 0 ;
}
if ( gr - > num_gr_mem = = 0 ) {
/* Group is empty */
* ( result - > gr_mem ) = NULL ;
return result ;
}
2003-04-14 07:49:45 +04:00
if ( ( tst = malloc ( ( ( gr - > num_gr_mem + 1 ) * sizeof ( char * ) ) ) ) = = NULL )
goto out ;
2003-04-02 10:16:15 +04:00
result - > gr_mem = ( char * * ) tst ;
/* Start looking at extra data */
i = 0 ;
while ( next_token ( ( char * * ) & gr_mem , name , " , " , sizeof ( fstring ) ) ) {
/* Allocate space for member */
if ( ( ( result - > gr_mem ) [ i ] =
malloc ( strlen ( name ) + 1 ) ) = = NULL ) {
2003-04-14 07:49:45 +04:00
for ( i - = 1 ; i > = 0 ; i - - )
SAFE_FREE ( ( result - > gr_mem ) [ i ] ) ;
goto out ;
2003-04-02 10:16:15 +04:00
}
strcpy ( ( result - > gr_mem ) [ i ] , name ) ;
i + + ;
}
/* Terminate list */
( result - > gr_mem ) [ i ] = NULL ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returning filled grent %s, %d \n " , result - > gr_name , result - > gr_gid ) ;
# endif
2003-04-02 10:16:15 +04:00
return result ;
2003-04-14 07:49:45 +04:00
/* A memory allocation failed, undo succesfull allocations and
return NULL */
out :
SAFE_FREE ( tst ) ;
SAFE_FREE ( result - > gr_passwd ) ;
SAFE_FREE ( result - > gr_name ) ;
SAFE_FREE ( result ) ;
return NULL ;
2003-04-02 10:16:15 +04:00
}
static struct group *
wb_aix_getgrgid ( gid_t gid )
{
/* take a group id and return a filled struct group */
struct winbindd_response response ;
struct winbindd_request request ;
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - getgrid for %d \n " , gid ) ;
# endif
2003-04-02 10:16:15 +04:00
request . data . gid = gid ;
2003-04-14 07:49:45 +04:00
if ( winbindd_request ( WINBINDD_GETGRGID , & request , & response )
= = NSS_STATUS_SUCCESS ) {
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returned from winbind_request \n " ) ;
# endif
2003-04-02 10:16:15 +04:00
return fill_grent ( & response . data . gr , response . extra_data ) ;
}
2003-04-14 07:49:45 +04:00
2003-04-02 10:16:15 +04:00
return NULL ;
}
static struct group *
wb_aix_getgrnam ( const char * name )
{
/* take a group name and return a filled struct group */
struct winbindd_response response ;
struct winbindd_request request ;
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - getgrnam for %s \n " , name ) ;
# endif
2003-04-02 10:16:15 +04:00
strncpy ( request . data . groupname , name ,
sizeof ( request . data . groupname ) ) ;
request . data . groupname
[ sizeof ( request . data . groupname ) - 1 ] = ' \0 ' ;
2003-04-14 07:49:45 +04:00
if ( winbindd_request ( WINBINDD_GETGRNAM , & request , & response )
= = NSS_STATUS_SUCCESS ) {
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returned from winbind_request \n " ) ;
# endif
2003-04-02 10:16:15 +04:00
return fill_grent ( & response . data . gr , response . extra_data ) ;
2003-04-14 07:49:45 +04:00
}
2003-04-02 10:16:15 +04:00
return NULL ;
}
static char *
wb_aix_getgrset ( const char * user )
{
/* take a username and return a string containing a comma-separated list of
group id numbers to which the user belongs */
struct winbindd_response response ;
struct winbindd_request request ;
char * tmpbuf , * result ;
int i , idx = 0 ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - getgrset for %s \n " , user ) ;
# endif
2003-04-02 10:16:15 +04:00
strncpy ( request . data . username , user ,
sizeof ( request . data . username ) - 1 ) ;
request . data . username
[ sizeof ( request . data . username ) - 1 ] = ' \0 ' ;
2003-04-14 07:49:45 +04:00
if ( winbindd_request ( WINBINDD_GETGROUPS , & request , & response )
= = NSS_STATUS_SUCCESS ) {
2003-04-02 10:16:15 +04:00
int num_gids = response . data . num_entries ;
gid_t * gid_list = ( gid_t * ) response . extra_data ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returned from winbind_request \n " ) ;
# endif
2003-04-02 10:16:15 +04:00
/* allocate a space large enough to contruct the string */
if ( ! ( tmpbuf = malloc ( num_gids * 12 ) ) ) {
return NULL ;
}
idx + = sprintf ( tmpbuf , " %d " , gid_list [ 0 ] ) ;
for ( i = 1 ; i < num_gids ; i + + ) {
tmpbuf [ idx + + ] = ' , ' ;
idx + = sprintf ( tmpbuf + idx , " %d " , gid_list [ i ] ) ;
}
tmpbuf [ idx ] = ' \0 ' ;
if ( ! ( result = malloc ( idx + 1 ) ) ) {
/* allocate a string the right size to return, but
if that fails may as well return our working buffer
because it contains the same thing */
return tmpbuf ;
}
strcpy ( result , tmpbuf ) ;
2003-04-14 07:49:45 +04:00
SAFE_FREE ( tmpbuf ) ;
2003-04-02 10:16:15 +04:00
return result ;
}
return NULL ;
}
static struct passwd *
wb_aix_getpwuid ( uid_t uid )
{
/* take a uid and return a filled struct passwd */
struct winbindd_response response ;
struct winbindd_request request ;
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - getpwid for %d \n " , uid ) ;
# endif
2003-04-02 10:16:15 +04:00
request . data . uid = uid ;
2003-04-14 07:49:45 +04:00
if ( winbindd_request ( WINBINDD_GETPWUID , & request , & response )
= = NSS_STATUS_SUCCESS ) {
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returned from winbind_request \n " ) ;
# endif
2003-04-02 10:16:15 +04:00
return fill_pwent ( & response . data . pw ) ;
}
return NULL ;
}
static struct passwd *
wb_aix_getpwnam ( const char * name )
{
/* take a username and return a filled struct passwd */
struct winbindd_response response ;
struct winbindd_request request ;
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-04-14 07:49:45 +04:00
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - getpwnam for %s \n " , name ) ;
# endif
2003-04-02 10:16:15 +04:00
strncpy ( request . data . username , name ,
sizeof ( request . data . username ) - 1 ) ;
request . data . username
[ sizeof ( request . data . username ) - 1 ] = ' \0 ' ;
2003-04-14 07:49:45 +04:00
if ( winbindd_request ( WINBINDD_GETPWNAM , & request , & response )
= = NSS_STATUS_SUCCESS ) {
# ifdef WB_AIX_DEBUG
printf ( " wb_aix - returned from winbind_request \n " ) ;
# endif
return fill_pwent ( & response . data . pw ) ;
2003-04-02 10:16:15 +04:00
}
return NULL ;
}
int
wb_aix_init ( struct secmethod_table * methods )
{
memset ( methods , 0 , sizeof ( * methods ) ) ;
2003-04-14 07:49:45 +04:00
/* identification methods, this is the minimum requried for a
working module */
2003-04-02 10:16:15 +04:00
methods - > method_getgrgid = wb_aix_getgrgid ;
methods - > method_getgrnam = wb_aix_getgrnam ;
methods - > method_getgrset = wb_aix_getgrset ;
methods - > method_getpwnam = wb_aix_getpwnam ;
methods - > method_getpwuid = wb_aix_getpwuid ;
2003-04-14 07:49:45 +04:00
2003-04-02 10:16:15 +04:00
return AUTH_SUCCESS ;
}