2003-03-07 23:47:59 +00:00
/*
Unix SMB / CIFS implementation .
2003-04-29 10:54:13 +00:00
ID Mapping
2003-03-07 23:47:59 +00:00
Copyright ( C ) Tim Potter 2000
2003-08-01 14:47:39 +00:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2003
2003-03-07 23:47:59 +00:00
Copyright ( C ) Simo Sorce 2003
2006-07-11 18:01:26 +00:00
Copyright ( C ) Jeremy Allison 2006
2003-03-07 23:47:59 +00: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
2003-04-02 10:36:02 +00:00
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
2003-03-07 23:47:59 +00:00
# include "includes.h"
2003-03-08 00:49:18 +00:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
2006-04-26 15:41:25 +00:00
static_decl_idmap ;
2003-05-29 19:08:40 +00:00
struct idmap_function_entry {
2003-03-07 23:47:59 +00:00
const char * name ;
struct idmap_methods * methods ;
2003-05-29 19:08:40 +00:00
struct idmap_function_entry * prev , * next ;
2003-03-07 23:47:59 +00:00
} ;
2003-05-29 19:08:40 +00:00
static struct idmap_function_entry * backends = NULL ;
2003-06-27 20:55:48 +00:00
static struct idmap_methods * cache_map ;
2003-04-02 10:36:02 +00:00
static struct idmap_methods * remote_map ;
2003-03-07 23:47:59 +00:00
2004-06-29 15:46:43 +00:00
static BOOL proxyonly = False ;
2003-06-27 20:55:48 +00:00
/**********************************************************************
Get idmap methods . Don ' t allow tdb to be a remote method .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-30 00:44:45 +00:00
2003-06-27 20:55:48 +00:00
static struct idmap_methods * get_methods ( const char * name , BOOL cache_method )
2003-03-07 23:47:59 +00:00
{
2003-05-29 19:08:40 +00:00
struct idmap_function_entry * entry = backends ;
2003-03-07 23:47:59 +00:00
2003-06-27 20:55:48 +00:00
for ( entry = backends ; entry ; entry = entry - > next ) {
if ( ! cache_method & & strequal ( entry - > name , " tdb " ) )
continue ; /* tdb is only cache method. */
if ( strequal ( entry - > name , name ) )
return entry - > methods ;
2003-03-07 23:47:59 +00:00
}
2003-05-29 19:08:40 +00:00
return NULL ;
}
2003-03-07 23:47:59 +00:00
2003-06-27 20:55:48 +00:00
/**********************************************************************
Allow a module to register itself as a method .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-05-29 19:08:40 +00:00
NTSTATUS smb_register_idmap ( int version , const char * name , struct idmap_methods * methods )
{
2003-06-26 18:26:52 +00:00
struct idmap_function_entry * entry ;
2003-05-29 19:08:40 +00:00
if ( ( version ! = SMB_IDMAP_INTERFACE_VERSION ) ) {
2003-06-27 20:55:48 +00:00
DEBUG ( 0 , ( " smb_register_idmap: Failed to register idmap module. \n "
2003-05-29 19:08:40 +00:00
" The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d, \n "
" current SMB_IDMAP_INTERFACE_VERSION is %d. \n "
" Please recompile against the current version of samba! \n " ,
version , SMB_IDMAP_INTERFACE_VERSION ) ) ;
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
}
if ( ! name | | ! name [ 0 ] | | ! methods ) {
2003-06-27 20:55:48 +00:00
DEBUG ( 0 , ( " smb_register_idmap: called with NULL pointer or empty name! \n " ) ) ;
2003-05-29 19:08:40 +00:00
return NT_STATUS_INVALID_PARAMETER ;
}
2003-03-07 23:47:59 +00:00
2003-06-27 20:55:48 +00:00
if ( get_methods ( name , False ) ) {
DEBUG ( 0 , ( " smb_register_idmap: idmap module %s already registered! \n " , name ) ) ;
2003-05-29 19:08:40 +00:00
return NT_STATUS_OBJECT_NAME_COLLISION ;
2003-03-07 23:47:59 +00:00
}
2004-12-07 18:25:53 +00:00
entry = SMB_XMALLOC_P ( struct idmap_function_entry ) ;
2003-05-29 19:08:40 +00:00
entry - > name = smb_xstrdup ( name ) ;
entry - > methods = methods ;
2003-06-26 18:26:52 +00:00
DLIST_ADD ( backends , entry ) ;
2003-06-27 20:55:48 +00:00
DEBUG ( 5 , ( " smb_register_idmap: Successfully added idmap backend '%s' \n " , name ) ) ;
2003-05-29 19:08:40 +00:00
return NT_STATUS_OK ;
2003-03-07 23:47:59 +00:00
}
2003-06-27 20:55:48 +00:00
/**********************************************************************
Initialise idmap cache and a remote backend ( if configured ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-27 12:07:20 +00:00
2004-07-10 17:00:53 +00:00
BOOL idmap_init ( const char * * remote_backend )
2003-06-27 20:55:48 +00:00
{
2003-05-29 19:08:40 +00:00
if ( ! backends )
static_init_idmap ;
2003-06-27 20:55:48 +00:00
if ( ! cache_map ) {
cache_map = get_methods ( " tdb " , True ) ;
2003-05-29 19:08:40 +00:00
2003-06-27 20:55:48 +00:00
if ( ! cache_map ) {
DEBUG ( 0 , ( " idmap_init: could not find tdb cache backend! \n " ) ) ;
2003-05-29 19:08:40 +00:00
return False ;
}
2003-06-27 20:55:48 +00:00
if ( ! NT_STATUS_IS_OK ( cache_map - > init ( NULL ) ) ) {
DEBUG ( 0 , ( " idmap_init: could not initialise tdb cache backend! \n " ) ) ;
2003-04-19 15:29:39 +00:00
return False ;
}
2003-03-08 17:29:40 +00:00
}
2004-07-10 17:00:53 +00:00
if ( ( remote_map = = NULL ) & & ( remote_backend ! = NULL ) & &
( * remote_backend ! = NULL ) & & ( * * remote_backend ! = ' \0 ' ) ) {
char * rem_backend = smb_xstrdup ( * remote_backend ) ;
2003-06-06 13:48:39 +00:00
fstring params = " " ;
char * pparams ;
2006-01-16 17:21:47 +00:00
BOOL idmap_prefix_workaround = False ;
2003-06-06 13:48:39 +00:00
/* get any mode parameters passed in */
2003-06-27 20:55:48 +00:00
if ( ( pparams = strchr ( rem_backend , ' : ' ) ) ! = NULL ) {
2003-06-09 17:28:42 +00:00
* pparams = ' \0 ' ;
2003-06-06 13:48:39 +00:00
pparams + + ;
fstrcpy ( params , pparams ) ;
}
2006-01-14 15:25:33 +00:00
/* strip any leading idmap_ prefix of */
if ( strncmp ( rem_backend , " idmap_ " , 6 ) = = 0 ) {
rem_backend + = 6 ;
2006-01-16 17:21:47 +00:00
idmap_prefix_workaround = True ;
2006-01-14 15:25:33 +00:00
DEBUG ( 0 , ( " idmap_init: idmap backend uses deprecated 'idmap_' prefix. Please replace 'idmap_%s' by '%s' in %s \n " , rem_backend , rem_backend , dyn_CONFIGFILE ) ) ;
}
2003-06-06 13:48:39 +00:00
2003-06-27 20:55:48 +00:00
DEBUG ( 3 , ( " idmap_init: using '%s' as remote backend \n " , rem_backend ) ) ;
2003-03-07 23:47:59 +00:00
2003-06-27 20:55:48 +00:00
if ( ( remote_map = get_methods ( rem_backend , False ) ) | |
( NT_STATUS_IS_OK ( smb_probe_module ( " idmap " , rem_backend ) ) & &
( remote_map = get_methods ( rem_backend , False ) ) ) ) {
2004-10-22 16:19:31 +00:00
if ( ! NT_STATUS_IS_OK ( remote_map - > init ( params ) ) ) {
DEBUG ( 0 , ( " idmap_init: failed to initialize remote backend! \n " ) ) ;
return False ;
}
2003-05-29 19:08:40 +00:00
} else {
2003-06-27 20:55:48 +00:00
DEBUG ( 0 , ( " idmap_init: could not load remote backend '%s' \n " , rem_backend ) ) ;
2006-01-16 17:21:47 +00:00
if ( idmap_prefix_workaround )
rem_backend - = 6 ;
2003-06-27 20:55:48 +00:00
SAFE_FREE ( rem_backend ) ;
2003-03-07 23:47:59 +00:00
return False ;
}
2006-01-16 17:21:47 +00:00
if ( idmap_prefix_workaround )
rem_backend - = 6 ;
2003-06-27 20:55:48 +00:00
SAFE_FREE ( rem_backend ) ;
2003-03-07 23:47:59 +00:00
}
2003-03-08 17:29:40 +00:00
2003-03-07 23:47:59 +00:00
return True ;
}
2004-06-29 15:46:43 +00:00
/**************************************************************************
Don ' t do id mapping . This is used to make winbind a netlogon proxy only .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-08 22:10:34 +00:00
void idmap_set_proxyonly ( void )
2004-06-29 15:46:43 +00:00
{
proxyonly = True ;
}
2005-06-08 22:10:34 +00:00
BOOL idmap_proxyonly ( void )
{
return proxyonly ;
}
2003-06-27 20:55:48 +00:00
/**************************************************************************
This is a rare operation , designed to allow an explicit mapping to be
2003-06-30 22:07:47 +00:00
set up for a sid to a POSIX id .
2003-06-27 20:55:48 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 18:01:26 +00:00
NTSTATUS idmap_set_mapping ( const DOM_SID * sid , unid_t id , enum idmap_type id_type )
2003-03-07 23:47:59 +00:00
{
2003-06-30 22:07:47 +00:00
struct idmap_methods * map = remote_map ;
2003-07-01 10:01:57 +00:00
DOM_SID tmp_sid ;
2006-07-11 18:01:26 +00:00
if ( proxyonly ) {
2004-06-29 15:46:43 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-11 18:01:26 +00:00
}
2004-06-29 15:46:43 +00:00
2006-02-03 22:19:41 +00:00
if ( sid_check_is_in_our_domain ( sid ) ) {
DEBUG ( 3 , ( " Refusing to add SID %s to idmap, it's our own "
" domain \n " , sid_string_static ( sid ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
if ( sid_check_is_in_builtin ( sid ) ) {
DEBUG ( 3 , ( " Refusing to add SID %s to idmap, it's our builtin "
" domain \n " , sid_string_static ( sid ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2003-07-22 04:31:20 +00:00
DEBUG ( 10 , ( " idmap_set_mapping: Set %s to %s %lu \n " ,
2003-07-01 10:01:57 +00:00
sid_string_static ( sid ) ,
2006-07-11 18:01:26 +00:00
( id_type = = ID_USERID ) ? " UID " : " GID " ,
( id_type = = ID_USERID ) ? ( unsigned long ) id . uid :
2003-07-22 04:31:20 +00:00
( unsigned long ) id . gid ) ) ;
2003-07-01 10:01:57 +00:00
2006-07-11 18:01:26 +00:00
if ( ( NT_STATUS_IS_OK ( cache_map - > get_sid_from_id ( & tmp_sid , id , id_type , IDMAP_FLAG_QUERY_ONLY ) ) ) & &
sid_equal ( sid , & tmp_sid ) ) {
2003-07-01 10:01:57 +00:00
/* Nothing to do, we already have that mapping */
DEBUG ( 10 , ( " idmap_set_mapping: Mapping already there \n " ) ) ;
return NT_STATUS_OK ;
}
2003-03-08 17:29:40 +00:00
2003-06-30 22:07:47 +00:00
if ( map = = NULL ) {
/* Ok, we don't have a authoritative remote
mapping . So update our local cache only . */
map = cache_map ;
2003-03-08 17:29:40 +00:00
}
2003-06-30 22:07:47 +00:00
return map - > set_mapping ( sid , id , id_type ) ;
2003-03-08 17:29:40 +00:00
}
2003-06-27 20:55:48 +00:00
/**************************************************************************
Get ID from SID . This can create a mapping for a SID to a POSIX id .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 18:01:26 +00:00
NTSTATUS idmap_get_id_from_sid ( unid_t * id , enum idmap_type * id_type , const DOM_SID * sid , int flags )
2003-03-07 23:47:59 +00:00
{
NTSTATUS ret ;
2006-07-11 18:01:26 +00:00
int cache_flags = flags ;
2003-03-07 23:47:59 +00:00
2006-07-11 18:01:26 +00:00
if ( proxyonly ) {
2004-06-29 15:46:43 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-11 18:01:26 +00:00
}
2004-06-29 15:46:43 +00:00
2006-02-03 22:19:41 +00:00
if ( sid_check_is_in_our_domain ( sid ) ) {
DEBUG ( 9 , ( " sid %s is in our domain -- go look in passdb \n " ,
sid_string_static ( sid ) ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
if ( sid_check_is_in_builtin ( sid ) ) {
DEBUG ( 9 , ( " sid %s is in builtin domain -- go look in passdb \n " ,
sid_string_static ( sid ) ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
2003-06-27 20:55:48 +00:00
if ( remote_map ) {
2003-06-30 22:07:47 +00:00
/* We have a central remote idmap so only look in
2006-07-11 18:01:26 +00:00
cache , ensure we don ' t allocate */
cache_flags | = IDMAP_FLAG_QUERY_ONLY ;
2003-03-08 17:29:40 +00:00
}
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
ret = cache_map - > get_id_from_sid ( id , id_type , sid , cache_flags ) ;
2003-06-30 22:07:47 +00:00
if ( NT_STATUS_IS_OK ( ret ) ) {
return NT_STATUS_OK ;
}
2006-07-11 18:01:26 +00:00
if ( ( remote_map = = NULL ) | | ( flags & IDMAP_FLAG_CACHE_ONLY ) ) {
2003-06-30 22:07:47 +00:00
return ret ;
}
2006-07-11 18:01:26 +00:00
/* Ok, the mapping was not in the cache, give the remote map a try. */
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
ret = remote_map - > get_id_from_sid ( id , id_type , sid , flags ) ;
2003-06-30 22:07:47 +00:00
if ( NT_STATUS_IS_OK ( ret ) ) {
/* The remote backend gave us a valid mapping, cache it. */
ret = cache_map - > set_mapping ( sid , * id , * id_type ) ;
2003-03-07 23:47:59 +00:00
}
return ret ;
}
2003-06-27 20:55:48 +00:00
/**************************************************************************
Get SID from ID . This must have been created before .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 18:01:26 +00:00
NTSTATUS idmap_get_sid_from_id ( DOM_SID * sid , unid_t id , enum idmap_type id_type , int flags )
2003-03-07 23:47:59 +00:00
{
NTSTATUS ret ;
2006-07-11 18:01:26 +00:00
int cache_flags = flags ;
2003-03-07 23:47:59 +00:00
2006-07-11 18:01:26 +00:00
if ( proxyonly ) {
2004-06-29 15:46:43 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-11 18:01:26 +00:00
}
2004-06-29 15:46:43 +00:00
2003-04-02 10:36:02 +00:00
if ( remote_map ) {
2006-07-11 18:01:26 +00:00
/* We have a central remote idmap so only look in
cache , ensure we don ' t allocate */
cache_flags | = IDMAP_FLAG_QUERY_ONLY ;
2003-03-08 17:29:40 +00:00
}
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
ret = cache_map - > get_sid_from_id ( sid , id , id_type , cache_flags ) ;
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
if ( NT_STATUS_IS_OK ( ret ) ) {
2003-06-30 22:07:47 +00:00
return ret ;
2006-07-11 18:01:26 +00:00
}
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
if ( ( remote_map = = NULL ) | | ( flags & IDMAP_FLAG_CACHE_ONLY ) ) {
2003-06-30 22:07:47 +00:00
return ret ;
2006-07-11 18:01:26 +00:00
}
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
/* Not in cache, ask our authoritative backend */
2003-06-30 22:07:47 +00:00
2006-07-11 18:01:26 +00:00
ret = remote_map - > get_sid_from_id ( sid , id , id_type , flags ) ;
2003-06-30 22:07:47 +00:00
if ( NT_STATUS_IS_OK ( ret ) ) {
/* The remote backend gave us a valid mapping, cache it. */
ret = cache_map - > set_mapping ( sid , id , id_type ) ;
2003-03-07 23:47:59 +00:00
}
return ret ;
}
2003-07-09 16:44:47 +00:00
/**************************************************************************
2003-07-11 05:33:40 +00:00
Alloocate a new UNIX uid / gid
2003-07-09 16:44:47 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 18:01:26 +00:00
NTSTATUS idmap_allocate_id ( unid_t * id , enum idmap_type id_type )
2003-07-09 16:44:47 +00:00
{
/* we have to allocate from the authoritative backend */
2006-07-11 18:01:26 +00:00
if ( proxyonly ) {
2004-06-29 15:46:43 +00:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-11 18:01:26 +00:00
}
2004-06-29 15:46:43 +00:00
2006-07-11 18:01:26 +00:00
if ( remote_map ) {
2003-07-09 16:44:47 +00:00
return remote_map - > allocate_id ( id , id_type ) ;
2006-07-11 18:01:26 +00:00
}
2003-07-09 16:44:47 +00:00
return cache_map - > allocate_id ( id , id_type ) ;
}
2003-06-27 20:55:48 +00:00
/**************************************************************************
Shutdown maps .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-07 23:47:59 +00:00
NTSTATUS idmap_close ( void )
{
NTSTATUS ret ;
2006-07-11 18:01:26 +00:00
if ( proxyonly ) {
2004-06-29 15:46:43 +00:00
return NT_STATUS_OK ;
2006-07-11 18:01:26 +00:00
}
2004-06-29 15:46:43 +00:00
2005-07-03 12:05:07 +00:00
ret = cache_map - > close_fn ( ) ;
2003-06-22 10:09:52 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2003-06-27 20:55:48 +00:00
DEBUG ( 3 , ( " idmap_close: failed to close local tdb cache! \n " ) ) ;
2003-03-08 17:29:40 +00:00
}
2003-06-30 22:07:47 +00:00
cache_map = NULL ;
2003-03-08 17:29:40 +00:00
2003-04-02 10:36:02 +00:00
if ( remote_map ) {
2005-07-03 12:05:07 +00:00
ret = remote_map - > close_fn ( ) ;
2003-06-22 10:09:52 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2003-03-08 17:29:40 +00:00
DEBUG ( 3 , ( " idmap_close: failed to close remote idmap repository! \n " ) ) ;
}
2003-06-30 22:07:47 +00:00
remote_map = NULL ;
2003-03-07 23:47:59 +00:00
}
return ret ;
}
2003-06-27 20:55:48 +00:00
/**************************************************************************
Dump backend status .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-07 23:47:59 +00:00
void idmap_status ( void )
{
2003-06-27 20:55:48 +00:00
cache_map - > status ( ) ;
2006-07-11 18:01:26 +00:00
if ( remote_map ) {
2003-06-27 20:55:48 +00:00
remote_map - > status ( ) ;
2006-07-11 18:01:26 +00:00
}
2003-03-07 23:47:59 +00:00
}