2001-03-23 03:50:31 +03:00
/*
2002-01-30 09:08:46 +03:00
* Unix SMB / CIFS implementation .
2001-03-23 03:50:31 +03:00
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 2000 ,
2006-08-10 00:25:13 +04:00
* Copyright ( C ) Jean Francois Micouleau 1998 - 2001.
2006-03-15 03:10:38 +03:00
* Copyright ( C ) Volker Lendecke 2006.
* Copyright ( C ) Gerald Carter 2006.
2001-03-23 03:50:31 +03:00
*
* 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 "includes.h"
static TDB_CONTEXT * tdb ; /* used for driver files */
2002-01-09 08:24:07 +03:00
# define DATABASE_VERSION_V1 1 /* native byte format. */
# define DATABASE_VERSION_V2 2 /* le format. */
2006-08-10 00:25:13 +04:00
# define DATABASE_VERSION_V3 3 /* Indexed format */
2002-01-09 08:24:07 +03:00
2001-03-23 03:50:31 +03:00
# define GROUP_PREFIX "UNIXGROUP / "
2004-04-07 16:43:44 +04:00
/* Alias memberships are stored reverse, as memberships. The performance
* critical operation is to determine the aliases a SID is member of , not
* listing alias members . So we store a list of alias SIDs a SID is member of
* hanging of the member as key .
*/
# define MEMBEROF_PREFIX "MEMBEROF / "
2006-08-10 00:25:13 +04:00
static BOOL pack_group_map ( TALLOC_CTX * mem_ctx , const GROUP_MAP * map ,
TDB_DATA * data )
{
return tdb_pack_append ( mem_ctx , & data - > dptr , & data - > dsize , " fddff " ,
sid_string_static ( & map - > sid ) , map - > gid ,
map - > sid_name_use , map - > nt_name , map - > comment ) ;
}
2002-01-29 04:01:14 +03:00
2006-08-10 00:25:13 +04:00
static BOOL unpack_group_map ( TDB_DATA data , GROUP_MAP * map )
{
fstring sidstr ;
if ( ! tdb_unpack ( data . dptr , data . dsize , " fddff " , sidstr , & map - > gid ,
& map - > sid_name_use , & map - > nt_name , & map - > comment ) ) {
DEBUG ( 0 , ( " tdb_unpack failed \n " ) ) ;
return False ;
}
if ( ! string_to_sid ( & map - > sid , sidstr ) ) {
DEBUG ( 0 , ( " sid_string %s invalid \n " , sidstr ) ) ;
return False ;
}
return True ;
}
/*
* Calculate keys from the group mapping record
*
* We ' ve got 3 keys : SID , Name ( uppercased ) and gid
*/
# define KEYNUM_SID (0)
# define KEYNUM_NAME (1)
# define KEYNUM_GID (2)
static char * * group_mapping_keys ( TALLOC_CTX * mem_ctx , TDB_DATA data ,
void * private_data )
{
char * * result ;
GROUP_MAP map ;
GROUP_MAP * mapp = ( GROUP_MAP * ) private_data ;
if ( mapp = = NULL ) {
if ( ! unpack_group_map ( data , & map ) ) {
DEBUG ( 0 , ( " unpack_groupmap failed \n " ) ) ;
return NULL ;
}
mapp = & map ;
}
result = TALLOC_ARRAY ( mem_ctx , char * , 4 ) ;
if ( result = = NULL ) {
DEBUG ( 0 , ( " talloc_array failed \n " ) ) ;
return NULL ;
}
2006-08-15 12:05:52 +04:00
result [ KEYNUM_SID ] = talloc_strdup ( result ,
2006-08-10 00:25:13 +04:00
sid_string_static ( & mapp - > sid ) ) ;
2006-08-15 12:05:52 +04:00
result [ KEYNUM_NAME ] = talloc_strdup ( result , mapp - > nt_name ) ;
result [ KEYNUM_GID ] = talloc_asprintf ( result , " %d " , ( int ) mapp - > gid ) ;
2006-08-10 00:25:13 +04:00
result [ 3 ] = NULL ;
if ( ( result [ 0 ] = = NULL ) | | ( result [ 1 ] = = NULL ) | |
( result [ 2 ] = = NULL ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( result ) ;
return NULL ;
}
/* name lookups are case insensitive, store the key in upper case */
2006-08-15 12:05:52 +04:00
strupper_m ( result [ KEYNUM_NAME ] ) ;
2006-08-10 00:25:13 +04:00
return result ;
}
static NTSTATUS upgrade_groupdb_to_v3 ( struct tdb_context * groupdb )
{
TDB_DATA kbuf , newkey ;
NTSTATUS status ;
for ( kbuf = tdb_firstkey ( groupdb ) ;
kbuf . dptr ;
newkey = tdb_nextkey ( groupdb , kbuf ) , safe_free ( kbuf . dptr ) ,
kbuf = newkey ) {
fstring string_sid ;
TDB_DATA data , newdata ;
GROUP_MAP map ;
int ret ;
if ( strncmp ( kbuf . dptr , GROUP_PREFIX ,
strlen ( GROUP_PREFIX ) ) ! = 0 ) {
continue ;
}
data = tdb_fetch ( groupdb , kbuf ) ;
if ( ! data . dptr ) {
continue ;
}
fstrcpy ( string_sid , kbuf . dptr + strlen ( GROUP_PREFIX ) ) ;
ret = tdb_unpack ( data . dptr , data . dsize , " ddff " ,
& map . gid , & map . sid_name_use , & map . nt_name ,
& map . comment ) ;
SAFE_FREE ( data . dptr ) ;
if ( ret = = - 1 ) {
DEBUG ( 3 , ( " upgrade_groupdb_to_v3: tdb_unpack "
" failure \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ! string_to_sid ( & map . sid , string_sid ) ) {
DEBUG ( 3 , ( " Got invalid sid: %s \n " , string_sid ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( tdb_delete ( groupdb , kbuf ) < 0 ) {
status = map_ntstatus_from_tdb ( groupdb ) ;
DEBUG ( 3 , ( " tdb_delete failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
if ( map . gid = = - 1 ) {
DEBUG ( 3 , ( " Deleting umapped group %s \n " , map . nt_name ) ) ;
continue ;
}
ZERO_STRUCT ( newdata ) ;
if ( ! pack_group_map ( NULL , & map , & newdata ) ) {
DEBUG ( 0 , ( " pack_group_map_failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
status = tdb_add_keyed ( groupdb , group_mapping_keys ,
newdata , & map ) ;
TALLOC_FREE ( newdata . dptr ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECTID_EXISTS ) ) {
DEBUG ( 0 , ( " mapping for gid %d / name %s maps to "
" multiple SIDs -- rejected \n " ,
map . gid , map . nt_name ) ) ;
return status ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " tdb_add_keyed failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
}
return NT_STATUS_OK ;
}
2006-03-15 03:10:38 +03:00
2001-03-23 03:50:31 +03:00
/****************************************************************************
2002-01-09 07:13:30 +03:00
Open the group mapping tdb .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-09 07:13:30 +03:00
2006-08-09 19:25:26 +04:00
static NTSTATUS init_group_mapping ( void )
2001-03-23 03:50:31 +03:00
{
2003-01-03 11:28:12 +03:00
const char * vstring = " INFO/version " ;
2002-01-09 07:13:30 +03:00
int32 vers_id ;
2006-08-10 00:25:13 +04:00
NTSTATUS status ;
2002-01-09 07:13:30 +03:00
2004-11-06 00:55:21 +03:00
if ( tdb )
2006-08-09 19:25:26 +04:00
return NT_STATUS_OK ;
2006-03-15 03:10:38 +03:00
2006-08-09 19:25:26 +04:00
tdb = tdb_open_log ( lock_path ( " group_mapping.tdb " ) , 0 , TDB_DEFAULT ,
O_RDWR | O_CREAT , 0600 ) ;
2001-03-23 03:50:31 +03:00
if ( ! tdb ) {
2006-08-10 00:25:13 +04:00
DEBUG ( 0 , ( " Failed to open group mapping database: %s \n " ,
strerror ( errno ) ) ) ;
2006-08-09 19:25:26 +04:00
return map_nt_error_from_unix ( errno ) ;
2001-03-23 03:50:31 +03:00
}
2006-08-10 00:25:13 +04:00
if ( tdb_transaction_start ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " Could not start transaction: %s \n " ,
nt_errstr ( status ) ) ) ;
tdb_close ( tdb ) ;
tdb = NULL ;
return status ;
}
2002-01-09 07:13:30 +03:00
/* Cope with byte-reversed older versions of the db. */
vers_id = tdb_fetch_int32 ( tdb , vstring ) ;
2006-08-10 00:25:13 +04:00
if ( vers_id = = DATABASE_VERSION_V3 ) {
if ( tdb_transaction_cancel ( tdb ) < 0 ) {
smb_panic ( " tdb_cancel_transaction failed \n " ) ;
2006-03-15 03:10:38 +03:00
}
2006-08-10 00:25:13 +04:00
return NT_STATUS_OK ;
2006-03-15 03:10:38 +03:00
}
2006-08-10 00:25:13 +04:00
if ( vers_id < 0 ) {
tdb_store_int32 ( tdb , vstring , DATABASE_VERSION_V3 ) ;
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
if ( ( vers_id = = DATABASE_VERSION_V1 ) | |
( IREV ( vers_id ) = = DATABASE_VERSION_V1 ) ) {
2001-12-03 03:00:43 +03:00
2006-08-10 00:25:13 +04:00
/* Written on a bigendian machine with old fetch_int
* code . Save as le . */
tdb_store_int32 ( tdb , vstring , DATABASE_VERSION_V2 ) ;
vers_id = DATABASE_VERSION_V2 ;
2002-01-27 13:53:43 +03:00
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
if ( vers_id = = DATABASE_VERSION_V2 ) {
status = upgrade_groupdb_to_v3 ( tdb ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
tdb_store_int32 ( tdb , vstring , DATABASE_VERSION_V3 ) ;
}
2001-11-29 19:05:05 +03:00
2006-08-10 00:25:13 +04:00
if ( tdb_transaction_commit ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_transaction_commit failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto fail ;
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
return NT_STATUS_OK ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
fail :
if ( tdb_transaction_cancel ( tdb ) < 0 ) {
smb_panic ( " tdb_cancel_transaction failed \n " ) ;
2006-08-09 19:25:26 +04:00
}
2006-08-10 00:25:13 +04:00
tdb_close ( tdb ) ;
tdb = NULL ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
return status ;
2001-03-23 03:50:31 +03:00
}
2006-02-04 01:19:41 +03:00
/****************************************************************************
Map a unix group to a newly created mapping
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS map_unix_group ( const struct group * grp , GROUP_MAP * pmap )
{
NTSTATUS status ;
GROUP_MAP map ;
const char * grpname , * dom , * name ;
uint32 rid ;
2006-08-08 23:29:34 +04:00
if ( NT_STATUS_IS_OK ( pdb_getgrgid ( & map , grp - > gr_gid ) ) ) {
2006-02-04 01:19:41 +03:00
return NT_STATUS_GROUP_EXISTS ;
}
map . gid = grp - > gr_gid ;
grpname = grp - > gr_name ;
if ( lookup_name ( tmp_talloc_ctx ( ) , grpname , LOOKUP_NAME_ISOLATED ,
& dom , & name , NULL , NULL ) ) {
const char * tmp = talloc_asprintf (
tmp_talloc_ctx ( ) , " Unix Group %s " , grp - > gr_name ) ;
DEBUG ( 5 , ( " %s exists as %s \\ %s, retrying as \" %s \" \n " ,
grpname , dom , name , tmp ) ) ;
grpname = tmp ;
}
if ( lookup_name ( tmp_talloc_ctx ( ) , grpname , LOOKUP_NAME_ISOLATED ,
NULL , NULL , NULL , NULL ) ) {
DEBUG ( 3 , ( " \" %s \" exists, can't map it \n " , grp - > gr_name ) ) ;
return NT_STATUS_GROUP_EXISTS ;
}
fstrcpy ( map . nt_name , grpname ) ;
if ( pdb_rid_algorithm ( ) ) {
rid = pdb_gid_to_group_rid ( grp - > gr_gid ) ;
} else {
if ( ! pdb_new_rid ( & rid ) ) {
DEBUG ( 3 , ( " Could not get a new RID for %s \n " ,
grp - > gr_name ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
}
sid_compose ( & map . sid , get_global_sam_sid ( ) , rid ) ;
map . sid_name_use = SID_NAME_DOM_GRP ;
fstrcpy ( map . comment , talloc_asprintf ( tmp_talloc_ctx ( ) , " Unix Group %s " ,
grp - > gr_name ) ) ;
status = pdb_add_group_mapping_entry ( & map ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
* pmap = map ;
}
return status ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-11-23 05:52:36 +03:00
Return the sid and the type of the unix group .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-23 05:52:36 +03:00
2006-08-09 19:25:26 +04:00
static NTSTATUS get_group_map_from_sid ( const DOM_SID * sid , GROUP_MAP * map )
2001-03-23 03:50:31 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
2006-08-09 19:25:26 +04:00
NTSTATUS status ;
2006-08-10 00:25:13 +04:00
2006-08-09 19:25:26 +04:00
status = init_group_mapping ( ) ;
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
2006-08-09 19:25:26 +04:00
return status ;
2002-01-27 13:53:43 +03:00
}
2001-12-03 03:00:43 +03:00
2006-08-10 00:25:13 +04:00
status = tdb_find_keyed ( NULL , tdb , KEYNUM_SID , sid_string_static ( sid ) ,
& data , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2006-08-09 19:25:26 +04:00
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
status = unpack_group_map ( data , map ) ?
NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
TALLOC_FREE ( data . dptr ) ;
return status ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-11-23 05:52:36 +03:00
Return the sid and the type of the unix group .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-23 05:52:36 +03:00
2006-08-09 19:25:26 +04:00
static NTSTATUS get_group_map_from_gid ( gid_t gid , GROUP_MAP * map )
2001-03-23 03:50:31 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
2006-08-09 19:25:26 +04:00
NTSTATUS status ;
2006-08-10 00:25:13 +04:00
char * gidstr ;
2001-03-23 03:50:31 +03:00
2006-08-09 19:25:26 +04:00
status = init_group_mapping ( ) ;
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
2006-08-09 19:25:26 +04:00
return status ;
2002-01-27 13:53:43 +03:00
}
2001-12-03 03:00:43 +03:00
2006-08-10 00:25:13 +04:00
if ( asprintf ( & gidstr , " %d " , ( int ) gid ) < 0 ) {
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
status = tdb_find_keyed ( NULL , tdb , KEYNUM_GID , gidstr , & data , NULL ) ;
SAFE_FREE ( gidstr ) ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2001-03-23 03:50:31 +03:00
}
2006-08-10 00:25:13 +04:00
status = unpack_group_map ( data , map ) ?
NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION ;
TALLOC_FREE ( data . dptr ) ;
return status ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-11-23 05:52:36 +03:00
Return the sid and the type of the unix group .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-23 05:52:36 +03:00
2006-08-09 19:25:26 +04:00
static NTSTATUS get_group_map_from_ntname ( const char * name , GROUP_MAP * map )
2001-03-23 03:50:31 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
2006-08-09 19:25:26 +04:00
NTSTATUS status ;
2006-08-10 00:25:13 +04:00
char * tmp ;
2001-03-23 03:50:31 +03:00
2006-08-09 19:25:26 +04:00
status = init_group_mapping ( ) ;
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
2006-08-09 19:25:26 +04:00
return status ;
2002-01-27 13:53:43 +03:00
}
2001-12-03 03:00:43 +03:00
2006-08-10 00:25:13 +04:00
tmp = SMB_STRDUP ( name ) ;
if ( tmp = = NULL ) {
DEBUG ( 0 , ( " strdup failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
2001-03-23 03:50:31 +03:00
}
2006-08-10 00:25:13 +04:00
/*
* The name is stored uppercase to make the search case insensitive
*/
2001-12-03 03:00:43 +03:00
2006-08-10 00:25:13 +04:00
strupper_m ( tmp ) ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
status = tdb_find_keyed ( NULL , tdb , KEYNUM_NAME , tmp , & data , NULL ) ;
SAFE_FREE ( tmp ) ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
status = unpack_group_map ( data , map ) ?
NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
TALLOC_FREE ( data . dptr ) ;
return status ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-11-23 05:52:36 +03:00
Enumerate the group mapping .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-23 05:52:36 +03:00
2006-08-09 19:25:26 +04:00
static NTSTATUS enum_group_mapping ( const DOM_SID * domsid ,
enum SID_NAME_USE sid_name_use ,
GROUP_MAP * * pp_rmap ,
size_t * p_num_entries , BOOL unix_only )
2001-03-23 03:50:31 +03:00
{
2006-08-10 00:25:13 +04:00
struct tdb_keyed_iterator * iterator ;
TDB_DATA dbuf ;
2006-08-09 19:25:26 +04:00
NTSTATUS status ;
2001-03-23 03:50:31 +03:00
2006-08-09 19:25:26 +04:00
status = init_group_mapping ( ) ;
2006-08-10 00:25:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
2006-08-09 19:25:26 +04:00
return status ;
2002-01-27 13:53:43 +03:00
}
2001-12-03 03:00:43 +03:00
2005-10-18 07:24:00 +04:00
* p_num_entries = 0 ;
* pp_rmap = NULL ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
iterator = tdb_enum_keyed ( NULL , tdb ) ;
if ( iterator = = NULL ) {
DEBUG ( 0 , ( " tdb_enum_keyed failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
while ( tdb_next_keyed ( iterator , & dbuf ) ) {
2003-05-12 22:12:31 +04:00
2006-08-10 00:25:13 +04:00
GROUP_MAP map ;
DOM_SID grpsid ;
uint32 rid ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
if ( ! unpack_group_map ( dbuf , & map ) ) {
DEBUG ( 5 , ( " Got invalid group mapping entry \n " ) ) ;
TALLOC_FREE ( dbuf . dptr ) ;
continue ;
}
2001-03-23 03:50:31 +03:00
2001-09-17 04:58:15 +04:00
SAFE_FREE ( dbuf . dptr ) ;
2001-03-23 03:50:31 +03:00
/* list only the type or everything if UNKNOWN */
2006-08-10 00:25:13 +04:00
if ( sid_name_use ! = SID_NAME_UNKNOWN & &
sid_name_use ! = map . sid_name_use ) {
DEBUG ( 11 , ( " enum_group_mapping: group %s is not of the "
" requested type \n " , map . nt_name ) ) ;
2001-05-04 19:44:27 +04:00
continue ;
2001-11-29 19:05:05 +03:00
}
2003-05-12 22:12:31 +04:00
2001-11-29 19:05:05 +03:00
if ( unix_only = = ENUM_ONLY_MAPPED & & map . gid = = - 1 ) {
2006-08-10 00:25:13 +04:00
DEBUG ( 11 , ( " enum_group_mapping: group %s is non "
" mapped \n " , map . nt_name ) ) ;
2001-05-04 19:44:27 +04:00
continue ;
2001-11-29 19:05:05 +03:00
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
sid_copy ( & grpsid , & map . sid ) ;
2006-03-15 03:10:38 +03:00
sid_split_rid ( & grpsid , & rid ) ;
/* Only check the domain if we were given one */
if ( domsid & & ! sid_equal ( domsid , & grpsid ) ) {
2006-08-10 00:25:13 +04:00
DEBUG ( 11 , ( " enum_group_mapping: group %s is not in "
" domain %s \n " , sid_string_static ( & map . sid ) ,
sid_string_static ( domsid ) ) ) ;
2006-03-15 03:10:38 +03:00
continue ;
}
2005-12-12 00:59:58 +03:00
DEBUG ( 11 , ( " enum_group_mapping: returning group %s of "
" type %s \n " , map . nt_name ,
sid_type_lookup ( map . sid_name_use ) ) ) ;
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
ADD_TO_ARRAY ( NULL , GROUP_MAP , map , pp_rmap , p_num_entries ) ;
if ( * pp_rmap = = NULL ) {
DEBUG ( 0 , ( " ADD_TO_ARRAY failed \n " ) ) ;
2006-08-09 19:25:26 +04:00
return NT_STATUS_NO_MEMORY ;
2001-08-12 21:30:01 +04:00
}
2001-03-23 03:50:31 +03:00
}
2006-08-09 19:25:26 +04:00
return NT_STATUS_OK ;
2001-03-23 03:50:31 +03:00
}
2004-04-07 16:43:44 +04:00
/* This operation happens on session setup, so it should better be fast. We
* store a list of aliases a SID is member of hanging off MEMBEROF / SID . */
2004-11-06 02:34:00 +03:00
static NTSTATUS one_alias_membership ( const DOM_SID * member ,
2005-10-18 07:24:00 +04:00
DOM_SID * * sids , size_t * num )
2004-04-07 16:43:44 +04:00
{
fstring key , string_sid ;
TDB_DATA kbuf , dbuf ;
const char * p ;
2006-08-09 19:25:26 +04:00
if ( ! NT_STATUS_IS_OK ( init_group_mapping ( ) ) ) {
2004-04-07 16:43:44 +04:00
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2004-11-06 02:34:00 +03:00
sid_to_string ( string_sid , member ) ;
2004-04-07 16:43:44 +04:00
slprintf ( key , sizeof ( key ) , " %s%s " , MEMBEROF_PREFIX , string_sid ) ;
kbuf . dsize = strlen ( key ) + 1 ;
kbuf . dptr = key ;
dbuf = tdb_fetch ( tdb , kbuf ) ;
if ( dbuf . dptr = = NULL ) {
return NT_STATUS_OK ;
}
p = dbuf . dptr ;
while ( next_token ( & p , string_sid , " " , sizeof ( string_sid ) ) ) {
DOM_SID alias ;
if ( ! string_to_sid ( & alias , string_sid ) )
continue ;
2005-03-27 20:33:04 +04:00
add_sid_to_array_unique ( NULL , & alias , sids , num ) ;
2004-04-07 16:43:44 +04:00
if ( sids = = NULL )
return NT_STATUS_NO_MEMORY ;
}
SAFE_FREE ( dbuf . dptr ) ;
return NT_STATUS_OK ;
}
2005-10-18 07:24:00 +04:00
static NTSTATUS alias_memberships ( const DOM_SID * members , size_t num_members ,
DOM_SID * * sids , size_t * num )
2004-11-06 02:34:00 +03:00
{
2005-10-18 07:24:00 +04:00
size_t i ;
2004-11-06 02:34:00 +03:00
* num = 0 ;
* sids = NULL ;
for ( i = 0 ; i < num_members ; i + + ) {
NTSTATUS status = one_alias_membership ( & members [ i ] , sids , num ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
return status ;
}
return NT_STATUS_OK ;
}
2004-04-07 16:43:44 +04:00
static BOOL is_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
{
DOM_SID * sids ;
2005-10-18 07:24:00 +04:00
size_t i , num ;
2004-04-07 16:43:44 +04:00
/* This feels the wrong way round, but the on-disk data structure
* dictates it this way . */
2004-11-06 02:34:00 +03:00
if ( ! NT_STATUS_IS_OK ( alias_memberships ( member , 1 , & sids , & num ) ) )
2004-04-07 16:43:44 +04:00
return False ;
for ( i = 0 ; i < num ; i + + ) {
if ( sid_compare ( alias , & sids [ i ] ) = = 0 ) {
SAFE_FREE ( sids ) ;
return True ;
}
}
SAFE_FREE ( sids ) ;
return False ;
}
static NTSTATUS add_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
{
GROUP_MAP map ;
TDB_DATA kbuf , dbuf ;
pstring key ;
fstring string_sid ;
char * new_memberstring ;
2006-08-10 00:25:13 +04:00
NTSTATUS status ;
2004-04-07 16:43:44 +04:00
2006-08-10 00:25:13 +04:00
status = init_group_mapping ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-04-07 16:43:44 +04:00
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
2006-08-10 00:25:13 +04:00
return status ;
2004-04-07 16:43:44 +04:00
}
2006-08-10 00:25:13 +04:00
if ( tdb_transaction_start ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " Could not start transaction: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
status = get_group_map_from_sid ( alias , & map ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
status = NT_STATUS_NO_SUCH_ALIAS ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2004-04-07 16:43:44 +04:00
if ( ( map . sid_name_use ! = SID_NAME_ALIAS ) & &
2006-08-10 00:25:13 +04:00
( map . sid_name_use ! = SID_NAME_WKN_GRP ) ) {
status = NT_STATUS_NO_SUCH_ALIAS ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
2006-08-10 00:25:13 +04:00
if ( is_aliasmem ( alias , member ) ) {
status = NT_STATUS_MEMBER_IN_ALIAS ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
sid_to_string ( string_sid , member ) ;
slprintf ( key , sizeof ( key ) , " %s%s " , MEMBEROF_PREFIX , string_sid ) ;
kbuf . dsize = strlen ( key ) + 1 ;
kbuf . dptr = key ;
dbuf = tdb_fetch ( tdb , kbuf ) ;
sid_to_string ( string_sid , alias ) ;
if ( dbuf . dptr ! = NULL ) {
asprintf ( & new_memberstring , " %s %s " , ( char * ) ( dbuf . dptr ) ,
string_sid ) ;
} else {
2004-12-07 21:25:53 +03:00
new_memberstring = SMB_STRDUP ( string_sid ) ;
2004-04-07 16:43:44 +04:00
}
2006-08-10 00:25:13 +04:00
if ( new_memberstring = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
SAFE_FREE ( dbuf . dptr ) ;
dbuf . dsize = strlen ( new_memberstring ) + 1 ;
dbuf . dptr = new_memberstring ;
2006-08-10 00:25:13 +04:00
if ( tdb_store ( tdb , kbuf , dbuf , 0 ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_store failed: %s \n " , nt_errstr ( status ) ) ) ;
SAFE_FREE ( new_memberstring ) ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
SAFE_FREE ( new_memberstring ) ;
2006-08-10 00:25:13 +04:00
if ( tdb_transaction_commit ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_transaction_commit failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto fail ;
}
return NT_STATUS_OK ;
fail :
if ( tdb_transaction_cancel ( tdb ) < 0 ) {
smb_panic ( " tdb_cancel_transaction failed \n " ) ;
}
return status ;
2004-04-07 16:43:44 +04:00
}
struct aliasmem_closure {
const DOM_SID * alias ;
DOM_SID * * sids ;
2005-10-18 07:24:00 +04:00
size_t * num ;
2004-04-07 16:43:44 +04:00
} ;
static int collect_aliasmem ( TDB_CONTEXT * tdb_ctx , TDB_DATA key , TDB_DATA data ,
void * state )
{
struct aliasmem_closure * closure = ( struct aliasmem_closure * ) state ;
const char * p ;
fstring alias_string ;
if ( strncmp ( key . dptr , MEMBEROF_PREFIX ,
strlen ( MEMBEROF_PREFIX ) ) ! = 0 )
return 0 ;
p = data . dptr ;
while ( next_token ( & p , alias_string , " " , sizeof ( alias_string ) ) ) {
DOM_SID alias , member ;
const char * member_string ;
if ( ! string_to_sid ( & alias , alias_string ) )
continue ;
if ( sid_compare ( closure - > alias , & alias ) ! = 0 )
continue ;
/* Ok, we found the alias we're looking for in the membership
* list currently scanned . The key represents the alias
* member . Add that . */
member_string = strchr ( key . dptr , ' / ' ) ;
/* Above we tested for MEMBEROF_PREFIX which includes the
* slash . */
SMB_ASSERT ( member_string ! = NULL ) ;
member_string + = 1 ;
if ( ! string_to_sid ( & member , member_string ) )
continue ;
2005-03-27 20:33:04 +04:00
add_sid_to_array ( NULL , & member , closure - > sids , closure - > num ) ;
2004-04-07 16:43:44 +04:00
}
return 0 ;
}
2006-08-10 00:25:13 +04:00
static NTSTATUS enum_aliasmem ( const DOM_SID * alias , DOM_SID * * sids ,
size_t * num )
2004-04-07 16:43:44 +04:00
{
GROUP_MAP map ;
struct aliasmem_closure closure ;
2006-08-09 19:25:26 +04:00
if ( ! NT_STATUS_IS_OK ( init_group_mapping ( ) ) ) {
2004-04-07 16:43:44 +04:00
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2006-08-09 19:25:26 +04:00
if ( ! NT_STATUS_IS_OK ( get_group_map_from_sid ( alias , & map ) ) )
2004-04-07 16:43:44 +04:00
return NT_STATUS_NO_SUCH_ALIAS ;
if ( ( map . sid_name_use ! = SID_NAME_ALIAS ) & &
( map . sid_name_use ! = SID_NAME_WKN_GRP ) )
return NT_STATUS_NO_SUCH_ALIAS ;
* sids = NULL ;
* num = 0 ;
closure . alias = alias ;
closure . sids = sids ;
closure . num = num ;
tdb_traverse ( tdb , collect_aliasmem , & closure ) ;
return NT_STATUS_OK ;
}
static NTSTATUS del_aliasmem ( const DOM_SID * alias , const DOM_SID * member )
{
2006-08-10 00:25:13 +04:00
NTSTATUS status ;
DOM_SID * sids = NULL ;
2005-10-18 07:24:00 +04:00
size_t i , num ;
2004-04-07 16:43:44 +04:00
BOOL found = False ;
2006-08-10 00:25:13 +04:00
char * member_string = NULL ;
2004-04-07 16:43:44 +04:00
TDB_DATA kbuf , dbuf ;
pstring key ;
fstring sid_string ;
2006-08-10 00:25:13 +04:00
status = init_group_mapping ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
return status ;
}
if ( tdb_transaction_start ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " Could not start transaction: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
2004-04-07 16:43:44 +04:00
2006-08-10 00:25:13 +04:00
status = alias_memberships ( member , 1 , & sids , & num ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2004-04-07 16:43:44 +04:00
for ( i = 0 ; i < num ; i + + ) {
if ( sid_compare ( & sids [ i ] , alias ) = = 0 ) {
found = True ;
break ;
}
}
if ( ! found ) {
SAFE_FREE ( sids ) ;
2006-08-10 00:25:13 +04:00
status = NT_STATUS_MEMBER_NOT_IN_ALIAS ;
goto fail ;
2004-04-07 16:43:44 +04:00
}
if ( i < num )
sids [ i ] = sids [ num - 1 ] ;
num - = 1 ;
sid_to_string ( sid_string , member ) ;
slprintf ( key , sizeof ( key ) , " %s%s " , MEMBEROF_PREFIX , sid_string ) ;
kbuf . dsize = strlen ( key ) + 1 ;
kbuf . dptr = key ;
2006-08-10 00:25:13 +04:00
if ( num = = 0 ) {
if ( tdb_delete ( tdb , kbuf ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_delete failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto fail ;
}
goto ok ;
}
2004-04-07 16:43:44 +04:00
2004-12-07 21:25:53 +03:00
member_string = SMB_STRDUP ( " " ) ;
2004-04-07 16:43:44 +04:00
if ( member_string = = NULL ) {
SAFE_FREE ( sids ) ;
2006-08-10 00:25:13 +04:00
status = NT_STATUS_NO_MEMORY ;
2004-04-07 16:43:44 +04:00
}
for ( i = 0 ; i < num ; i + + ) {
char * s = member_string ;
sid_to_string ( sid_string , & sids [ i ] ) ;
asprintf ( & member_string , " %s %s " , s , sid_string ) ;
SAFE_FREE ( s ) ;
if ( member_string = = NULL ) {
SAFE_FREE ( sids ) ;
2006-08-10 00:25:13 +04:00
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2004-04-07 16:43:44 +04:00
}
}
dbuf . dsize = strlen ( member_string ) + 1 ;
dbuf . dptr = member_string ;
2006-08-10 00:25:13 +04:00
if ( tdb_store ( tdb , kbuf , dbuf , 0 ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_store failed: %s \n " , nt_errstr ( status ) ) ) ;
SAFE_FREE ( sids ) ;
SAFE_FREE ( member_string ) ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
2006-08-10 00:25:13 +04:00
ok :
2004-04-07 16:43:44 +04:00
SAFE_FREE ( sids ) ;
SAFE_FREE ( member_string ) ;
2006-08-10 00:25:13 +04:00
if ( tdb_transaction_commit ( tdb ) < 0 ) {
status = map_ntstatus_from_tdb ( tdb ) ;
DEBUG ( 5 , ( " tdb_transaction_commit failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto fail ;
}
2004-04-07 16:43:44 +04:00
2006-08-10 00:25:13 +04:00
return NT_STATUS_OK ;
fail :
SAFE_FREE ( sids ) ;
SAFE_FREE ( member_string ) ;
if ( tdb_transaction_cancel ( tdb ) < 0 ) {
smb_panic ( " tdb_cancel_transaction failed \n " ) ;
}
return status ;
2004-04-07 16:43:44 +04:00
}
2001-03-23 03:50:31 +03:00
/*
*
* High level functions
* better to use them than the lower ones .
*
* we are checking if the group is in the mapping file
* and if the group is an existing unix group
*
*/
/* get a domain group from it's SID */
2006-08-09 19:25:26 +04:00
NTSTATUS get_domain_group_from_sid ( const DOM_SID * sid , GROUP_MAP * map )
2001-03-23 03:50:31 +03:00
{
struct group * grp ;
2006-08-09 19:25:26 +04:00
NTSTATUS status ;
status = init_group_mapping ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
2002-01-29 04:01:14 +03:00
}
2001-05-04 19:44:27 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid \n " ) ) ;
2001-03-23 03:50:31 +03:00
/* if the group is NOT in the database, it CAN NOT be a domain group */
2003-12-10 19:40:17 +03:00
become_root ( ) ;
2006-08-09 19:25:26 +04:00
status = pdb_getgrsid ( map , sid ) ;
2003-12-10 19:40:17 +03:00
unbecome_root ( ) ;
2006-03-15 20:40:28 +03:00
/* special case check for rid 513 */
2006-08-09 19:25:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-03-15 20:40:28 +03:00
uint32 rid ;
2006-08-08 12:26:40 +04:00
sid_peek_rid ( sid , & rid ) ;
2006-03-15 20:40:28 +03:00
if ( rid = = DOMAIN_GROUP_RID_USERS ) {
fstrcpy ( map - > nt_name , " None " ) ;
fstrcpy ( map - > comment , " Ordinary Users " ) ;
2006-08-08 12:26:40 +04:00
sid_copy ( & map - > sid , sid ) ;
2006-03-15 20:40:28 +03:00
map - > sid_name_use = SID_NAME_DOM_GRP ;
2006-08-09 19:25:26 +04:00
return NT_STATUS_OK ;
2006-03-15 20:40:28 +03:00
}
2006-08-09 19:25:26 +04:00
return status ;
2006-03-15 20:40:28 +03:00
}
2001-03-23 03:50:31 +03:00
2001-05-04 19:44:27 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid: SID found in the TDB \n " ) ) ;
2001-03-23 03:50:31 +03:00
/* if it's not a domain group, continue */
2001-12-05 00:53:47 +03:00
if ( map - > sid_name_use ! = SID_NAME_DOM_GRP ) {
2006-08-09 19:25:26 +04:00
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
2001-12-05 00:53:47 +03:00
}
2001-05-04 19:44:27 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid: SID is a domain group \n " ) ) ;
2001-03-23 03:50:31 +03:00
2001-12-05 00:53:47 +03:00
if ( map - > gid = = - 1 ) {
2006-08-09 19:25:26 +04:00
return NT_STATUS_NOT_FOUND ;
2001-12-05 00:53:47 +03:00
}
2001-03-23 03:50:31 +03:00
2006-08-10 00:25:13 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid: SID is mapped to gid:%lu \n " ,
( unsigned long ) map - > gid ) ) ;
2003-08-15 21:01:49 +04:00
2003-08-15 21:38:11 +04:00
grp = getgrgid ( map - > gid ) ;
2003-08-15 21:01:49 +04:00
if ( ! grp ) {
2006-08-10 00:25:13 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid: gid DOESN'T exist in "
" UNIX security \n " ) ) ;
2006-08-09 19:25:26 +04:00
return NT_STATUS_NOT_FOUND ;
2001-12-02 02:56:05 +03:00
}
2001-05-04 19:44:27 +04:00
2006-08-10 00:25:13 +04:00
DEBUG ( 10 , ( " get_domain_group_from_sid: gid exists in UNIX "
" security \n " ) ) ;
2001-03-23 03:50:31 +03:00
2006-08-09 19:25:26 +04:00
return NT_STATUS_OK ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
Create a UNIX group on demand .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-13 20:08:25 +03:00
int smb_create_group ( const char * unix_group , gid_t * new_gid )
2001-03-23 03:50:31 +03:00
{
pstring add_script ;
2003-07-16 06:20:53 +04:00
int ret = - 1 ;
int fd = 0 ;
* new_gid = 0 ;
2001-03-23 03:50:31 +03:00
2003-07-09 20:44:47 +04:00
/* defer to scripts */
if ( * lp_addgroup_script ( ) ) {
pstrcpy ( add_script , lp_addgroup_script ( ) ) ;
pstring_sub ( add_script , " %g " , unix_group ) ;
2006-03-07 19:28:05 +03:00
ret = smbrun ( add_script , & fd ) ;
2005-02-07 21:20:06 +03:00
DEBUG ( ret ? 0 : 3 , ( " smb_create_group: Running the command `%s' gave %d \n " , add_script , ret ) ) ;
2003-07-09 20:44:47 +04:00
if ( ret ! = 0 )
return ret ;
if ( fd ! = 0 ) {
fstring output ;
* new_gid = 0 ;
if ( read ( fd , output , sizeof ( output ) ) > 0 ) {
* new_gid = ( gid_t ) strtoul ( output , NULL , 10 ) ;
}
2003-07-16 06:20:53 +04:00
2003-07-09 20:44:47 +04:00
close ( fd ) ;
2002-09-25 19:19:00 +04:00
}
2005-09-30 21:13:37 +04:00
}
2003-07-16 06:20:53 +04:00
if ( * new_gid = = 0 ) {
struct group * grp = getgrnam ( unix_group ) ;
if ( grp ! = NULL )
* new_gid = grp - > gr_gid ;
2003-07-09 20:44:47 +04:00
}
2003-07-16 06:20:53 +04:00
return ret ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
Delete a UNIX group on demand .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-13 20:08:25 +03:00
int smb_delete_group ( const char * unix_group )
2001-03-23 03:50:31 +03:00
{
pstring del_script ;
int ret ;
2003-07-09 20:44:47 +04:00
/* defer to scripts */
if ( * lp_delgroup_script ( ) ) {
pstrcpy ( del_script , lp_delgroup_script ( ) ) ;
pstring_sub ( del_script , " %g " , unix_group ) ;
ret = smbrun ( del_script , NULL ) ;
2005-02-07 21:20:06 +03:00
DEBUG ( ret ? 0 : 3 , ( " smb_delete_group: Running the command `%s' gave %d \n " , del_script , ret ) ) ;
2003-07-09 20:44:47 +04:00
return ret ;
}
2005-09-30 21:13:37 +04:00
2003-07-09 20:44:47 +04:00
return - 1 ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Set a user ' s primary UNIX group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int smb_set_primary_group ( const char * unix_group , const char * unix_user )
{
pstring add_script ;
int ret ;
2003-07-09 20:44:47 +04:00
/* defer to scripts */
if ( * lp_setprimarygroup_script ( ) ) {
pstrcpy ( add_script , lp_setprimarygroup_script ( ) ) ;
all_string_sub ( add_script , " %g " , unix_group , sizeof ( add_script ) ) ;
all_string_sub ( add_script , " %u " , unix_user , sizeof ( add_script ) ) ;
ret = smbrun ( add_script , NULL ) ;
2005-03-03 19:52:44 +03:00
flush_pwnam_cache ( ) ;
2005-02-07 21:20:06 +03:00
DEBUG ( ret ? 0 : 3 , ( " smb_set_primary_group: "
2003-07-09 20:44:47 +04:00
" Running the command `%s' gave %d \n " , add_script , ret ) ) ;
return ret ;
}
return - 1 ;
2002-09-25 19:19:00 +04:00
}
/****************************************************************************
Add a user to a UNIX group .
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-13 20:08:25 +03:00
int smb_add_user_group ( const char * unix_group , const char * unix_user )
2001-03-23 03:50:31 +03:00
{
pstring add_script ;
int ret ;
2003-07-09 20:44:47 +04:00
/* defer to scripts */
if ( * lp_addusertogroup_script ( ) ) {
pstrcpy ( add_script , lp_addusertogroup_script ( ) ) ;
pstring_sub ( add_script , " %g " , unix_group ) ;
pstring_sub ( add_script , " %u " , unix_user ) ;
ret = smbrun ( add_script , NULL ) ;
2005-02-07 21:20:06 +03:00
DEBUG ( ret ? 0 : 3 , ( " smb_add_user_group: Running the command `%s' gave %d \n " , add_script , ret ) ) ;
2003-07-09 20:44:47 +04:00
return ret ;
}
return - 1 ;
2001-03-23 03:50:31 +03:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Delete a user from a UNIX group
2001-03-23 03:50:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-02 10:41:54 +03:00
int smb_delete_user_group ( const char * unix_group , const char * unix_user )
2001-03-23 03:50:31 +03:00
{
pstring del_script ;
int ret ;
2003-07-09 20:44:47 +04:00
/* defer to scripts */
if ( * lp_deluserfromgroup_script ( ) ) {
pstrcpy ( del_script , lp_deluserfromgroup_script ( ) ) ;
pstring_sub ( del_script , " %g " , unix_group ) ;
pstring_sub ( del_script , " %u " , unix_user ) ;
ret = smbrun ( del_script , NULL ) ;
2005-02-07 21:20:06 +03:00
DEBUG ( ret ? 0 : 3 , ( " smb_delete_user_group: Running the command `%s' gave %d \n " , del_script , ret ) ) ;
2003-07-09 20:44:47 +04:00
return ret ;
}
return - 1 ;
2001-03-23 03:50:31 +03:00
}
2003-03-22 12:03:46 +03:00
NTSTATUS pdb_default_getgrsid ( struct pdb_methods * methods , GROUP_MAP * map ,
2006-08-08 12:26:40 +04:00
const DOM_SID * sid )
2003-03-22 12:03:46 +03:00
{
2006-08-09 19:25:26 +04:00
return get_group_map_from_sid ( sid , map ) ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_getgrgid ( struct pdb_methods * methods , GROUP_MAP * map ,
2003-06-18 19:24:10 +04:00
gid_t gid )
2003-03-22 12:03:46 +03:00
{
2006-08-09 19:25:26 +04:00
return get_group_map_from_gid ( gid , map ) ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_getgrnam ( struct pdb_methods * methods , GROUP_MAP * map ,
2003-06-18 19:24:10 +04:00
const char * name )
2003-03-22 12:03:46 +03:00
{
2006-08-09 19:25:26 +04:00
return get_group_map_from_ntname ( name , map ) ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_add_group_mapping_entry ( struct pdb_methods * methods ,
2006-08-10 00:25:13 +04:00
GROUP_MAP * map )
2003-03-22 12:03:46 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
NTSTATUS status ;
status = init_group_mapping ( ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " failed to initialize group mapping \n " ) ) ;
return status ;
}
ZERO_STRUCT ( data ) ;
if ( ! pack_group_map ( NULL , map , & data ) ) {
DEBUG ( 0 , ( " pack_group_map failed \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
status = tdb_add_keyed ( tdb , group_mapping_keys , data , map ) ;
TALLOC_FREE ( data . dptr ) ;
return status ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_update_group_mapping_entry ( struct pdb_methods * methods ,
2006-08-10 00:25:13 +04:00
GROUP_MAP * map )
2003-03-22 12:03:46 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
char * primary_key ;
NTSTATUS status ;
status = tdb_find_keyed ( NULL , tdb , KEYNUM_SID ,
sid_string_static ( & map - > sid ) ,
& data , & primary_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
TALLOC_FREE ( data . dptr ) ;
ZERO_STRUCT ( data ) ;
if ( ! pack_group_map ( NULL , map , & data ) ) {
DEBUG ( 0 , ( " pack_group_map failed \n " ) ) ;
SAFE_FREE ( primary_key ) ;
return NT_STATUS_NO_MEMORY ;
}
status = tdb_update_keyed ( tdb , primary_key , group_mapping_keys ,
data , NULL ) ;
TALLOC_FREE ( data . dptr ) ;
TALLOC_FREE ( primary_key ) ;
return status ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_delete_group_mapping_entry ( struct pdb_methods * methods ,
2006-08-10 00:25:13 +04:00
DOM_SID sid )
2003-03-22 12:03:46 +03:00
{
2006-08-10 00:25:13 +04:00
TDB_DATA data ;
char * primary_key ;
NTSTATUS status ;
GROUP_MAP map ;
status = tdb_find_keyed ( NULL , tdb , KEYNUM_SID , sid_string_static ( & sid ) ,
& data , & primary_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! unpack_group_map ( data , & map ) ) {
DEBUG ( 0 , ( " unpack_group_map failed \n " ) ) ;
TALLOC_FREE ( data . dptr ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
TALLOC_FREE ( data . dptr ) ;
status = tdb_del_keyed ( tdb , group_mapping_keys , primary_key , & map ) ;
TALLOC_FREE ( primary_key ) ;
return status ;
2003-03-22 12:03:46 +03:00
}
NTSTATUS pdb_default_enum_group_mapping ( struct pdb_methods * methods ,
2006-08-09 19:25:26 +04:00
const DOM_SID * sid ,
enum SID_NAME_USE sid_name_use ,
GROUP_MAP * * pp_rmap ,
size_t * p_num_entries ,
BOOL unix_only )
2003-03-22 12:03:46 +03:00
{
2006-08-09 19:25:26 +04:00
return enum_group_mapping ( sid , sid_name_use , pp_rmap , p_num_entries ,
unix_only ) ;
2003-03-22 12:03:46 +03:00
}
2004-04-07 16:43:44 +04:00
NTSTATUS pdb_default_create_alias ( struct pdb_methods * methods ,
const char * name , uint32 * rid )
{
DOM_SID sid ;
enum SID_NAME_USE type ;
uint32 new_rid ;
gid_t gid ;
2005-12-03 21:34:13 +03:00
BOOL exists ;
2004-04-07 16:43:44 +04:00
GROUP_MAP map ;
2006-02-04 01:19:41 +03:00
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
2004-04-07 16:43:44 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " Trying to create alias %s \n " , name ) ) ;
2005-12-03 21:34:13 +03:00
2006-02-04 01:19:41 +03:00
mem_ctx = talloc_new ( NULL ) ;
2005-12-03 21:34:13 +03:00
if ( mem_ctx = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
exists = lookup_name ( mem_ctx , name , LOOKUP_NAME_ISOLATED ,
NULL , NULL , & sid , & type ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( mem_ctx ) ;
2005-12-03 21:34:13 +03:00
if ( exists ) {
2004-04-07 16:43:44 +04:00
return NT_STATUS_ALIAS_EXISTS ;
2005-12-03 21:34:13 +03:00
}
2004-04-07 16:43:44 +04:00
2006-02-04 01:19:41 +03:00
if ( ! winbind_allocate_gid ( & gid ) ) {
DEBUG ( 3 , ( " Could not get a gid out of winbind \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
if ( ! pdb_new_rid ( & new_rid ) ) {
DEBUG ( 0 , ( " Could not allocate a RID -- wasted a gid :-( \n " ) ) ;
2004-04-07 16:43:44 +04:00
return NT_STATUS_ACCESS_DENIED ;
2006-02-04 01:19:41 +03:00
}
DEBUG ( 10 , ( " Creating alias %s with gid %d and rid %d \n " ,
name , gid , new_rid ) ) ;
2004-04-07 16:43:44 +04:00
sid_copy ( & sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & sid , new_rid ) ;
map . gid = gid ;
sid_copy ( & map . sid , & sid ) ;
map . sid_name_use = SID_NAME_ALIAS ;
fstrcpy ( map . nt_name , name ) ;
fstrcpy ( map . comment , " " ) ;
2006-02-04 01:19:41 +03:00
status = pdb_add_group_mapping_entry ( & map ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Could not add group mapping entry for alias %s "
" (%s) \n " , name , nt_errstr ( status ) ) ) ;
return status ;
2004-04-07 16:43:44 +04:00
}
* rid = new_rid ;
return NT_STATUS_OK ;
}
NTSTATUS pdb_default_delete_alias ( struct pdb_methods * methods ,
const DOM_SID * sid )
{
2006-02-13 20:08:25 +03:00
return pdb_delete_group_mapping_entry ( * sid ) ;
2004-04-07 16:43:44 +04:00
}
NTSTATUS pdb_default_get_aliasinfo ( struct pdb_methods * methods ,
const DOM_SID * sid ,
struct acct_info * info )
{
GROUP_MAP map ;
2006-08-08 23:29:34 +04:00
if ( ! NT_STATUS_IS_OK ( pdb_getgrsid ( & map , sid ) ) )
2004-04-07 16:43:44 +04:00
return NT_STATUS_NO_SUCH_ALIAS ;
2006-02-04 01:19:41 +03:00
if ( ( map . sid_name_use ! = SID_NAME_ALIAS ) & &
( map . sid_name_use ! = SID_NAME_WKN_GRP ) ) {
DEBUG ( 2 , ( " %s is a %s, expected an alias \n " ,
sid_string_static ( sid ) ,
sid_type_lookup ( map . sid_name_use ) ) ) ;
return NT_STATUS_NO_SUCH_ALIAS ;
}
2004-04-07 16:43:44 +04:00
fstrcpy ( info - > acct_name , map . nt_name ) ;
fstrcpy ( info - > acct_desc , map . comment ) ;
sid_peek_rid ( & map . sid , & info - > rid ) ;
return NT_STATUS_OK ;
}
NTSTATUS pdb_default_set_aliasinfo ( struct pdb_methods * methods ,
const DOM_SID * sid ,
struct acct_info * info )
{
GROUP_MAP map ;
2006-08-08 23:29:34 +04:00
if ( ! NT_STATUS_IS_OK ( pdb_getgrsid ( & map , sid ) ) )
2004-04-07 16:43:44 +04:00
return NT_STATUS_NO_SUCH_ALIAS ;
2006-03-22 11:04:13 +03:00
fstrcpy ( map . nt_name , info - > acct_name ) ;
2004-04-07 16:43:44 +04:00
fstrcpy ( map . comment , info - > acct_desc ) ;
2006-02-04 01:19:41 +03:00
return pdb_update_group_mapping_entry ( & map ) ;
2004-04-07 16:43:44 +04:00
}
NTSTATUS pdb_default_add_aliasmem ( struct pdb_methods * methods ,
const DOM_SID * alias , const DOM_SID * member )
{
return add_aliasmem ( alias , member ) ;
}
NTSTATUS pdb_default_del_aliasmem ( struct pdb_methods * methods ,
const DOM_SID * alias , const DOM_SID * member )
{
return del_aliasmem ( alias , member ) ;
}
NTSTATUS pdb_default_enum_aliasmem ( struct pdb_methods * methods ,
2005-10-18 07:24:00 +04:00
const DOM_SID * alias , DOM_SID * * pp_members ,
size_t * p_num_members )
2004-04-07 16:43:44 +04:00
{
2005-10-18 07:24:00 +04:00
return enum_aliasmem ( alias , pp_members , p_num_members ) ;
2004-04-07 16:43:44 +04:00
}
NTSTATUS pdb_default_alias_memberships ( struct pdb_methods * methods ,
2005-03-27 20:33:04 +04:00
TALLOC_CTX * mem_ctx ,
const DOM_SID * domain_sid ,
2005-03-28 07:27:44 +04:00
const DOM_SID * members ,
2005-10-18 07:24:00 +04:00
size_t num_members ,
uint32 * * pp_alias_rids ,
size_t * p_num_alias_rids )
2004-04-07 16:43:44 +04:00
{
2005-03-27 20:33:04 +04:00
DOM_SID * alias_sids ;
2005-10-18 07:24:00 +04:00
size_t i , num_alias_sids ;
2005-03-27 20:33:04 +04:00
NTSTATUS result ;
alias_sids = NULL ;
num_alias_sids = 0 ;
result = alias_memberships ( members , num_members ,
& alias_sids , & num_alias_sids ) ;
if ( ! NT_STATUS_IS_OK ( result ) )
return result ;
2005-10-18 07:24:00 +04:00
* pp_alias_rids = TALLOC_ARRAY ( mem_ctx , uint32 , num_alias_sids ) ;
if ( * pp_alias_rids = = NULL )
2005-03-27 20:33:04 +04:00
return NT_STATUS_NO_MEMORY ;
2005-10-18 07:24:00 +04:00
* p_num_alias_rids = 0 ;
2005-03-27 20:33:04 +04:00
for ( i = 0 ; i < num_alias_sids ; i + + ) {
if ( ! sid_peek_check_rid ( domain_sid , & alias_sids [ i ] ,
2005-10-18 07:24:00 +04:00
& ( * pp_alias_rids ) [ * p_num_alias_rids ] ) )
2005-03-27 20:33:04 +04:00
continue ;
2005-10-18 07:24:00 +04:00
* p_num_alias_rids + = 1 ;
2005-03-27 20:33:04 +04:00
}
SAFE_FREE ( alias_sids ) ;
return NT_STATUS_OK ;
2004-04-07 16:43:44 +04:00
}
2006-03-15 03:10:38 +03:00
/********************************************************************
Really just intended to be called by smbd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS pdb_create_builtin_alias ( uint32 rid )
{
DOM_SID sid ;
enum SID_NAME_USE type ;
gid_t gid ;
GROUP_MAP map ;
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
const char * name = NULL ;
fstring groupname ;
DEBUG ( 10 , ( " Trying to create builtin alias %d \n " , rid ) ) ;
if ( ! sid_compose ( & sid , & global_sid_Builtin , rid ) ) {
return NT_STATUS_NO_SUCH_ALIAS ;
}
if ( ( mem_ctx = talloc_new ( NULL ) ) = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! lookup_sid ( mem_ctx , & sid , NULL , & name , & type ) ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_SUCH_ALIAS ;
}
/* validate RID so copy the name and move on */
fstrcpy ( groupname , name ) ;
TALLOC_FREE ( mem_ctx ) ;
if ( ! winbind_allocate_gid ( & gid ) ) {
DEBUG ( 3 , ( " pdb_create_builtin_alias: Could not get a gid out of winbind \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
DEBUG ( 10 , ( " Creating alias %s with gid %d \n " , name , gid ) ) ;
map . gid = gid ;
sid_copy ( & map . sid , & sid ) ;
map . sid_name_use = SID_NAME_ALIAS ;
fstrcpy ( map . nt_name , name ) ;
fstrcpy ( map . comment , " " ) ;
status = pdb_add_group_mapping_entry ( & map ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " pdb_create_builtin_alias: Could not add group mapping entry for alias %d "
" (%s) \n " , rid , nt_errstr ( status ) ) ) ;
}
return status ;
}
2005-09-30 21:13:37 +04:00