2003-04-14 03:49:45 +00:00
/*
Unix SMB / CIFS implementation .
2003-05-19 00:42:28 +00:00
AIX loadable authentication module , providing identification
2003-04-14 03:49:45 +00:00
routines against Samba winbind / Windows NT Domain
Copyright ( C ) Tim Potter 2003
Copyright ( C ) Steve Roylance 2003
2003-10-21 12:18:08 +00:00
Copyright ( C ) Andrew Tridgell 2003
2003-04-14 03:49:45 +00:00
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 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/*
see
http : //publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm
for information in the interface that this module implements
*/
2003-04-02 06:16:15 +00:00
# include <stdlib.h>
# include <string.h>
# include <usersec.h>
# include <errno.h>
2003-10-21 12:18:08 +00:00
# include <stdarg.h>
2003-04-02 06:16:15 +00:00
# include "winbind_client.h"
2003-10-21 12:18:08 +00:00
/*
the documentation doesn ' t say so , but experimentation shows that all
of the functions need to return static data , and the area can be
freed only when the same function is called again , or the close
method is called on the module . Note that this matches the standard
behaviour of functions like getpwnam ( ) .
The most puzzling thing about this AIX interface is that it seems to
offer no way of providing a user or group enumeration method . You
can find out any amount of detail about a user or group once you
know the name , but you can ' t obtain a list of those names . If anyone
does find out how to do this then please let me know ( yes , I should
be able to find out as I work for IBM , and this is an IBM interface ,
but finding the right person to ask is a mammoth task ! )
tridge @ samba . org October 2003
*/
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/*
each function uses one of the following lists of memory , declared
static in each backend method . This allows the function to destroy
the memory when that backend is called next time
*/
struct mem_list {
struct mem_list * next , * prev ;
void * p ;
} ;
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/* allocate some memory on a mem_list */
static void * list_alloc ( struct mem_list * * list , size_t size )
{
struct mem_list * m ;
m = malloc ( sizeof ( * m ) ) ;
if ( ! m ) {
errno = ENOMEM ;
return NULL ;
}
m - > p = malloc ( size ) ;
if ( ! m - > p ) {
errno = ENOMEM ;
free ( m ) ;
return NULL ;
}
m - > next = * list ;
m - > prev = NULL ;
if ( * list ) {
( * list ) - > prev = m ;
}
( * list ) = m ;
return m - > p ;
}
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/* duplicate a string using list_alloc() */
static char * list_strdup ( struct mem_list * * list , const char * s )
{
char * ret = list_alloc ( list , strlen ( s ) + 1 ) ;
if ( ! ret ) return NULL ;
strcpy ( ret , s ) ;
return ret ;
}
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/* destroy a mem_list */
static void list_destory ( struct mem_list * * list )
{
struct mem_list * m , * next ;
for ( m = * list ; m ; m = next ) {
next = m - > next ;
free ( m - > p ) ;
free ( m ) ;
}
( * list ) = NULL ;
}
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
# define HANDLE_ERRORS(ret) do { \
if ( ( ret ) = = NSS_STATUS_NOTFOUND ) { \
errno = ENOENT ; \
return NULL ; \
} else if ( ( ret ) ! = NSS_STATUS_SUCCESS ) { \
errno = EIO ; \
return NULL ; \
} \
} while ( 0 )
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/*
fill a struct passwd from a winbindd_pw struct , using memory from a mem_list
*/
static struct passwd * fill_pwent ( struct mem_list * * list , struct winbindd_pw * pw )
2003-04-14 03:49:45 +00:00
{
2003-10-21 12:18:08 +00:00
struct passwd * result ;
2003-04-14 03:49:45 +00:00
2003-10-21 12:18:08 +00:00
if ( ! ( result = list_alloc ( list , sizeof ( struct passwd ) ) ) ) {
return NULL ;
}
2003-04-14 03:49:45 +00:00
2003-10-21 12:18:08 +00:00
ZERO_STRUCTP ( result ) ;
2003-04-14 03:49:45 +00:00
2003-10-21 12:18:08 +00:00
result - > pw_uid = pw - > pw_uid ;
result - > pw_gid = pw - > pw_gid ;
2003-04-14 03:49:45 +00:00
2003-10-21 12:18:08 +00:00
/* strings */
if ( ( result - > pw_name = list_strdup ( list , pw - > pw_name ) ) = = NULL | |
( result - > pw_passwd = list_strdup ( list , pw - > pw_passwd ) ) = = NULL | |
( result - > pw_gecos = list_strdup ( list , pw - > pw_gecos ) ) = = NULL | |
( result - > pw_dir = list_strdup ( list , pw - > pw_dir ) ) = = NULL | |
( result - > pw_shell = list_strdup ( list , pw - > pw_shell ) ) = = NULL ) {
return NULL ;
2003-04-14 03:49:45 +00:00
}
2003-10-21 12:18:08 +00:00
return result ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
/*
fill a struct group from a winbindd_pw struct , using memory from a mem_list
*/
static struct group * fill_grent ( struct mem_list * * list , struct winbindd_gr * gr , char * gr_mem )
2003-04-02 06:16:15 +00:00
{
int i ;
char * tst ;
struct group * result ;
2003-10-21 12:18:08 +00:00
char * name , * p ;
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
if ( ! ( result = list_alloc ( list , sizeof ( struct group ) ) ) ) {
return NULL ;
}
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
ZERO_STRUCTP ( result ) ;
2003-04-02 06:16:15 +00:00
result - > gr_gid = gr - > gr_gid ;
2003-10-21 12:18:08 +00:00
/* Group name */
if ( ( result - > gr_name = list_strdup ( list , gr - > gr_name ) ) = = NULL | |
( result - > gr_passwd = list_strdup ( list , gr - > gr_passwd ) ) = = NULL ) {
return NULL ;
}
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/* Group membership */
2003-04-02 06:16:15 +00:00
if ( ( gr - > num_gr_mem < 0 ) | | ! gr_mem ) {
gr - > num_gr_mem = 0 ;
}
if ( gr - > num_gr_mem = = 0 ) {
2003-10-21 12:18:08 +00:00
/* Group is empty */
2003-04-02 06:16:15 +00:00
return result ;
}
2003-10-21 12:18:08 +00:00
tst = list_alloc ( list , ( gr - > num_gr_mem + 1 ) * sizeof ( char * ) ) ;
if ( ! tst ) {
return NULL ;
}
2003-04-14 03:49:45 +00:00
2003-04-02 06:16:15 +00:00
result - > gr_mem = ( char * * ) tst ;
/* Start looking at extra data */
2003-10-21 12:18:08 +00:00
i = 0 ;
for ( name = strtok_r ( gr_mem , " , " , & p ) ;
name ;
name = strtok_r ( NULL , " , " , & p ) ) {
if ( i > = gr - > num_gr_mem ) {
return NULL ;
}
( result - > gr_mem ) [ i ] = list_strdup ( list , name ) ;
if ( ( result - > gr_mem ) [ i ] = = NULL ) {
return NULL ;
}
2003-04-02 06:16:15 +00:00
i + + ;
}
/* Terminate list */
( result - > gr_mem ) [ i ] = NULL ;
return result ;
}
2003-10-21 12:18:08 +00:00
/* take a group id and return a filled struct group */
static struct group * wb_aix_getgrgid ( gid_t gid )
2003-04-02 06:16:15 +00:00
{
2003-10-21 12:18:08 +00:00
static struct mem_list * list ;
2003-04-02 06:16:15 +00:00
struct winbindd_response response ;
struct winbindd_request request ;
2003-10-21 12:18:08 +00:00
struct group * grp ;
2003-05-19 00:42:28 +00:00
NSS_STATUS ret ;
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
list_destory ( & list ) ;
2003-04-02 06:16:15 +00:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
request . data . gid = gid ;
2003-05-19 00:42:28 +00:00
ret = winbindd_request ( WINBINDD_GETGRGID , & request , & response ) ;
2003-10-21 12:18:08 +00:00
HANDLE_ERRORS ( ret ) ;
grp = fill_grent ( & list , & response . data . gr , response . extra_data ) ;
free_response ( & response ) ;
return grp ;
2003-04-02 06:16:15 +00:00
}
/* take a group name and return a filled struct group */
2003-10-21 12:18:08 +00:00
static struct group * wb_aix_getgrnam ( const char * name )
{
static struct mem_list * list ;
2003-04-02 06:16:15 +00:00
struct winbindd_response response ;
struct winbindd_request request ;
2003-05-19 00:42:28 +00:00
NSS_STATUS ret ;
2003-10-21 12:18:08 +00:00
struct group * grp ;
list_destory ( & list ) ;
2003-04-02 06:16:15 +00:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-10-21 12:18:08 +00:00
if ( strlen ( name ) + 1 > sizeof ( request . data . groupname ) ) {
errno = EINVAL ;
return NULL ;
}
strcpy ( request . data . groupname , name ) ;
2003-04-02 06:16:15 +00:00
2003-05-19 00:42:28 +00:00
ret = winbindd_request ( WINBINDD_GETGRNAM , & request , & response ) ;
2003-10-21 12:18:08 +00:00
HANDLE_ERRORS ( ret ) ;
grp = fill_grent ( & list , & response . data . gr , response . extra_data ) ;
free_response ( & response ) ;
return grp ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
/* take a username and return a string containing a comma-separated
list of group id numbers to which the user belongs */
static char * wb_aix_getgrset ( char * user )
2003-04-02 06:16:15 +00:00
{
2003-10-21 12:18:08 +00:00
static struct mem_list * list ;
2003-04-02 06:16:15 +00:00
struct winbindd_response response ;
struct winbindd_request request ;
2003-05-19 00:42:28 +00:00
NSS_STATUS ret ;
2003-10-21 12:18:08 +00:00
int i , idx ;
char * tmpbuf ;
int num_gids ;
gid_t * gid_list ;
2003-04-14 03:49:45 +00:00
2003-10-21 12:18:08 +00:00
list_destory ( & list ) ;
if ( strlen ( user ) + 1 > sizeof ( request . data . username ) ) {
errno = EINVAL ;
return NULL ;
}
strcpy ( request . data . username , user ) ;
2003-04-02 06:16:15 +00:00
2003-05-19 00:42:28 +00:00
ret = winbindd_request ( WINBINDD_GETGROUPS , & request , & response ) ;
2003-10-21 12:18:08 +00:00
HANDLE_ERRORS ( ret ) ;
num_gids = response . data . num_entries ;
gid_list = ( gid_t * ) response . extra_data ;
2003-04-02 06:16:15 +00:00
2003-10-21 12:18:08 +00:00
/* allocate a space large enough to contruct the string */
tmpbuf = list_alloc ( & list , num_gids * 12 ) ;
if ( ! tmpbuf ) {
return NULL ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
for ( idx = i = 0 ; i < num_gids - 1 ; i + + ) {
idx + = sprintf ( tmpbuf + idx , " %u, " , gid_list [ i ] ) ;
}
idx + = sprintf ( tmpbuf + idx , " %u " , gid_list [ i ] ) ;
free_response ( & response ) ;
return tmpbuf ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
/* take a uid and return a filled struct passwd */
static struct passwd * wb_aix_getpwuid ( uid_t uid )
2003-04-02 06:16:15 +00:00
{
2003-10-21 12:18:08 +00:00
static struct mem_list * list ;
2003-04-02 06:16:15 +00:00
struct winbindd_response response ;
struct winbindd_request request ;
2003-05-19 00:42:28 +00:00
NSS_STATUS ret ;
2003-10-21 12:18:08 +00:00
list_destory ( & list ) ;
2003-04-02 06:16:15 +00:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
request . data . uid = uid ;
2003-05-19 00:42:28 +00:00
ret = winbindd_request ( WINBINDD_GETPWUID , & request , & response ) ;
2003-10-21 12:18:08 +00:00
HANDLE_ERRORS ( ret ) ;
return fill_pwent ( & list , & response . data . pw ) ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
/* take a username and return a filled struct passwd */
static struct passwd * wb_aix_getpwnam ( const char * name )
{
static struct mem_list * list ;
2003-04-02 06:16:15 +00:00
struct winbindd_response response ;
struct winbindd_request request ;
2003-05-19 00:42:28 +00:00
NSS_STATUS ret ;
2003-10-21 12:18:08 +00:00
list_destory ( & list ) ;
2003-04-02 06:16:15 +00:00
ZERO_STRUCT ( response ) ;
ZERO_STRUCT ( request ) ;
2003-05-19 00:42:28 +00:00
2003-10-21 12:18:08 +00:00
if ( strlen ( name ) + 1 > sizeof ( request . data . username ) ) {
errno = EINVAL ;
return NULL ;
}
strcpy ( request . data . username , name ) ;
2003-04-02 06:16:15 +00:00
2003-05-19 00:42:28 +00:00
ret = winbindd_request ( WINBINDD_GETPWNAM , & request , & response ) ;
2003-10-21 12:18:08 +00:00
HANDLE_ERRORS ( ret ) ;
2003-05-19 00:42:28 +00:00
2003-10-21 12:18:08 +00:00
return fill_pwent ( & list , & response . data . pw ) ;
2003-04-02 06:16:15 +00:00
}
2003-10-21 12:18:08 +00:00
int wb_aix_init ( struct secmethod_table * methods )
2003-04-02 06:16:15 +00:00
{
2003-10-21 12:18:08 +00:00
ZERO_STRUCTP ( methods ) ;
2003-04-02 06:16:15 +00:00
2003-04-14 03:49:45 +00:00
/* identification methods, this is the minimum requried for a
2003-10-21 12:18:08 +00:00
working module */
2003-04-02 06:16:15 +00: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 03:49:45 +00:00
2003-04-02 06:16:15 +00:00
return AUTH_SUCCESS ;
}
2003-10-21 12:18:08 +00:00