2003-07-09 16:44:47 +00:00
/*
Unix SMB / CIFS implementation .
Winbind account management functions
Copyright ( C ) by Gerald ( Jerry ) Carter 2003
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "winbindd.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
# define WBKEY_PASSWD "WBA_PASSWD"
# define WBKEY_GROUP "WBA_GROUP"
# define NUM_PW_FIELDS 7
# define NUM_GRP_FIELDS 4
/* Globals */
static TDB_CONTEXT * account_tdb ;
extern userdom_struct current_user_info ;
2003-07-11 05:33:40 +00:00
struct _check_primary_grp {
gid_t gid ;
BOOL found ;
} ;
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_winbindd_gr ( WINBINDD_GR * grp )
{
int i ;
if ( ! grp )
return ;
for ( i = 0 ; i < grp - > num_gr_mem ; i + + )
SAFE_FREE ( grp - > gr_mem [ i ] ) ;
SAFE_FREE ( grp - > gr_mem ) ;
return ;
}
2003-07-09 16:44:47 +00:00
/*****************************************************************************
Initialise auto - account database .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL winbindd_accountdb_init ( void )
{
/* see if we've already opened the tdb */
if ( account_tdb )
return True ;
2003-08-06 18:01:39 +00:00
/* winbindd_idmap.tdb should always be opened by the idmap_init()
code first */
2003-07-09 16:44:47 +00:00
2003-08-06 18:01:39 +00:00
if ( ! ( account_tdb = idmap_tdb_handle ( ) ) ) {
DEBUG ( 0 , ( " winbindd_accountdb_init: Unable to retreive handle for database \n " ) ) ;
return False ;
2003-07-09 16:44:47 +00:00
}
/* yeah! */
return True ;
}
/**********************************************************************
Convert a string in / etc / passwd format to a struct passwd * entry
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WINBINDD_PW * string2passwd ( char * string )
{
static WINBINDD_PW pw ;
char * p , * str ;
char * fields [ NUM_PW_FIELDS ] ;
int i ;
if ( ! string )
return NULL ;
ZERO_STRUCTP ( & pw ) ;
DEBUG ( 10 , ( " string2passwd: converting \" %s \" \n " , string ) ) ;
ZERO_STRUCT ( fields ) ;
for ( i = 0 , str = string ; i < NUM_PW_FIELDS - 1 ; i + + ) {
if ( ! ( p = strchr ( str , ' : ' ) ) ) {
DEBUG ( 0 , ( " string2passwd: parsing failure \n " ) ) ;
return NULL ;
}
* p = ' \0 ' ;
if ( str )
fields [ i ] = str ;
str = p + 1 ;
}
if ( str )
fields [ i ] = str ;
/* copy fields */
fstrcpy ( pw . pw_name , fields [ 0 ] ) ;
fstrcpy ( pw . pw_passwd , fields [ 1 ] ) ;
pw . pw_uid = atoi ( fields [ 2 ] ) ;
pw . pw_gid = atoi ( fields [ 3 ] ) ;
fstrcpy ( pw . pw_gecos , fields [ 4 ] ) ;
fstrcpy ( pw . pw_dir , fields [ 5 ] ) ;
fstrcpy ( pw . pw_shell , fields [ 6 ] ) ;
/* last minute sanity checks */
if ( pw . pw_uid = = 0 | | pw . pw_gid = = 0 ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " string2passwd: Failure! uid==%lu, gid==%lu \n " ,
( unsigned long ) pw . pw_uid , ( unsigned long ) pw . pw_gid ) ) ;
2003-07-09 16:44:47 +00:00
return NULL ;
}
DEBUG ( 10 , ( " string2passwd: Success \n " ) ) ;
return & pw ;
}
/**********************************************************************
Convert a struct passwd * to a string formatted for / etc / passwd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * passwd2string ( const WINBINDD_PW * pw )
{
static pstring string ;
int ret ;
if ( ! pw | | ! pw - > pw_name )
return NULL ;
DEBUG ( 10 , ( " passwd2string: converting passwd struct for %s \n " ,
pw - > pw_name ) ) ;
2003-07-23 12:33:59 +00:00
ret = pstr_sprintf ( string , " %s:%s:%lu:%lu:%s:%s:%s " ,
2003-07-09 16:44:47 +00:00
pw - > pw_name ,
pw - > pw_passwd ? pw - > pw_passwd : " x " ,
2003-07-22 04:31:20 +00:00
( unsigned long ) pw - > pw_uid ,
( unsigned long ) pw - > pw_gid ,
2003-07-09 16:44:47 +00:00
pw - > pw_gecos ,
pw - > pw_dir ,
pw - > pw_shell ) ;
if ( ret < 0 ) {
2003-07-23 12:33:59 +00:00
DEBUG ( 0 , ( " passwd2string: pstr_sprintf() failed! \n " ) ) ;
2003-07-09 16:44:47 +00:00
return NULL ;
}
return string ;
}
/**********************************************************************
Convert a string in / etc / group format to a struct group * entry
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static WINBINDD_GR * string2group ( char * string )
{
static WINBINDD_GR grp ;
char * p , * str ;
char * fields [ NUM_GRP_FIELDS ] ;
int i ;
char * * gr_members = NULL ;
int num_gr_members = 0 ;
if ( ! string )
return NULL ;
ZERO_STRUCTP ( & grp ) ;
DEBUG ( 10 , ( " string2group: converting \" %s \" \n " , string ) ) ;
ZERO_STRUCT ( fields ) ;
for ( i = 0 , str = string ; i < NUM_GRP_FIELDS - 1 ; i + + ) {
if ( ! ( p = strchr ( str , ' : ' ) ) ) {
DEBUG ( 0 , ( " string2group: parsing failure \n " ) ) ;
return NULL ;
}
* p = ' \0 ' ;
if ( str )
fields [ i ] = str ;
str = p + 1 ;
}
/* group members */
if ( * str ) {
/* we already know we have a non-empty string */
num_gr_members = count_chars ( str , ' , ' ) + 1 ;
/* if there was at least one comma, then there
are n + 1 members */
if ( num_gr_members ) {
fstring buffer ;
gr_members = ( char * * ) smb_xmalloc ( sizeof ( char * ) * num_gr_members + 1 ) ;
i = 0 ;
while ( next_token ( & str , buffer , " , " , sizeof ( buffer ) ) & & i < num_gr_members ) {
gr_members [ i + + ] = smb_xstrdup ( buffer ) ;
}
gr_members [ i ] = NULL ;
}
}
/* copy fields */
fstrcpy ( grp . gr_name , fields [ 0 ] ) ;
fstrcpy ( grp . gr_passwd , fields [ 1 ] ) ;
grp . gr_gid = atoi ( fields [ 2 ] ) ;
grp . num_gr_mem = num_gr_members ;
grp . gr_mem = gr_members ;
/* last minute sanity checks */
if ( grp . gr_gid = = 0 ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 0 , ( " string2group: Failure! gid==%lu \n " , ( unsigned long ) grp . gr_gid ) ) ;
2003-07-09 16:44:47 +00:00
SAFE_FREE ( gr_members ) ;
return NULL ;
}
DEBUG ( 10 , ( " string2group: Success \n " ) ) ;
return & grp ;
}
/**********************************************************************
Convert a struct group * to a string formatted for / etc / group
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * group2string ( const WINBINDD_GR * grp )
{
static pstring string ;
int ret ;
char * member , * gr_mem_str ;
int num_members ;
int i , size ;
if ( ! grp | | ! grp - > gr_name )
return NULL ;
DEBUG ( 10 , ( " group2string: converting passwd struct for %s \n " ,
grp - > gr_name ) ) ;
if ( grp - > num_gr_mem ) {
int idx = 0 ;
member = grp - > gr_mem [ 0 ] ;
size = 0 ;
num_members = 0 ;
while ( member ) {
size + = strlen ( member ) + 1 ;
num_members + + ;
member = grp - > gr_mem [ num_members ] ;
}
gr_mem_str = smb_xmalloc ( size ) ;
for ( i = 0 ; i < num_members ; i + + ) {
snprintf ( & gr_mem_str [ idx ] , size - idx , " %s, " , grp - > gr_mem [ i ] ) ;
idx + = strlen ( grp - > gr_mem [ i ] ) + 1 ;
}
/* add trailing NULL (also removes trailing ',' */
gr_mem_str [ size - 1 ] = ' \0 ' ;
}
else {
/* no members */
gr_mem_str = smb_xmalloc ( sizeof ( fstring ) ) ;
fstrcpy ( gr_mem_str , " " ) ;
}
2003-07-23 12:33:59 +00:00
ret = pstr_sprintf ( string , " %s:%s:%lu:%s " ,
2003-07-09 16:44:47 +00:00
grp - > gr_name ,
grp - > gr_passwd ? grp - > gr_passwd : " * " ,
2003-07-22 04:31:20 +00:00
( unsigned long ) grp - > gr_gid ,
2003-07-09 16:44:47 +00:00
gr_mem_str ) ;
SAFE_FREE ( gr_mem_str ) ;
if ( ret < 0 ) {
2003-07-23 12:33:59 +00:00
DEBUG ( 0 , ( " group2string: pstr_sprintf() failed! \n " ) ) ;
2003-07-09 16:44:47 +00:00
return NULL ;
}
return string ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acct_userkey_byname ( const char * name )
{
static fstring key ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/NAME/%s " , WBKEY_PASSWD , name ) ;
2003-07-09 16:44:47 +00:00
return key ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acct_userkey_byuid ( uid_t uid )
{
static fstring key ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/UID/%lu " , WBKEY_PASSWD , ( unsigned long ) uid ) ;
2003-07-09 16:44:47 +00:00
return key ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acct_groupkey_byname ( const char * name )
{
static fstring key ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/NAME/%s " , WBKEY_GROUP , name ) ;
2003-07-09 16:44:47 +00:00
return key ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * acct_groupkey_bygid ( gid_t gid )
{
static fstring key ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/GID/%lu " , WBKEY_GROUP , ( unsigned long ) gid ) ;
2003-07-09 16:44:47 +00:00
return key ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WINBINDD_PW * wb_getpwnam ( const char * name )
{
char * keystr ;
TDB_DATA data ;
static WINBINDD_PW * pw ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_getpwnam: Failed to open winbindd account db \n " ) ) ;
return NULL ;
}
keystr = acct_userkey_byname ( name ) ;
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , keystr ) ;
2003-07-09 16:44:47 +00:00
pw = NULL ;
if ( data . dptr ) {
pw = string2passwd ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
}
DEBUG ( 5 , ( " wb_getpwnam: %s user (%s) \n " ,
( pw ? " Found " : " Did not find " ) , name ) ) ;
return pw ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WINBINDD_PW * wb_getpwuid ( const uid_t uid )
{
char * keystr ;
TDB_DATA data ;
static WINBINDD_PW * pw ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_getpwuid: Failed to open winbindd account db \n " ) ) ;
return NULL ;
}
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , acct_userkey_byuid ( uid ) ) ;
2003-07-09 16:44:47 +00:00
if ( ! data . dptr ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 4 , ( " wb_getpwuid: failed to locate uid == %lu \n " , ( unsigned long ) uid ) ) ;
2003-07-09 16:44:47 +00:00
return NULL ;
}
keystr = acct_userkey_byname ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , keystr ) ;
2003-07-09 16:44:47 +00:00
pw = NULL ;
if ( data . dptr ) {
pw = string2passwd ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
}
2003-07-22 04:31:20 +00:00
DEBUG ( 5 , ( " wb_getpwuid: %s user (uid == %lu) \n " ,
( pw ? " Found " : " Did not find " ) , ( unsigned long ) uid ) ) ;
2003-07-09 16:44:47 +00:00
return pw ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL wb_storepwnam ( const WINBINDD_PW * pw )
{
char * namekey , * uidkey ;
TDB_DATA data ;
char * str ;
int ret = 0 ;
fstring username ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_storepwnam: Failed to open winbindd account db \n " ) ) ;
return False ;
}
namekey = acct_userkey_byname ( pw - > pw_name ) ;
/* lock the main entry first */
if ( tdb_lock_bystring ( account_tdb , namekey , 0 ) = = - 1 ) {
DEBUG ( 0 , ( " wb_storepwnam: Failed to lock %s \n " , namekey ) ) ;
return False ;
}
str = passwd2string ( pw ) ;
data . dptr = str ;
data . dsize = strlen ( str ) + 1 ;
2003-07-10 20:37:01 +00:00
if ( ( tdb_store_bystring ( account_tdb , namekey , data , TDB_REPLACE ) ) = = - 1 ) {
2003-07-09 16:44:47 +00:00
DEBUG ( 0 , ( " wb_storepwnam: Failed to store \" %s \" \n " , str ) ) ;
ret = - 1 ;
goto done ;
}
/* store the uid index */
uidkey = acct_userkey_byuid ( pw - > pw_uid ) ;
fstrcpy ( username , pw - > pw_name ) ;
data . dptr = username ;
data . dsize = strlen ( username ) + 1 ;
2003-07-10 20:37:01 +00:00
if ( ( tdb_store_bystring ( account_tdb , uidkey , data , TDB_REPLACE ) ) = = - 1 ) {
2003-07-09 16:44:47 +00:00
DEBUG ( 0 , ( " wb_storepwnam: Failed to store uid key \" %s \" \n " , str ) ) ;
2003-07-10 20:37:01 +00:00
tdb_delete_bystring ( account_tdb , namekey ) ;
2003-07-09 16:44:47 +00:00
ret = - 1 ;
goto done ;
}
DEBUG ( 10 , ( " wb_storepwnam: Success -> \" %s \" \n " , str ) ) ;
done :
tdb_unlock_bystring ( account_tdb , namekey ) ;
return ( ret = = 0 ) ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WINBINDD_GR * wb_getgrnam ( const char * name )
{
char * keystr ;
TDB_DATA data ;
static WINBINDD_GR * grp ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_getgrnam: Failed to open winbindd account db \n " ) ) ;
return NULL ;
}
keystr = acct_groupkey_byname ( name ) ;
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , keystr ) ;
2003-07-09 16:44:47 +00:00
grp = NULL ;
if ( data . dptr ) {
grp = string2group ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
}
DEBUG ( 5 , ( " wb_getgrnam: %s group (%s) \n " ,
( grp ? " Found " : " Did not find " ) , name ) ) ;
return grp ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
WINBINDD_GR * wb_getgrgid ( gid_t gid )
{
char * keystr ;
TDB_DATA data ;
static WINBINDD_GR * grp ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_getgrgid: Failed to open winbindd account db \n " ) ) ;
return NULL ;
}
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , acct_groupkey_bygid ( gid ) ) ;
2003-07-09 16:44:47 +00:00
if ( ! data . dptr ) {
2003-07-22 04:31:20 +00:00
DEBUG ( 4 , ( " wb_getgrgid: failed to locate gid == %lu \n " ,
( unsigned long ) gid ) ) ;
2003-07-09 16:44:47 +00:00
return NULL ;
}
keystr = acct_groupkey_byname ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
2003-07-10 20:37:01 +00:00
data = tdb_fetch_bystring ( account_tdb , keystr ) ;
2003-07-09 16:44:47 +00:00
grp = NULL ;
if ( data . dptr ) {
grp = string2group ( data . dptr ) ;
SAFE_FREE ( data . dptr ) ;
}
2003-07-22 04:31:20 +00:00
DEBUG ( 5 , ( " wb_getgrgid: %s group (gid == %lu) \n " ,
( grp ? " Found " : " Did not find " ) , ( unsigned long ) gid ) ) ;
2003-07-09 16:44:47 +00:00
return grp ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL wb_storegrnam ( const WINBINDD_GR * grp )
{
char * namekey , * gidkey ;
TDB_DATA data ;
char * str ;
int ret = 0 ;
fstring groupname ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_storepwnam: Failed to open winbindd account db \n " ) ) ;
return False ;
}
namekey = acct_groupkey_byname ( grp - > gr_name ) ;
/* lock the main entry first */
if ( tdb_lock_bystring ( account_tdb , namekey , 0 ) = = - 1 ) {
DEBUG ( 0 , ( " wb_storegrnam: Failed to lock %s \n " , namekey ) ) ;
return False ;
}
str = group2string ( grp ) ;
data . dptr = str ;
data . dsize = strlen ( str ) + 1 ;
2003-07-10 20:37:01 +00:00
if ( ( tdb_store_bystring ( account_tdb , namekey , data , TDB_REPLACE ) ) = = - 1 ) {
2003-07-09 16:44:47 +00:00
DEBUG ( 0 , ( " wb_storegrnam: Failed to store \" %s \" \n " , str ) ) ;
ret = - 1 ;
goto done ;
}
/* store the gid index */
gidkey = acct_groupkey_bygid ( grp - > gr_gid ) ;
fstrcpy ( groupname , grp - > gr_name ) ;
data . dptr = groupname ;
data . dsize = strlen ( groupname ) + 1 ;
2003-07-10 20:37:01 +00:00
if ( ( tdb_store_bystring ( account_tdb , gidkey , data , TDB_REPLACE ) ) = = - 1 ) {
2003-07-09 16:44:47 +00:00
DEBUG ( 0 , ( " wb_storegrnam: Failed to store gid key \" %s \" \n " , str ) ) ;
2003-07-10 20:37:01 +00:00
tdb_delete_bystring ( account_tdb , namekey ) ;
2003-07-09 16:44:47 +00:00
ret = - 1 ;
goto done ;
}
DEBUG ( 10 , ( " wb_storegrnam: Success -> \" %s \" \n " , str ) ) ;
done :
tdb_unlock_bystring ( account_tdb , namekey ) ;
return ( ret = = 0 ) ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL wb_addgrpmember ( WINBINDD_GR * grp , const char * user )
{
int i ;
char * * members ;
if ( ! grp | | ! user )
return False ;
for ( i = 0 ; i < grp - > num_gr_mem ; i + + ) {
if ( StrCaseCmp ( grp - > gr_mem [ i ] , user ) = = 0 )
return True ;
}
/* add one new slot and keep an extra for the terminating NULL */
members = Realloc ( grp - > gr_mem , ( grp - > num_gr_mem + 2 ) * sizeof ( char * ) ) ;
if ( ! members )
return False ;
grp - > gr_mem = members ;
grp - > gr_mem [ grp - > num_gr_mem + + ] = smb_xstrdup ( user ) ;
grp - > gr_mem [ grp - > num_gr_mem ] = NULL ;
return True ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL wb_delgrpmember ( WINBINDD_GR * grp , const char * user )
{
int i ;
BOOL found = False ;
if ( ! grp | | ! user )
return False ;
for ( i = 0 ; i < grp - > num_gr_mem & & ! found ; i + + ) {
if ( StrCaseCmp ( grp - > gr_mem [ i ] , user ) = = 0 )
found = True ;
}
if ( ! found )
return False ;
2003-07-11 05:33:40 +00:00
/* still some remaining members */
if ( grp - > num_gr_mem > 1 ) {
memmove ( grp - > gr_mem [ i ] , grp - > gr_mem [ i + 1 ] , sizeof ( char * ) * ( grp - > num_gr_mem - ( i + 1 ) ) ) ;
grp - > num_gr_mem - - ;
}
else { /* last one */
free_winbindd_gr ( grp ) ;
grp - > gr_mem = NULL ;
grp - > num_gr_mem = 0 ;
}
2003-07-09 16:44:47 +00:00
return True ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-07-11 05:33:40 +00:00
static int cleangroups_traverse_fn ( TDB_CONTEXT * the_tdb , TDB_DATA kbuf , TDB_DATA dbuf ,
void * state )
2003-07-09 16:44:47 +00:00
{
2003-07-11 05:33:40 +00:00
int len ;
fstring key ;
char * name = ( char * ) state ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/NAME " , WBKEY_GROUP ) ;
2003-07-11 05:33:40 +00:00
len = strlen ( key ) ;
/* if this is a group entry then, check the members */
if ( ( strncmp ( kbuf . dptr , key , len ) = = 0 ) & & dbuf . dptr ) {
WINBINDD_GR * grp ;
2003-07-09 16:44:47 +00:00
2003-07-11 05:33:40 +00:00
if ( ! ( grp = string2group ( dbuf . dptr ) ) ) {
DEBUG ( 0 , ( " cleangroups_traverse_fn: Failure to parse [%s] \n " ,
dbuf . dptr ) ) ;
return 0 ;
}
/* just try to delete the user and rely on wb_delgrpmember()
to tell you whether or not the group changed . This is more
effecient than testing group membership first since the
checks for deleting a user from a group is essentially the
same as checking if he / she is a member */
if ( wb_delgrpmember ( grp , name ) ) {
DEBUG ( 10 , ( " cleanupgroups_traverse_fn: Removed user (%s) from group (%s) \n " ,
name , grp - > gr_name ) ) ;
wb_storegrnam ( grp ) ;
}
free_winbindd_gr ( grp ) ;
}
2003-07-09 16:44:47 +00:00
2003-07-11 05:33:40 +00:00
return 0 ;
2003-07-09 16:44:47 +00:00
}
2003-07-10 20:37:01 +00:00
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-07-11 05:33:40 +00:00
static BOOL wb_delete_user ( WINBINDD_PW * pw )
2003-07-10 20:37:01 +00:00
{
char * namekey ;
2003-07-11 05:33:40 +00:00
char * uidkey ;
2003-07-10 20:37:01 +00:00
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
2003-07-11 05:33:40 +00:00
DEBUG ( 0 , ( " wb_delete_user: Failed to open winbindd account db \n " ) ) ;
2003-07-10 20:37:01 +00:00
return False ;
}
2003-07-11 05:33:40 +00:00
namekey = acct_userkey_byname ( pw - > pw_name ) ;
2003-07-10 20:37:01 +00:00
/* lock the main entry first */
if ( tdb_lock_bystring ( account_tdb , namekey , 0 ) = = - 1 ) {
DEBUG ( 0 , ( " wb_delete_user: Failed to lock %s \n " , namekey ) ) ;
return False ;
}
2003-07-11 05:33:40 +00:00
/* remove user from all groups */
tdb_traverse ( account_tdb , cleangroups_traverse_fn , ( void * ) pw - > pw_name ) ;
/* remove the user */
uidkey = acct_userkey_byuid ( pw - > pw_uid ) ;
2003-07-10 20:37:01 +00:00
tdb_delete_bystring ( account_tdb , namekey ) ;
2003-07-11 05:33:40 +00:00
tdb_delete_bystring ( account_tdb , uidkey ) ;
2003-07-10 20:37:01 +00:00
tdb_unlock_bystring ( account_tdb , namekey ) ;
return True ;
}
2003-07-11 05:33:40 +00:00
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int isprimarygroup_traverse_fn ( TDB_CONTEXT * the_tdb , TDB_DATA kbuf ,
TDB_DATA dbuf , void * params )
{
int len ;
fstring key ;
struct _check_primary_grp * check = ( struct _check_primary_grp * ) params ;
2003-07-23 12:33:59 +00:00
fstr_sprintf ( key , " %s/NAME " , WBKEY_PASSWD ) ;
2003-07-11 05:33:40 +00:00
len = strlen ( key ) ;
/* if this is a group entry then, check the members */
if ( ( strncmp ( kbuf . dptr , key , len ) = = 0 ) & & dbuf . dptr ) {
WINBINDD_PW * pw ; ;
if ( ! ( pw = string2passwd ( dbuf . dptr ) ) ) {
DEBUG ( 0 , ( " isprimarygroup_traverse_fn: Failure to parse [%s] \n " ,
dbuf . dptr ) ) ;
return 0 ;
}
if ( check - > gid = = pw - > pw_gid ) {
check - > found = True ;
return 1 ;
}
}
return 0 ;
}
2003-07-10 20:37:01 +00:00
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-07-11 05:33:40 +00:00
static BOOL wb_delete_group ( WINBINDD_GR * grp )
2003-07-10 20:37:01 +00:00
{
2003-07-11 05:33:40 +00:00
struct _check_primary_grp check ;
char * namekey ;
char * gidkey ;
if ( ! account_tdb & & ! winbindd_accountdb_init ( ) ) {
DEBUG ( 0 , ( " wb_delete_group: Failed to open winbindd account db \n " ) ) ;
return False ;
}
/* lock the main entry first */
namekey = acct_groupkey_byname ( grp - > gr_name ) ;
if ( tdb_lock_bystring ( account_tdb , namekey , 0 ) = = - 1 ) {
DEBUG ( 0 , ( " wb_delete_group: Failed to lock %s \n " , namekey ) ) ;
return False ;
}
/* is this group the primary group for any user? If
so deny delete */
check . found = False ;
tdb_traverse ( account_tdb , isprimarygroup_traverse_fn , ( void * ) & check ) ;
if ( check . found ) {
DEBUG ( 4 , ( " wb_delete_group: Cannot delete group (%s) since it "
" is the primary group for some users \n " , grp - > gr_name ) ) ;
return False ;
}
/* We're clear. Delete the group */
DEBUG ( 5 , ( " wb_delete_group: Removing group (%s) \n " , grp - > gr_name ) ) ;
gidkey = acct_groupkey_bygid ( grp - > gr_gid ) ;
tdb_delete_bystring ( account_tdb , namekey ) ;
tdb_delete_bystring ( account_tdb , gidkey ) ;
tdb_unlock_bystring ( account_tdb , namekey ) ;
return True ;
2003-07-10 20:37:01 +00:00
}
2003-07-09 16:44:47 +00:00
/**********************************************************************
Create a new " UNIX " user for the system given a username
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_create_user ( struct winbindd_cli_state * state )
{
char * user , * group ;
unid_t id ;
WINBINDD_PW pw ;
WINBINDD_GR * wb_grp ;
struct group * unix_grp ;
gid_t primary_gid ;
2003-07-11 05:33:40 +00:00
uint32 flags = state - > request . flags ;
uint32 rid ;
2003-07-09 16:44:47 +00:00
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_create_user: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . username ) - 1 ] = ' \0 ' ;
state - > request . data . acct_mgt . groupname [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
user = state - > request . data . acct_mgt . username ;
group = state - > request . data . acct_mgt . groupname ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: create_user: user=>(%s), group=>(%s) \n " ,
( unsigned long ) state - > pid , user , group ) ) ;
2003-07-09 16:44:47 +00:00
if ( ! * group )
group = lp_template_primary_group ( ) ;
/* validate the primary group
1 ) lookup in local tdb first
2 ) call getgrnam ( ) as a last resort */
if ( ( wb_grp = wb_getgrnam ( group ) ) ! = NULL ) {
primary_gid = wb_grp - > gr_gid ;
free_winbindd_gr ( wb_grp ) ;
}
else if ( ( unix_grp = sys_getgrnam ( group ) ) ! = NULL ) {
primary_gid = unix_grp - > gr_gid ;
}
else {
DEBUG ( 2 , ( " winbindd_create_user: Cannot validate gid for group (%s) \n " , group ) ) ;
return WINBINDD_ERROR ;
}
/* get a new uid */
if ( ! NT_STATUS_IS_OK ( idmap_allocate_id ( & id , ID_USERID ) ) ) {
DEBUG ( 0 , ( " winbindd_create_user: idmap_allocate_id() failed! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* The substitution of %U and %D in the 'template homedir' is done
by lp_string ( ) calling standard_sub_basic ( ) . */
fstrcpy ( current_user_info . smb_name , user ) ;
sub_set_smb_name ( user ) ;
fstrcpy ( current_user_info . domain , get_global_sam_name ( ) ) ;
/* fill in the passwd struct */
fstrcpy ( pw . pw_name , user ) ;
fstrcpy ( pw . pw_passwd , " x " ) ;
fstrcpy ( pw . pw_gecos , user ) ;
fstrcpy ( pw . pw_dir , lp_template_homedir ( ) ) ;
fstrcpy ( pw . pw_shell , lp_template_shell ( ) ) ;
pw . pw_uid = id . uid ;
pw . pw_gid = primary_gid ;
2003-07-11 05:33:40 +00:00
/* store the new entry */
if ( ! wb_storepwnam ( & pw ) )
return WINBINDD_ERROR ;
/* do we need a new RID? */
if ( flags & WBFLAG_ALLOCATE_RID ) {
if ( ! NT_STATUS_IS_OK ( idmap_allocate_rid ( & rid , USER_RID_TYPE ) ) ) {
DEBUG ( 0 , ( " winbindd_create_user: RID allocation failure! Cannot create user (%s) \n " ,
user ) ) ;
wb_delete_user ( & pw ) ;
return WINBINDD_ERROR ;
}
state - > response . data . rid = rid ;
}
2003-07-09 16:44:47 +00:00
2003-07-11 05:33:40 +00:00
return WINBINDD_OK ;
2003-07-09 16:44:47 +00:00
}
/**********************************************************************
Create a new " UNIX " group for the system given a username
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_create_group ( struct winbindd_cli_state * state )
{
char * group ;
unid_t id ;
WINBINDD_GR grp ;
2003-07-11 05:33:40 +00:00
uint32 flags = state - > request . flags ;
uint32 rid ;
2003-07-09 16:44:47 +00:00
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_create_group: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . groupname [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
group = state - > request . data . acct_mgt . groupname ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: create_group: (%s) \n " , ( unsigned long ) state - > pid , group ) ) ;
2003-07-09 16:44:47 +00:00
/* get a new uid */
if ( ! NT_STATUS_IS_OK ( idmap_allocate_id ( & id , ID_GROUPID ) ) ) {
DEBUG ( 0 , ( " winbindd_create_group: idmap_allocate_id() failed! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* fill in the group struct */
fstrcpy ( grp . gr_name , group ) ;
fstrcpy ( grp . gr_passwd , " * " ) ;
grp . gr_gid = id . gid ;
grp . gr_mem = NULL ; /* start with no members */
grp . num_gr_mem = 0 ;
2003-07-11 05:33:40 +00:00
if ( ! wb_storegrnam ( & grp ) )
return WINBINDD_ERROR ;
/* do we need a new RID? */
if ( flags & WBFLAG_ALLOCATE_RID ) {
if ( ! NT_STATUS_IS_OK ( idmap_allocate_rid ( & rid , GROUP_RID_TYPE ) ) ) {
DEBUG ( 0 , ( " winbindd_create_group: RID allocation failure! Cannot create group (%s) \n " ,
group ) ) ;
wb_delete_group ( & grp ) ;
return WINBINDD_ERROR ;
}
state - > response . data . rid = rid ;
}
2003-07-09 16:44:47 +00:00
2003-07-11 05:33:40 +00:00
return WINBINDD_OK ;
2003-07-09 16:44:47 +00:00
}
/**********************************************************************
Add a user to the membership for a group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_add_user_to_group ( struct winbindd_cli_state * state )
{
WINBINDD_PW * pw ;
WINBINDD_GR * grp ;
char * user , * group ;
BOOL ret ;
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_add_user_to_group: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . groupname [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . username ) - 1 ] = ' \0 ' ;
group = state - > request . data . acct_mgt . groupname ;
user = state - > request . data . acct_mgt . username ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: add_user_to_group: add %s to %s \n " , ( unsigned long ) state - > pid ,
2003-07-09 16:44:47 +00:00
user , group ) ) ;
/* make sure it is a valid user */
if ( ! ( pw = wb_getpwnam ( user ) ) ) {
DEBUG ( 4 , ( " winbindd_add_user_to_group: Cannot add a non-existent user \n " ) ) ;
return WINBINDD_ERROR ;
}
/* make sure it is a valid group */
if ( ! ( grp = wb_getgrnam ( group ) ) ) {
DEBUG ( 4 , ( " winbindd_add_user_to_group: Cannot add a user to a non-extistent group \n " ) ) ;
return WINBINDD_ERROR ;
}
if ( ! wb_addgrpmember ( grp , user ) )
return WINBINDD_ERROR ;
ret = wb_storegrnam ( grp ) ;
free_winbindd_gr ( grp ) ;
return ( ret ? WINBINDD_OK : WINBINDD_ERROR ) ;
}
/**********************************************************************
Remove a user from the membership of a group
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_remove_user_from_group ( struct winbindd_cli_state * state )
{
WINBINDD_GR * grp ;
char * user , * group ;
BOOL ret ;
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_remove_user_from_group: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . groupname [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . username ) - 1 ] = ' \0 ' ;
group = state - > request . data . acct_mgt . groupname ;
user = state - > request . data . acct_mgt . username ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: remove_user_to_group: delete %s from %s \n " , ( unsigned long ) state - > pid ,
2003-07-09 16:44:47 +00:00
user , group ) ) ;
/* don't worry about checking the username since we're removing it anyways */
/* make sure it is a valid group */
if ( ! ( grp = wb_getgrnam ( group ) ) ) {
DEBUG ( 4 , ( " winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group \n " ) ) ;
return WINBINDD_ERROR ;
}
if ( ! wb_delgrpmember ( grp , user ) )
return WINBINDD_ERROR ;
ret = wb_storegrnam ( grp ) ;
free_winbindd_gr ( grp ) ;
return ( ret ? WINBINDD_OK : WINBINDD_ERROR ) ;
}
/**********************************************************************
Set the primary group membership of a user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_set_user_primary_group ( struct winbindd_cli_state * state )
{
WINBINDD_PW * pw ;
WINBINDD_GR * grp ;
char * user , * group ;
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_set_user_primary_group: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . groupname [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . username ) - 1 ] = ' \0 ' ;
group = state - > request . data . acct_mgt . groupname ;
user = state - > request . data . acct_mgt . username ;
2003-07-22 06:52:39 +00:00
DEBUG ( 3 , ( " [%5lu]: set_user_primary_group: group %s for user %s \n " ,
( unsigned long ) state - > pid , group , user ) ) ;
2003-07-09 16:44:47 +00:00
/* make sure it is a valid user */
if ( ! ( pw = wb_getpwnam ( user ) ) ) {
DEBUG ( 4 , ( " winbindd_add_user_to_group: Cannot add a non-existent user \n " ) ) ;
return WINBINDD_ERROR ;
}
/* make sure it is a valid group */
if ( ! ( grp = wb_getgrnam ( group ) ) ) {
DEBUG ( 4 , ( " winbindd_add_user_to_group: Cannot add a user to a non-extistent group \n " ) ) ;
return WINBINDD_ERROR ;
}
pw - > pw_gid = grp - > gr_gid ;
free_winbindd_gr ( grp ) ;
return ( wb_storepwnam ( pw ) ? WINBINDD_OK : WINBINDD_ERROR ) ;
}
/**********************************************************************
2003-07-10 20:37:01 +00:00
Delete a user from the winbindd account tdb .
2003-07-09 16:44:47 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_delete_user ( struct winbindd_cli_state * state )
{
2003-07-10 20:37:01 +00:00
WINBINDD_PW * pw ;
char * user ;
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_delete_user: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . username ) - 1 ] = ' \0 ' ;
user = state - > request . data . acct_mgt . username ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: delete_user: %s \n " , ( unsigned long ) state - > pid , user ) ) ;
2003-07-10 20:37:01 +00:00
/* make sure it is a valid user */
if ( ! ( pw = wb_getpwnam ( user ) ) ) {
DEBUG ( 4 , ( " winbindd_delete_user: Cannot delete a non-existent user \n " ) ) ;
return WINBINDD_ERROR ;
}
2003-07-11 05:33:40 +00:00
return ( wb_delete_user ( pw ) ? WINBINDD_OK : WINBINDD_ERROR ) ;
2003-07-09 16:44:47 +00:00
}
/**********************************************************************
2003-07-10 20:37:01 +00:00
Delete a group from winbindd ' s account tdb .
2003-07-09 16:44:47 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum winbindd_result winbindd_delete_group ( struct winbindd_cli_state * state )
{
2003-07-10 20:37:01 +00:00
WINBINDD_GR * grp ;
char * group ;
2003-07-11 05:33:40 +00:00
BOOL ret ;
2003-07-10 20:37:01 +00:00
if ( ! state - > privileged ) {
DEBUG ( 2 , ( " winbindd_delete_group: non-privileged access denied! \n " ) ) ;
return WINBINDD_ERROR ;
}
/* Ensure null termination */
state - > request . data . acct_mgt . username [ sizeof ( state - > request . data . acct_mgt . groupname ) - 1 ] = ' \0 ' ;
group = state - > request . data . acct_mgt . groupname ;
2003-07-22 04:31:20 +00:00
DEBUG ( 3 , ( " [%5lu]: delete_group: %s \n " , ( unsigned long ) state - > pid , group ) ) ;
2003-07-10 20:37:01 +00:00
/* make sure it is a valid group */
if ( ! ( grp = wb_getgrnam ( group ) ) ) {
2003-07-11 05:33:40 +00:00
DEBUG ( 4 , ( " winbindd_delete_group: Cannot delete a non-existent group \n " ) ) ;
2003-07-10 20:37:01 +00:00
return WINBINDD_ERROR ;
}
2003-07-11 05:33:40 +00:00
ret = wb_delete_group ( grp ) ;
2003-07-10 20:37:01 +00:00
free_winbindd_gr ( grp ) ;
2003-07-11 05:33:40 +00:00
return ( ret ? WINBINDD_OK : WINBINDD_ERROR ) ;
2003-07-09 16:44:47 +00:00
}
2003-07-10 20:37:01 +00:00