2006-12-12 17:52:13 +03:00
/*
Unix SMB / CIFS implementation .
ID Mapping
Copyright ( C ) Simo Sorce 2003
Copyright ( C ) Jeremy Allison 2006
2011-01-03 00:05:36 +03:00
Copyright ( C ) Michael Adam 2010
2006-12-12 17:52:13 +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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-12-12 17:52:13 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.*/
2006-12-12 17:52:13 +03:00
# include "includes.h"
2009-03-09 23:50:50 +03:00
# include "winbindd.h"
# include "winbindd_proto.h"
2010-08-18 20:13:42 +04:00
# include "idmap.h"
# include "idmap_cache.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2013-02-21 23:31:19 +04:00
# include "secrets.h"
2006-12-12 17:52:13 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
/*****************************************************************
Returns the SID mapped to the given UID .
If mapping is not possible returns an error .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-21 05:25:01 +04:00
NTSTATUS idmap_uid_to_sid ( const char * domname , struct dom_sid * sid , uid_t uid )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
struct id_map map ;
2008-07-13 14:07:40 +04:00
bool expired ;
2006-12-12 17:52:13 +03:00
2008-11-28 12:05:19 +03:00
DEBUG ( 10 , ( " idmap_uid_to_sid: uid = [%lu], domain = '%s' \n " ,
( unsigned long ) uid , domname ? domname : " NULL " ) ) ;
2006-12-12 17:52:13 +03:00
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( )
& & idmap_cache_find_uid2sid ( uid , sid , & expired ) ) {
2009-05-12 08:56:57 +04:00
DEBUG ( 10 , ( " idmap_cache_find_uid2sid found %u%s \n " ,
( unsigned int ) uid ,
2008-07-13 14:07:40 +04:00
expired ? " (expired) " : " " ) ) ;
if ( expired & & idmap_is_online ( ) ) {
DEBUG ( 10 , ( " revalidating expired entry \n " ) ) ;
goto backend ;
}
if ( is_null_sid ( sid ) ) {
DEBUG ( 10 , ( " Returning negative cache entry \n " ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
DEBUG ( 10 , ( " Returning positive cache entry \n " ) ) ;
return NT_STATUS_OK ;
}
backend :
2011-11-09 23:48:23 +04:00
ZERO_STRUCT ( map ) ;
2006-12-12 17:52:13 +03:00
map . sid = sid ;
map . xid . type = ID_TYPE_UID ;
map . xid . id = uid ;
2008-07-13 14:07:40 +04:00
ret = idmap_backends_unixid_to_sid ( domname , & map ) ;
2006-12-12 17:52:13 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2013-05-03 14:24:17 +04:00
DEBUG ( 10 , ( " error mapping uid [%lu]: %s \n " , ( unsigned long ) uid ,
nt_errstr ( ret ) ) ) ;
2013-05-03 14:28:59 +04:00
map . status = ID_UNMAPPED ;
2006-12-12 17:52:13 +03:00
}
2007-01-14 20:58:24 +03:00
if ( map . status ! = ID_MAPPED ) {
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( ) ) {
struct dom_sid null_sid ;
2012-03-23 14:11:33 +04:00
struct unixid id ;
id . type = ID_TYPE_UID ;
id . id = uid ;
2009-03-09 23:50:50 +03:00
ZERO_STRUCT ( null_sid ) ;
2012-03-23 14:11:33 +04:00
idmap_cache_set_sid2unixid ( & null_sid , & id ) ;
2009-03-09 23:50:50 +03:00
}
2006-12-12 17:52:13 +03:00
DEBUG ( 10 , ( " uid [%lu] not mapped \n " , ( unsigned long ) uid ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( ) ) {
2012-03-23 14:11:33 +04:00
idmap_cache_set_sid2unixid ( sid , & map . xid ) ;
2009-03-09 23:50:50 +03:00
}
2008-07-13 14:07:40 +04:00
2006-12-12 17:52:13 +03:00
return NT_STATUS_OK ;
}
/*****************************************************************
Returns SID mapped to the given GID .
If mapping is not possible returns an error .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-21 05:25:01 +04:00
NTSTATUS idmap_gid_to_sid ( const char * domname , struct dom_sid * sid , gid_t gid )
2006-12-12 17:52:13 +03:00
{
NTSTATUS ret ;
struct id_map map ;
2008-07-13 14:07:40 +04:00
bool expired ;
2006-12-12 17:52:13 +03:00
2009-05-16 18:05:37 +04:00
DEBUG ( 10 , ( " idmap_gid_to_sid: gid = [%lu], domain = '%s' \n " ,
2008-11-28 12:05:19 +03:00
( unsigned long ) gid , domname ? domname : " NULL " ) ) ;
2006-12-12 17:52:13 +03:00
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( )
& & idmap_cache_find_gid2sid ( gid , sid , & expired ) ) {
2009-05-12 08:56:57 +04:00
DEBUG ( 10 , ( " idmap_cache_find_gid2sid found %u%s \n " ,
( unsigned int ) gid ,
2008-07-13 14:07:40 +04:00
expired ? " (expired) " : " " ) ) ;
if ( expired & & idmap_is_online ( ) ) {
DEBUG ( 10 , ( " revalidating expired entry \n " ) ) ;
goto backend ;
}
if ( is_null_sid ( sid ) ) {
DEBUG ( 10 , ( " Returning negative cache entry \n " ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
DEBUG ( 10 , ( " Returning positive cache entry \n " ) ) ;
return NT_STATUS_OK ;
}
backend :
2011-11-09 23:48:23 +04:00
ZERO_STRUCT ( map ) ;
2006-12-12 17:52:13 +03:00
map . sid = sid ;
map . xid . type = ID_TYPE_GID ;
map . xid . id = gid ;
2008-07-13 14:07:40 +04:00
ret = idmap_backends_unixid_to_sid ( domname , & map ) ;
2006-12-12 17:52:13 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2013-05-03 14:24:17 +04:00
DEBUG ( 10 , ( " error mapping gid [%lu]: %s \n " , ( unsigned long ) gid ,
nt_errstr ( ret ) ) ) ;
2013-05-03 14:28:59 +04:00
map . status = ID_UNMAPPED ;
2006-12-12 17:52:13 +03:00
}
2007-01-14 20:58:24 +03:00
if ( map . status ! = ID_MAPPED ) {
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( ) ) {
struct dom_sid null_sid ;
2012-03-23 14:11:33 +04:00
struct unixid id ;
id . type = ID_TYPE_GID ;
id . id = gid ;
2009-03-09 23:50:50 +03:00
ZERO_STRUCT ( null_sid ) ;
2012-03-23 14:11:33 +04:00
idmap_cache_set_sid2unixid ( & null_sid , & id ) ;
2009-03-09 23:50:50 +03:00
}
2006-12-12 17:52:13 +03:00
DEBUG ( 10 , ( " gid [%lu] not mapped \n " , ( unsigned long ) gid ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
2009-03-09 23:50:50 +03:00
if ( winbindd_use_idmap_cache ( ) ) {
2012-03-23 14:11:33 +04:00
idmap_cache_set_sid2unixid ( sid , & map . xid ) ;
2009-03-09 23:50:50 +03:00
}
2008-07-13 14:07:40 +04:00
2006-12-12 17:52:13 +03:00
return NT_STATUS_OK ;
}
2010-06-16 18:59:26 +04:00
/**
* check whether a given unix id is inside the filter range of an idmap domain
*/
bool idmap_unix_id_is_in_range ( uint32_t id , struct idmap_domain * dom )
{
if ( id = = 0 ) {
/* 0 is not an allowed unix id for id mapping */
return false ;
}
if ( ( dom - > low_id & & ( id < dom - > low_id ) ) | |
( dom - > high_id & & ( id > dom - > high_id ) ) )
{
return false ;
}
return true ;
}
2013-02-21 23:30:48 +04:00
/**
* Helper for unixids_to_sids : find entry by id in mapping array ,
* search up to IDMAP_AD_MAX_IDS entries
*/
struct id_map * idmap_find_map_by_id ( struct id_map * * maps , enum id_type type ,
uint32_t id )
{
int i ;
for ( i = 0 ; i < IDMAP_LDAP_MAX_IDS ; i + + ) {
if ( maps [ i ] = = NULL ) { /* end of the run */
return NULL ;
}
if ( ( maps [ i ] - > xid . type = = type ) & & ( maps [ i ] - > xid . id = = id ) ) {
return maps [ i ] ;
}
}
return NULL ;
}
/**
* Helper for sids_to_unix_ids : find entry by SID in mapping array ,
* search up to IDMAP_AD_MAX_IDS entries
*/
struct id_map * idmap_find_map_by_sid ( struct id_map * * maps , struct dom_sid * sid )
{
int i ;
for ( i = 0 ; i < IDMAP_LDAP_MAX_IDS ; i + + ) {
if ( maps [ i ] = = NULL ) { /* end of the run */
return NULL ;
}
if ( dom_sid_equal ( maps [ i ] - > sid , sid ) ) {
return maps [ i ] ;
}
}
return NULL ;
}
2013-02-21 23:31:19 +04:00
char * idmap_fetch_secret ( const char * backend , const char * domain ,
const char * identity )
{
char * tmp , * ret ;
int r ;
r = asprintf ( & tmp , " IDMAP_%s_%s " , backend , domain ) ;
if ( r < 0 )
return NULL ;
/* make sure the key is case insensitive */
if ( ! strupper_m ( tmp ) ) {
SAFE_FREE ( tmp ) ;
return NULL ;
}
ret = secrets_fetch_generic ( tmp , identity ) ;
SAFE_FREE ( tmp ) ;
return ret ;
}