2008-12-16 11:30:16 +03:00
/*
2003-04-14 07:49:45 +04:00
Unix SMB / CIFS implementation .
2004-01-29 09:14:13 +03:00
AIX loadable authentication module , providing identification and
authentication routines against Samba winbind / Windows NT Domain
2003-04-14 07:49:45 +04:00
Copyright ( C ) Tim Potter 2003
Copyright ( C ) Steve Roylance 2003
2004-01-29 09:14:13 +03:00
Copyright ( C ) Andrew Tridgell 2003 - 2004
2008-12-16 11:30:16 +03:00
2003-04-14 07:49:45 +04:00
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
2003-04-14 07:49:45 +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 .
2008-12-16 11:30:16 +03:00
2003-04-14 07:49:45 +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 .
2008-12-16 11:30:16 +03:00
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/>.
2003-04-14 07:49:45 +04:00
*/
2003-04-02 10:16:15 +04:00
2003-10-21 16:18:08 +04:00
/*
2004-01-29 09:14:13 +03:00
To install this module copy nsswitch / WINBIND to / usr / lib / security and add
" WINBIND " in / usr / lib / security / methods . cfg and / etc / security / user
Note that this module also provides authentication and password
changing routines , so you do not need to install the winbind PAM
module .
2008-12-16 11:30:16 +03:00
see
2003-10-21 16:18:08 +04:00
http : //publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm
2004-01-29 09:14:13 +03:00
for some information in the interface that this module implements
Many thanks to Julianne Haugh for explaining some of the finer
details of this interface .
To debug this module use uess_test . c ( which you can get from tridge )
or set " options=debug " in / usr / lib / security / methods . cfg
2003-10-21 16:18:08 +04:00
*/
2003-04-02 10:16:15 +04:00
# include "winbind_client.h"
2006-09-22 02:24:53 +04:00
# include <usersec.h>
2003-04-02 10:16:15 +04:00
2007-03-01 06:07:57 +03:00
/* enable this to log which entry points have not been
completed yet */
# define LOG_UNIMPLEMENTED_CALLS 0
2004-01-29 09:14:13 +03:00
# define WB_AIX_ENCODED '_'
2003-04-02 10:16:15 +04:00
2004-01-29 09:14:13 +03:00
static int debug_enabled ;
2003-04-02 10:16:15 +04:00
2004-01-29 09:14:13 +03:00
static void logit ( const char * format , . . . )
2003-10-21 16:18:08 +04:00
{
2004-01-29 09:14:13 +03:00
va_list ap ;
FILE * f ;
if ( ! debug_enabled ) {
return ;
2003-10-21 16:18:08 +04:00
}
2004-01-29 09:14:13 +03:00
f = fopen ( " /tmp/WINBIND_DEBUG.log " , " a " ) ;
if ( ! f ) return ;
va_start ( ap , format ) ;
vfprintf ( f , format , ap ) ;
va_end ( ap ) ;
fclose ( f ) ;
2003-10-21 16:18:08 +04:00
}
2003-04-02 10:16:15 +04:00
2003-10-21 16:18:08 +04: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 10:16:15 +04:00
2004-01-29 09:14:13 +03:00
# define STRCPY_RET(dest, src) \
do { \
if ( strlen ( src ) + 1 > sizeof ( dest ) ) { errno = EINVAL ; return - 1 ; } \
2016-03-17 00:04:34 +03:00
strncpy ( dest , src , sizeof ( dest ) ) ; \
dest [ sizeof ( dest ) - 1 ] = ' \0 ' ; \
2004-01-29 09:14:13 +03:00
} while ( 0 )
# define STRCPY_RETNULL(dest, src) \
do { \
if ( strlen ( src ) + 1 > sizeof ( dest ) ) { errno = EINVAL ; return NULL ; } \
2016-03-17 00:04:34 +03:00
strncpy ( dest , src , sizeof ( dest ) ) ; \
dest [ sizeof ( dest ) - 1 ] = ' \0 ' ; \
2004-01-29 09:14:13 +03:00
} while ( 0 )
/* free a passwd structure */
static void free_pwd ( struct passwd * pwd )
{
free ( pwd - > pw_name ) ;
free ( pwd - > pw_passwd ) ;
free ( pwd - > pw_gecos ) ;
free ( pwd - > pw_dir ) ;
free ( pwd - > pw_shell ) ;
free ( pwd ) ;
}
/* free a group structure */
static void free_grp ( struct group * grp )
{
int i ;
free ( grp - > gr_name ) ;
free ( grp - > gr_passwd ) ;
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
if ( ! grp - > gr_mem ) {
free ( grp ) ;
return ;
}
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
for ( i = 0 ; grp - > gr_mem [ i ] ; i + + ) {
free ( grp - > gr_mem [ i ] ) ;
}
free ( grp - > gr_mem ) ;
free ( grp ) ;
}
/* replace commas with nulls, and null terminate */
static void replace_commas ( char * s )
{
char * p , * p0 = s ;
for ( p = strchr ( s , ' , ' ) ; p ; p = strchr ( p + 1 , ' , ' ) ) {
* p = 0 ;
p0 = p + 1 ;
}
p0 [ strlen ( p0 ) + 1 ] = 0 ;
}
/* the decode_*() routines are used to cope with the fact that AIX 5.2
and below cannot handle user or group names longer than 8
characters in some interfaces . We use the normalize method to
provide a mapping to a username that fits , by using the form ' _UID '
or ' _GID ' .
this only works if you can guarantee that the WB_AIX_ENCODED char
is not used as the first char of any other username
2003-10-21 16:18:08 +04:00
*/
2004-01-29 09:14:13 +03:00
static unsigned decode_id ( const char * name )
2003-04-14 07:49:45 +04:00
{
2004-01-29 09:14:13 +03:00
unsigned id ;
sscanf ( name + 1 , " %u " , & id ) ;
return id ;
}
2003-04-14 07:49:45 +04:00
2004-10-01 06:59:43 +04:00
static struct passwd * wb_aix_getpwuid ( uid_t uid ) ;
2004-01-29 09:14:13 +03:00
static char * decode_user ( const char * name )
{
struct passwd * pwd ;
unsigned id ;
char * ret ;
sscanf ( name + 1 , " %u " , & id ) ;
pwd = wb_aix_getpwuid ( id ) ;
if ( ! pwd ) {
2003-10-21 16:18:08 +04:00
return NULL ;
}
2004-01-29 09:14:13 +03:00
ret = strdup ( pwd - > pw_name ) ;
2003-04-14 07:49:45 +04:00
2004-01-29 09:14:13 +03:00
free_pwd ( pwd ) ;
logit ( " decoded '%s' -> '%s' \n " , name , ret ) ;
return ret ;
}
2003-04-14 07:49:45 +04:00
2004-01-29 09:14:13 +03:00
/*
fill a struct passwd from a winbindd_pw struct , allocating as a single block
*/
static struct passwd * fill_pwent ( struct winbindd_pw * pw )
{
struct passwd * result ;
result = calloc ( 1 , sizeof ( struct passwd ) ) ;
if ( ! result ) {
errno = ENOMEM ;
2003-10-21 16:18:08 +04:00
return NULL ;
2003-04-14 07:49:45 +04:00
}
2004-01-29 09:14:13 +03:00
result - > pw_uid = pw - > pw_uid ;
result - > pw_gid = pw - > pw_gid ;
result - > pw_name = strdup ( pw - > pw_name ) ;
result - > pw_passwd = strdup ( pw - > pw_passwd ) ;
result - > pw_gecos = strdup ( pw - > pw_gecos ) ;
result - > pw_dir = strdup ( pw - > pw_dir ) ;
result - > pw_shell = strdup ( pw - > pw_shell ) ;
2008-12-16 11:30:16 +03:00
2003-10-21 16:18:08 +04:00
return result ;
2003-04-02 10:16:15 +04:00
}
2003-10-21 16:18:08 +04:00
/*
2004-01-29 09:14:13 +03:00
fill a struct group from a winbindd_pw struct , allocating as a single block
2003-10-21 16:18:08 +04:00
*/
2004-01-29 09:14:13 +03:00
static struct group * fill_grent ( struct winbindd_gr * gr , char * gr_mem )
2003-04-02 10:16:15 +04:00
{
int i ;
struct group * result ;
2004-01-29 09:14:13 +03:00
char * p , * name ;
2003-04-02 10:16:15 +04:00
2004-01-29 09:14:13 +03:00
result = calloc ( 1 , sizeof ( struct group ) ) ;
if ( ! result ) {
errno = ENOMEM ;
2003-10-21 16:18:08 +04:00
return NULL ;
}
2003-04-02 10:16:15 +04:00
result - > gr_gid = gr - > gr_gid ;
2004-01-29 09:14:13 +03:00
result - > gr_name = strdup ( gr - > gr_name ) ;
result - > gr_passwd = strdup ( gr - > gr_passwd ) ;
2003-04-02 10:16:15 +04:00
2003-10-21 16:18:08 +04:00
/* Group membership */
2003-04-02 10:16:15 +04:00
if ( ( gr - > num_gr_mem < 0 ) | | ! gr_mem ) {
gr - > num_gr_mem = 0 ;
}
2008-12-16 11:30:16 +03:00
2003-04-02 10:16:15 +04:00
if ( gr - > num_gr_mem = = 0 ) {
2008-12-16 11:30:16 +03:00
/* Group is empty */
2003-04-02 10:16:15 +04:00
return result ;
}
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
result - > gr_mem = ( char * * ) malloc ( sizeof ( char * ) * ( gr - > num_gr_mem + 1 ) ) ;
if ( ! result - > gr_mem ) {
2009-05-23 18:02:40 +04:00
free ( result - > gr_name ) ;
free ( result - > gr_passwd ) ;
free ( result ) ;
2004-01-29 09:14:13 +03:00
errno = ENOMEM ;
2003-10-21 16:18:08 +04:00
return NULL ;
}
2003-04-02 10:16:15 +04:00
/* Start looking at extra data */
2003-10-21 16:18:08 +04:00
i = 0 ;
2008-12-16 11:30:16 +03:00
for ( name = strtok_r ( gr_mem , " , " , & p ) ;
name ;
2003-10-21 16:18:08 +04:00
name = strtok_r ( NULL , " , " , & p ) ) {
2004-01-29 09:14:13 +03:00
if ( i = = gr - > num_gr_mem ) {
break ;
2003-10-21 16:18:08 +04:00
}
2004-01-29 09:14:13 +03:00
result - > gr_mem [ i ] = strdup ( name ) ;
2003-04-02 10:16:15 +04:00
i + + ;
}
/* Terminate list */
2004-01-29 09:14:13 +03:00
result - > gr_mem [ i ] = NULL ;
2003-04-02 10:16:15 +04:00
return result ;
}
2008-12-16 11:30:16 +03:00
/* take a group id and return a filled struct group */
2003-10-21 16:18:08 +04:00
static struct group * wb_aix_getgrgid ( gid_t gid )
2003-04-02 10:16:15 +04:00
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2003-10-21 16:18:08 +04:00
struct group * grp ;
2003-05-19 04:42:28 +04:00
NSS_STATUS ret ;
2003-04-02 10:16:15 +04:00
2004-01-29 09:14:13 +03:00
logit ( " getgrgid %d \n " , gid ) ;
2003-10-21 16:18:08 +04:00
2003-04-02 10:16:15 +04:00
request . data . gid = gid ;
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_GETGRGID ,
& request , & response ) ;
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
logit ( " getgrgid ret=%d \n " , ret ) ;
2003-10-21 16:18:08 +04:00
HANDLE_ERRORS ( ret ) ;
2006-04-12 18:10:39 +04:00
grp = fill_grent ( & response . data . gr , response . extra_data . data ) ;
2003-10-21 16:18:08 +04:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-10-21 16:18:08 +04:00
return grp ;
2003-04-02 10:16:15 +04:00
}
/* take a group name and return a filled struct group */
2003-10-21 16:18:08 +04:00
static struct group * wb_aix_getgrnam ( const char * name )
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2003-05-19 04:42:28 +04:00
NSS_STATUS ret ;
2003-10-21 16:18:08 +04:00
struct group * grp ;
2004-01-29 09:14:13 +03:00
if ( * name = = WB_AIX_ENCODED ) {
return wb_aix_getgrgid ( decode_id ( name ) ) ;
}
logit ( " getgrnam '%s' \n " , name ) ;
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
STRCPY_RETNULL ( request . data . groupname , name ) ;
2003-04-02 10:16:15 +04:00
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_GETGRNAM ,
& request , & response ) ;
2008-12-16 11:30:16 +03:00
2003-10-21 16:18:08 +04:00
HANDLE_ERRORS ( ret ) ;
2006-04-12 18:10:39 +04:00
grp = fill_grent ( & response . data . gr , response . extra_data . data ) ;
2003-10-21 16:18:08 +04:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-10-21 16:18:08 +04:00
return grp ;
2003-04-02 10:16:15 +04:00
}
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
/* this call doesn't have to fill in the gr_mem, but we do anyway
for simplicity */
static struct group * wb_aix_getgracct ( void * id , int type )
{
if ( type = = 1 ) {
return wb_aix_getgrnam ( ( char * ) id ) ;
}
if ( type = = 0 ) {
return wb_aix_getgrgid ( * ( int * ) id ) ;
}
errno = EINVAL ;
return NULL ;
}
2003-10-21 16:18:08 +04: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 10:16:15 +04:00
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2003-05-19 04:42:28 +04:00
NSS_STATUS ret ;
2003-10-21 16:18:08 +04:00
int i , idx ;
char * tmpbuf ;
int num_gids ;
gid_t * gid_list ;
2004-01-29 09:14:13 +03:00
char * r_user = user ;
2003-04-14 07:49:45 +04:00
2004-01-29 09:14:13 +03:00
if ( * user = = WB_AIX_ENCODED ) {
r_user = decode_user ( r_user ) ;
if ( ! r_user ) {
errno = ENOENT ;
return NULL ;
}
}
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
logit ( " getgrset '%s' \n " , r_user ) ;
STRCPY_RETNULL ( request . data . username , r_user ) ;
if ( * user = = WB_AIX_ENCODED ) {
free ( r_user ) ;
2003-10-21 16:18:08 +04:00
}
2003-04-02 10:16:15 +04:00
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_GETGROUPS ,
& request , & response ) ;
2003-05-19 04:42:28 +04:00
2003-10-21 16:18:08 +04:00
HANDLE_ERRORS ( ret ) ;
num_gids = response . data . num_entries ;
2006-04-12 18:10:39 +04:00
gid_list = ( gid_t * ) response . extra_data . data ;
2008-12-16 11:30:16 +03:00
2003-10-21 16:18:08 +04:00
/* allocate a space large enough to contruct the string */
2004-01-29 09:14:13 +03:00
tmpbuf = malloc ( num_gids * 12 ) ;
2003-10-21 16:18:08 +04:00
if ( ! tmpbuf ) {
return NULL ;
2003-04-02 10:16:15 +04:00
}
2003-10-21 16:18:08 +04:00
for ( idx = i = 0 ; i < num_gids - 1 ; i + + ) {
2008-12-16 11:30:16 +03:00
idx + = sprintf ( tmpbuf + idx , " %u, " , gid_list [ i ] ) ;
2003-10-21 16:18:08 +04:00
}
2008-12-16 11:30:16 +03:00
idx + = sprintf ( tmpbuf + idx , " %u " , gid_list [ i ] ) ;
2003-10-21 16:18:08 +04:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-10-21 16:18:08 +04:00
return tmpbuf ;
2003-04-02 10:16:15 +04:00
}
2003-10-21 16:18:08 +04:00
2008-12-16 11:30:16 +03:00
/* take a uid and return a filled struct passwd */
2003-10-21 16:18:08 +04:00
static struct passwd * wb_aix_getpwuid ( uid_t uid )
2003-04-02 10:16:15 +04:00
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2003-05-19 04:42:28 +04:00
NSS_STATUS ret ;
2004-01-29 09:14:13 +03:00
struct passwd * pwd ;
logit ( " getpwuid '%d' \n " , uid ) ;
2003-10-21 16:18:08 +04:00
2003-04-02 10:16:15 +04:00
request . data . uid = uid ;
2008-12-16 11:30:16 +03:00
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_GETPWUID ,
& request , & response ) ;
2003-10-21 16:18:08 +04:00
HANDLE_ERRORS ( ret ) ;
2004-01-29 09:14:13 +03:00
pwd = fill_pwent ( & response . data . pw ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
logit ( " getpwuid gave ptr %p \n " , pwd ) ;
return pwd ;
2003-04-02 10:16:15 +04:00
}
2003-10-21 16:18:08 +04:00
/* take a username and return a filled struct passwd */
static struct passwd * wb_aix_getpwnam ( const char * name )
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2003-05-19 04:42:28 +04:00
NSS_STATUS ret ;
2004-01-29 09:14:13 +03:00
struct passwd * pwd ;
if ( * name = = WB_AIX_ENCODED ) {
return wb_aix_getpwuid ( decode_id ( name ) ) ;
}
logit ( " getpwnam '%s' \n " , name ) ;
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
STRCPY_RETNULL ( request . data . username , name ) ;
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_GETPWNAM ,
& request , & response ) ;
2004-01-29 09:14:13 +03:00
HANDLE_ERRORS ( ret ) ;
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
pwd = fill_pwent ( & response . data . pw ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
logit ( " getpwnam gave ptr %p \n " , pwd ) ;
return pwd ;
}
/*
list users
*/
static int wb_aix_lsuser ( char * attributes [ ] , attrval_t results [ ] , int size )
{
NSS_STATUS ret ;
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2004-01-29 09:14:13 +03:00
int len ;
char * s ;
if ( size ! = 1 | | strcmp ( attributes [ 0 ] , S_USERS ) ! = 0 ) {
logit ( " invalid lsuser op \n " ) ;
2003-10-21 16:18:08 +04:00
errno = EINVAL ;
2004-01-29 09:14:13 +03:00
return - 1 ;
2003-10-21 16:18:08 +04:00
}
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_LIST_USERS ,
& request , & response ) ;
2004-01-29 09:14:13 +03:00
if ( ret ! = 0 ) {
errno = EINVAL ;
return - 1 ;
}
2003-04-02 10:16:15 +04:00
2006-04-12 18:10:39 +04:00
len = strlen ( response . extra_data . data ) ;
2003-10-21 16:18:08 +04:00
2004-01-29 09:14:13 +03:00
s = malloc ( len + 2 ) ;
if ( ! s ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
errno = ENOMEM ;
return - 1 ;
}
2008-12-16 11:30:16 +03:00
2006-04-12 18:10:39 +04:00
memcpy ( s , response . extra_data . data , len + 1 ) ;
2004-01-29 09:14:13 +03:00
replace_commas ( s ) ;
results [ 0 ] . attr_un . au_char = s ;
results [ 0 ] . attr_flag = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
return 0 ;
}
/*
list groups
*/
static int wb_aix_lsgroup ( char * attributes [ ] , attrval_t results [ ] , int size )
{
NSS_STATUS ret ;
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2004-01-29 09:14:13 +03:00
int len ;
char * s ;
if ( size ! = 1 | | strcmp ( attributes [ 0 ] , S_GROUPS ) ! = 0 ) {
logit ( " invalid lsgroup op \n " ) ;
errno = EINVAL ;
return - 1 ;
}
2015-01-24 02:58:53 +03:00
ret = winbindd_request_response ( NULL , WINBINDD_LIST_GROUPS ,
& request , & response ) ;
2004-01-29 09:14:13 +03:00
if ( ret ! = 0 ) {
errno = EINVAL ;
return - 1 ;
}
2006-04-12 18:10:39 +04:00
len = strlen ( response . extra_data . data ) ;
2004-01-29 09:14:13 +03:00
s = malloc ( len + 2 ) ;
if ( ! s ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
errno = ENOMEM ;
return - 1 ;
}
2008-12-16 11:30:16 +03:00
2006-04-12 18:10:39 +04:00
memcpy ( s , response . extra_data . data , len + 1 ) ;
2004-01-29 09:14:13 +03:00
replace_commas ( s ) ;
results [ 0 ] . attr_un . au_char = s ;
results [ 0 ] . attr_flag = 0 ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2008-12-16 11:30:16 +03:00
2004-01-29 09:14:13 +03:00
return 0 ;
}
static attrval_t pwd_to_group ( struct passwd * pwd )
{
2018-12-21 17:02:40 +03:00
attrval_t r = {
. attr_flag = EINVAL ,
} ;
2004-01-29 09:14:13 +03:00
struct group * grp = wb_aix_getgrgid ( pwd - > pw_gid ) ;
2008-12-16 11:30:16 +03:00
2018-12-21 17:02:40 +03:00
if ( grp ! = NULL ) {
2004-01-29 09:14:13 +03:00
r . attr_flag = 0 ;
r . attr_un . au_char = strdup ( grp - > gr_name ) ;
free_grp ( grp ) ;
}
return r ;
}
static attrval_t pwd_to_groupsids ( struct passwd * pwd )
{
2018-12-21 17:02:40 +03:00
attrval_t r = {
. attr_flag = EINVAL ,
} ;
2004-01-29 09:14:13 +03:00
char * s , * p ;
2016-03-17 00:04:34 +03:00
size_t mlen ;
2004-01-29 09:14:13 +03:00
2007-03-01 06:07:57 +03:00
if ( ( s = wb_aix_getgrset ( pwd - > pw_name ) ) = = NULL ) {
2004-01-29 09:14:13 +03:00
r . attr_flag = EINVAL ;
return r ;
}
2016-03-17 00:04:34 +03:00
mlen = strlen ( s ) + 2 ;
if ( ( p = malloc ( mlen ) ) = = NULL ) {
2004-01-29 09:14:13 +03:00
r . attr_flag = ENOMEM ;
return r ;
}
2016-03-17 00:04:34 +03:00
strncpy ( p , s , mlen ) ;
p [ mlen - 1 ] = ' \0 ' ;
2004-01-29 09:14:13 +03:00
replace_commas ( p ) ;
free ( s ) ;
2018-12-21 17:02:40 +03:00
r . attr_flag = 0 ;
2004-01-29 09:14:13 +03:00
r . attr_un . au_char = p ;
return r ;
}
static attrval_t pwd_to_sid ( struct passwd * pwd )
{
2018-12-21 14:51:29 +03:00
char buf [ ( 1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */ ) + 1 ] = { 0 , } ;
int len ;
2004-01-29 09:14:13 +03:00
struct winbindd_request request ;
struct winbindd_response response ;
2018-12-21 14:51:29 +03:00
NSS_STATUS result ;
attrval_t r = {
. attr_flag = ENOENT ,
} ;
len = snprintf ( buf , sizeof ( buf ) ,
" U% " PRIu32 " \n " ,
( uint32_t ) pwd - > pw_uid ) ;
if ( len > = sizeof ( buf ) ) {
r = ( attrval_t ) {
. attr_flag = EINVAL ,
} ;
return r ;
}
2004-01-29 09:14:13 +03:00
2018-12-21 14:51:29 +03:00
request = ( struct winbindd_request ) {
2018-12-22 04:39:00 +03:00
. wb_flags = WBFLAG_FROM_NSS ,
2018-12-21 14:51:29 +03:00
. extra_data . data = buf ,
. extra_len = strlen ( buf ) + 1 ,
} ;
response = ( struct winbindd_response ) {
. length = 0 ,
} ;
result = winbindd_request_response ( NULL , WINBINDD_XIDS_TO_SIDS ,
& request , & response ) ;
if ( result = = NSS_STATUS_SUCCESS ) {
2004-01-29 09:14:13 +03:00
r . attr_flag = 0 ;
r . attr_un . au_char = strdup ( response . data . sid . sid ) ;
}
return r ;
}
static int wb_aix_user_attrib ( const char * key , char * attributes [ ] ,
attrval_t results [ ] , int size )
{
struct passwd * pwd ;
int i ;
pwd = wb_aix_getpwnam ( key ) ;
if ( ! pwd ) {
errno = ENOENT ;
return - 1 ;
}
for ( i = 0 ; i < size ; i + + ) {
2018-12-21 17:02:40 +03:00
results [ i ] = ( attrval_t ) {
. attr_flag = 0 ,
} ;
2004-01-29 09:14:13 +03:00
if ( strcmp ( attributes [ i ] , S_ID ) = = 0 ) {
results [ i ] . attr_un . au_int = pwd - > pw_uid ;
2007-04-04 08:28:28 +04:00
# ifdef _AIXVERSION_530
2007-03-01 06:07:57 +03:00
} else if ( strcmp ( attributes [ i ] , S_PGID ) = = 0 ) {
results [ i ] . attr_un . au_int = pwd - > pw_gid ;
2007-04-04 08:28:28 +04:00
# endif
2004-01-29 09:14:13 +03:00
} else if ( strcmp ( attributes [ i ] , S_PWD ) = = 0 ) {
results [ i ] . attr_un . au_char = strdup ( pwd - > pw_passwd ) ;
} else if ( strcmp ( attributes [ i ] , S_HOME ) = = 0 ) {
results [ i ] . attr_un . au_char = strdup ( pwd - > pw_dir ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , S_SHELL ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] . attr_un . au_char = strdup ( pwd - > pw_shell ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , S_REGISTRY ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] . attr_un . au_char = strdup ( " WINBIND " ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , S_GECOS ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] . attr_un . au_char = strdup ( pwd - > pw_gecos ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , S_PGRP ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] = pwd_to_group ( pwd ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , S_GROUPS ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] = pwd_to_groupsids ( pwd ) ;
2018-12-21 04:20:00 +03:00
} else if ( strcmp ( attributes [ i ] , S_GROUPSIDS ) = = 0 ) {
results [ i ] = pwd_to_groupsids ( pwd ) ;
2006-04-22 05:59:23 +04:00
} else if ( strcmp ( attributes [ i ] , " SID " ) = = 0 ) {
2004-01-29 09:14:13 +03:00
results [ i ] = pwd_to_sid ( pwd ) ;
} else {
logit ( " Unknown user attribute '%s' \n " , attributes [ i ] ) ;
results [ i ] . attr_flag = EINVAL ;
}
}
free_pwd ( pwd ) ;
return 0 ;
}
static int wb_aix_group_attrib ( const char * key , char * attributes [ ] ,
attrval_t results [ ] , int size )
{
struct group * grp ;
int i ;
grp = wb_aix_getgrnam ( key ) ;
if ( ! grp ) {
errno = ENOENT ;
return - 1 ;
}
for ( i = 0 ; i < size ; i + + ) {
results [ i ] . attr_flag = 0 ;
if ( strcmp ( attributes [ i ] , S_PWD ) = = 0 ) {
results [ i ] . attr_un . au_char = strdup ( grp - > gr_passwd ) ;
} else if ( strcmp ( attributes [ i ] , S_ID ) = = 0 ) {
results [ i ] . attr_un . au_int = grp - > gr_gid ;
} else {
logit ( " Unknown group attribute '%s' \n " , attributes [ i ] ) ;
results [ i ] . attr_flag = EINVAL ;
}
}
free_grp ( grp ) ;
return 0 ;
2003-04-02 10:16:15 +04:00
}
2004-01-29 09:14:13 +03:00
/*
called for user / group enumerations
*/
2008-12-16 11:30:16 +03:00
static int wb_aix_getentry ( char * key , char * table , char * attributes [ ] ,
2004-01-29 09:14:13 +03:00
attrval_t results [ ] , int size )
{
2008-12-16 11:30:16 +03:00
logit ( " Got getentry with key='%s' table='%s' size=%d attributes[0]='%s' \n " ,
2004-01-29 09:14:13 +03:00
key , table , size , attributes [ 0 ] ) ;
2008-12-16 11:30:16 +03:00
if ( strcmp ( key , " ALL " ) = = 0 & &
2004-01-29 09:14:13 +03:00
strcmp ( table , " user " ) = = 0 ) {
return wb_aix_lsuser ( attributes , results , size ) ;
}
2008-12-16 11:30:16 +03:00
if ( strcmp ( key , " ALL " ) = = 0 & &
2004-01-29 09:14:13 +03:00
strcmp ( table , " group " ) = = 0 ) {
return wb_aix_lsgroup ( attributes , results , size ) ;
}
if ( strcmp ( table , " user " ) = = 0 ) {
return wb_aix_user_attrib ( key , attributes , results , size ) ;
}
if ( strcmp ( table , " group " ) = = 0 ) {
return wb_aix_group_attrib ( key , attributes , results , size ) ;
}
logit ( " Unknown getentry operation key='%s' table='%s' \n " , key , table ) ;
errno = ENOSYS ;
return - 1 ;
}
/*
called to start the backend
*/
static void * wb_aix_open ( const char * name , const char * domain , int mode , char * options )
{
if ( strstr ( options , " debug " ) ) {
debug_enabled = 1 ;
}
2008-12-16 11:30:16 +03:00
logit ( " open name='%s' mode=%d domain='%s' options='%s' \n " , name , domain ,
2004-01-29 09:14:13 +03:00
mode , options ) ;
return NULL ;
}
static void wb_aix_close ( void * token )
{
logit ( " close \n " ) ;
return ;
}
2004-10-01 06:57:10 +04:00
# ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
2008-12-16 11:30:16 +03:00
/*
return a list of additional attributes supported by the backend
2004-01-29 09:14:13 +03:00
*/
static attrlist_t * * wb_aix_attrlist ( void )
{
2007-03-01 06:07:57 +03:00
/* pretty confusing but we are allocating the array of pointers
and the structures we ' ll be pointing to all at once . So
2008-12-16 11:30:16 +03:00
you need N + 1 pointers and N structures . */
2007-03-01 06:07:57 +03:00
attrlist_t * * ret = NULL ;
attrlist_t * offset = NULL ;
int i ;
int n ;
size_t size ;
struct attr_types {
const char * name ;
int flags ;
int type ;
} attr_list [ ] = {
/* user attributes */
{ S_ID , AL_USERATTR , SEC_INT } ,
{ S_PGRP , AL_USERATTR , SEC_CHAR } ,
{ S_HOME , AL_USERATTR , SEC_CHAR } ,
{ S_SHELL , AL_USERATTR , SEC_CHAR } ,
2007-04-04 08:28:28 +04:00
# ifdef _AIXVERSION_530
2007-03-01 06:07:57 +03:00
{ S_PGID , AL_USERATTR , SEC_INT } ,
2007-04-04 08:28:28 +04:00
# endif
2007-03-01 06:07:57 +03:00
{ S_GECOS , AL_USERATTR , SEC_CHAR } ,
{ S_SHELL , AL_USERATTR , SEC_CHAR } ,
{ S_PGRP , AL_USERATTR , SEC_CHAR } ,
{ S_GROUPS , AL_USERATTR , SEC_LIST } ,
2018-12-21 04:20:00 +03:00
{ S_GROUPSIDS , AL_USERATTR , SEC_LIST } ,
2007-03-01 06:07:57 +03:00
{ " SID " , AL_USERATTR , SEC_CHAR } ,
/* group attributes */
{ S_ID , AL_GROUPATTR , SEC_INT }
} ;
2004-01-29 09:14:13 +03:00
logit ( " method attrlist called \n " ) ;
2007-03-01 06:07:57 +03:00
n = sizeof ( attr_list ) / sizeof ( struct attr_types ) ;
2021-07-09 19:20:30 +03:00
size = ( ( n + 1 ) * sizeof ( attrlist_t * ) ) ;
2007-03-01 06:07:57 +03:00
if ( ( ret = malloc ( size ) ) = = NULL ) {
2004-01-29 09:14:13 +03:00
errno = ENOMEM ;
return NULL ;
}
2007-03-01 06:07:57 +03:00
/* offset to where the structures start in the buffer */
2004-01-29 09:14:13 +03:00
2007-03-01 06:07:57 +03:00
offset = ( attrlist_t * ) ( ret + n ) ;
/* now loop over the user_attr_list[] array and add
all the members */
for ( i = 0 ; i < n ; i + + ) {
attrlist_t * a = malloc ( sizeof ( attrlist_t ) ) ;
if ( ! a ) {
/* this is bad. Just bail */
return NULL ;
}
a - > al_name = strdup ( attr_list [ i ] . name ) ;
a - > al_flags = attr_list [ i ] . flags ;
a - > al_type = attr_list [ i ] . type ;
ret [ i ] = a ;
}
ret [ n ] = NULL ;
2004-01-29 09:14:13 +03:00
return ret ;
}
2004-10-01 06:57:10 +04:00
# endif
2004-01-29 09:14:13 +03:00
/*
2008-12-16 11:30:16 +03:00
turn a long username into a short one . Needed to cope with the 8 char
2004-01-29 09:14:13 +03:00
username limit in AIX 5.2 and below
*/
static int wb_aix_normalize ( char * longname , char * shortname )
{
struct passwd * pwd ;
logit ( " normalize '%s' \n " , longname ) ;
/* automatically cope with AIX 5.3 with longer usernames
when it comes out */
if ( S_NAMELEN > strlen ( longname ) ) {
2016-03-17 00:04:34 +03:00
strncpy ( shortname , longname , S_NAMELEN ) ;
shortname [ S_NAMELEN - 1 ] = ' \0 ' ;
2004-01-29 09:14:13 +03:00
return 1 ;
}
pwd = wb_aix_getpwnam ( longname ) ;
if ( ! pwd ) {
errno = ENOENT ;
return 0 ;
}
sprintf ( shortname , " %c%07u " , WB_AIX_ENCODED , pwd - > pw_uid ) ;
free_pwd ( pwd ) ;
return 1 ;
}
/*
authenticate a user
*/
2008-12-16 11:30:16 +03:00
static int wb_aix_authenticate ( char * user , char * pass ,
2004-01-29 09:14:13 +03:00
int * reenter , char * * message )
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2004-01-29 09:14:13 +03:00
NSS_STATUS result ;
char * r_user = user ;
logit ( " authenticate '%s' response='%s' \n " , user , pass ) ;
* reenter = 0 ;
* message = NULL ;
/* Send off request */
if ( * user = = WB_AIX_ENCODED ) {
r_user = decode_user ( r_user ) ;
if ( ! r_user ) {
return AUTH_NOTFOUND ;
}
}
STRCPY_RET ( request . data . auth . user , r_user ) ;
STRCPY_RET ( request . data . auth . pass , pass ) ;
if ( * user = = WB_AIX_ENCODED ) {
free ( r_user ) ;
}
2015-01-24 02:58:53 +03:00
result = winbindd_request_response ( NULL , WINBINDD_PAM_AUTH ,
& request , & response ) ;
2004-01-29 09:14:13 +03:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
logit ( " auth result %d for '%s' \n " , result , user ) ;
if ( result = = NSS_STATUS_SUCCESS ) {
errno = 0 ;
return AUTH_SUCCESS ;
}
return AUTH_FAILURE ;
}
/*
change a user password
*/
static int wb_aix_chpass ( char * user , char * oldpass , char * newpass , char * * message )
{
2018-12-22 04:39:00 +03:00
struct winbindd_request request = {
. wb_flags = WBFLAG_FROM_NSS ,
} ;
struct winbindd_response response = {
. length = 0 ,
} ;
2004-01-29 09:14:13 +03:00
NSS_STATUS result ;
char * r_user = user ;
if ( * user = = WB_AIX_ENCODED ) {
r_user = decode_user ( r_user ) ;
if ( ! r_user ) {
errno = ENOENT ;
return - 1 ;
}
}
logit ( " chpass '%s' old='%s' new='%s' \n " , r_user , oldpass , newpass ) ;
* message = NULL ;
/* Send off request */
STRCPY_RET ( request . data . chauthtok . user , r_user ) ;
STRCPY_RET ( request . data . chauthtok . oldpass , oldpass ) ;
STRCPY_RET ( request . data . chauthtok . newpass , newpass ) ;
if ( * user = = WB_AIX_ENCODED ) {
free ( r_user ) ;
}
2015-01-24 02:58:53 +03:00
result = winbindd_request_response ( NULL , WINBINDD_PAM_CHAUTHTOK ,
& request , & response ) ;
2004-01-29 09:14:13 +03:00
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2004-01-29 09:14:13 +03:00
if ( result = = NSS_STATUS_SUCCESS ) {
errno = 0 ;
return 0 ;
}
errno = EINVAL ;
return - 1 ;
}
/*
don ' t do any password strength testing for now
*/
2008-12-16 11:30:16 +03:00
static int wb_aix_passwdrestrictions ( char * user , char * newpass , char * oldpass ,
2004-01-29 09:14:13 +03:00
char * * message )
{
logit ( " passwdresrictions called for '%s' \n " , user ) ;
return 0 ;
}
static int wb_aix_passwdexpired ( char * user , char * * message )
{
logit ( " passwdexpired '%s' \n " , user ) ;
/* we should check the account bits here */
return 0 ;
}
/*
we can ' t return a crypt ( ) password
*/
static char * wb_aix_getpasswd ( char * user )
{
logit ( " getpasswd '%s' \n " , user ) ;
errno = ENOSYS ;
return NULL ;
}
/*
2008-12-16 11:30:16 +03:00
this is called to update things like the last login time . We don ' t
2004-01-29 09:14:13 +03:00
currently pass this onto the DC
*/
2008-12-16 11:30:16 +03:00
static int wb_aix_putentry ( char * key , char * table , char * attributes [ ] ,
2004-01-29 09:14:13 +03:00
attrval_t values [ ] , int size )
{
2008-12-16 11:30:16 +03:00
logit ( " putentry key='%s' table='%s' attrib='%s' \n " ,
2004-01-29 09:14:13 +03:00
key , table , size > = 1 ? attributes [ 0 ] : " <null> " ) ;
errno = ENOSYS ;
return - 1 ;
}
static int wb_aix_commit ( char * key , char * table )
{
logit ( " commit key='%s' table='%s' \n " ) ;
errno = ENOSYS ;
return - 1 ;
}
static int wb_aix_getgrusers ( char * group , void * result , int type , int * size )
{
logit ( " getgrusers group='%s' \n " , group ) ;
errno = ENOSYS ;
return - 1 ;
}
# define DECL_METHOD(x) \
int method_ # # x ( void ) \
{ \
logit ( " UNIMPLEMENTED METHOD '%s' \n " , # x ) ; \
errno = EINVAL ; \
return - 1 ; \
}
# if LOG_UNIMPLEMENTED_CALLS
DECL_METHOD ( delgroup ) ;
DECL_METHOD ( deluser ) ;
DECL_METHOD ( newgroup ) ;
DECL_METHOD ( newuser ) ;
DECL_METHOD ( putgrent ) ;
DECL_METHOD ( putgrusers ) ;
DECL_METHOD ( putpwent ) ;
DECL_METHOD ( lock ) ;
DECL_METHOD ( unlock ) ;
DECL_METHOD ( getcred ) ;
DECL_METHOD ( setcred ) ;
DECL_METHOD ( deletecred ) ;
# endif
2003-10-21 16:18:08 +04:00
int wb_aix_init ( struct secmethod_table * methods )
2003-04-02 10:16:15 +04:00
{
2003-10-21 16:18:08 +04:00
ZERO_STRUCTP ( methods ) ;
2003-04-02 10:16:15 +04:00
2004-10-01 06:57:10 +04:00
# ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION
2004-01-29 09:14:13 +03:00
methods - > method_version = SECMETHOD_VERSION_520 ;
2004-10-01 06:57:10 +04:00
# endif
2004-01-29 09:14:13 +03: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 ;
methods - > method_getentry = wb_aix_getentry ;
methods - > method_open = wb_aix_open ;
methods - > method_close = wb_aix_close ;
methods - > method_normalize = wb_aix_normalize ;
methods - > method_passwdexpired = wb_aix_passwdexpired ;
methods - > method_putentry = wb_aix_putentry ;
methods - > method_getpasswd = wb_aix_getpasswd ;
2008-12-16 11:30:16 +03:00
methods - > method_authenticate = wb_aix_authenticate ;
2004-01-29 09:14:13 +03:00
methods - > method_commit = wb_aix_commit ;
methods - > method_chpass = wb_aix_chpass ;
methods - > method_passwdrestrictions = wb_aix_passwdrestrictions ;
methods - > method_getgracct = wb_aix_getgracct ;
methods - > method_getgrusers = wb_aix_getgrusers ;
2004-10-01 06:57:10 +04:00
# ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST
2004-01-29 09:14:13 +03:00
methods - > method_attrlist = wb_aix_attrlist ;
2004-10-01 06:57:10 +04:00
# endif
2004-01-29 09:14:13 +03:00
# if LOG_UNIMPLEMENTED_CALLS
methods - > method_delgroup = method_delgroup ;
methods - > method_deluser = method_deluser ;
methods - > method_newgroup = method_newgroup ;
methods - > method_newuser = method_newuser ;
methods - > method_putgrent = method_putgrent ;
methods - > method_putgrusers = method_putgrusers ;
methods - > method_putpwent = method_putpwent ;
methods - > method_lock = method_lock ;
methods - > method_unlock = method_unlock ;
methods - > method_getcred = method_getcred ;
methods - > method_setcred = method_setcred ;
methods - > method_deletecred = method_deletecred ;
# endif
2003-04-14 07:49:45 +04:00
2003-04-02 10:16:15 +04:00
return AUTH_SUCCESS ;
}