2010-07-07 14:35:36 +04:00
/*
* idmap_autorid : static map between Active Directory / NT RIDs
* and RFC 2307 accounts
*
* based on the idmap_rid module , but this module defines the ranges
* for the domains by automatically allocating a range for each domain
*
2012-01-25 22:06:16 +04:00
* Copyright ( C ) Christian Ambach , 2010 - 2012
2010-07-07 14:35:36 +04: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 3 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 , see < http : //www.gnu.org/licenses/>.
*
*/
2013-04-26 02:52:49 +04:00
/*
* This module allocates ranges for domains to be used in a
* algorithmic mode like idmap_rid . Multiple ranges are supported
* for a single domain : If a rid exceeds the range size , a matching
* range is allocated to hold the rid ' s id .
*
* Here are the formulas applied :
*
*
* For a sid of the form domain_sid - rid , we have
*
* rid = reduced_rid + domain_range_index * range_size
*
* with
* reduced_rid : = rid % range_size
* domain_range_index : = rid / range_size
*
* And reduced_rid fits into a range .
*
* In the database , we associate a range_number to
* the pair domain_sid , domain_range_index .
*
* Now the unix id for the given sid calculates as :
*
* id = reduced_rid + range_low_id
*
* with
*
* range_low_id = low_id + range_number * range_size
*
*
* The inverse calculation goes like this :
*
* Given a unix id , let
*
* normalized_id : = id - low_id
* reduced_rid : = normalized_id % range_size
* range_number = normalized_id / range_size
*
* Then we have
*
* id = reduced_rid + low_id + range_number * range_size
*
* From the database , get the domain_sid , domain_range_index pair
* belonging to the range_number ( if there is already one ) .
*
* Then the rid for the unix id calculates as :
*
* rid = reduced_rid + domain_range_index * range_size
*/
2013-08-28 11:49:27 +04:00
# include "idmap_autorid_tdb.h"
2010-07-07 14:35:36 +04:00
# include "winbindd.h"
# include "idmap.h"
2012-01-25 22:06:16 +04:00
# include "idmap_rw.h"
2010-07-07 14:35:36 +04:00
# include "../libcli/security/dom_sid.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
/* handle to the tdb storing domain <-> range assignments */
static struct db_context * autorid_db ;
2013-08-28 17:07:44 +04:00
static bool ignore_builtin = false ;
2014-03-17 15:49:59 +04:00
static NTSTATUS idmap_autorid_get_alloc_range ( struct idmap_domain * dom ,
struct autorid_range_config * range )
{
NTSTATUS status ;
ZERO_STRUCT ( * range ) ;
fstrcpy ( range - > domsid , ALLOC_RANGE ) ;
status = idmap_autorid_get_domainrange ( autorid_db ,
range ,
dom - > read_only ) ;
return status ;
}
2012-01-25 22:06:16 +04:00
static NTSTATUS idmap_autorid_allocate_id ( struct idmap_domain * dom ,
struct unixid * xid ) {
NTSTATUS ret ;
2013-04-25 21:04:56 +04:00
struct autorid_range_config range ;
2012-01-25 22:06:16 +04:00
2012-05-07 16:19:26 +04:00
if ( dom - > read_only ) {
DEBUG ( 3 , ( " Backend is read-only, refusing "
" new allocation request \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2012-01-25 22:06:16 +04:00
/* fetch the range for the allocation pool */
2014-03-17 15:49:59 +04:00
ret = idmap_autorid_get_alloc_range ( dom , & range ) ;
2012-01-25 22:06:16 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 3 , ( " Could not determine range for allocation pool, "
" check previous messages for reason \n " ) ) ;
return ret ;
}
ret = idmap_tdb_common_get_new_id ( dom , xid ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " Fatal error while allocating new ID! \n " ) ) ;
return ret ;
}
2013-04-25 22:12:39 +04:00
xid - > id = xid - > id + range . low_id ;
2012-01-25 22:06:16 +04:00
DEBUG ( 10 , ( " Returned new %s %d from allocation range \n " ,
( xid - > type = = ID_TYPE_UID ) ? " uid " : " gid " , xid - > id ) ) ;
return ret ;
}
/*
* map a SID to xid using the idmap_tdb like pool
*/
2014-04-10 20:20:23 +04:00
static NTSTATUS idmap_autorid_id_to_sid_alloc ( struct idmap_domain * dom ,
struct id_map * map )
2012-01-25 22:06:16 +04:00
{
NTSTATUS ret ;
/* look out for the mapping */
ret = idmap_tdb_common_unixid_to_sid ( dom , map ) ;
if ( NT_STATUS_IS_OK ( ret ) ) {
map - > status = ID_MAPPED ;
return ret ;
}
map - > status = ID_UNKNOWN ;
DEBUG ( 10 , ( " no ID->SID mapping for %d could be found \n " , map - > xid . id ) ) ;
return ret ;
}
2011-03-08 23:47:41 +03:00
static NTSTATUS idmap_autorid_id_to_sid ( struct autorid_global_config * cfg ,
2012-01-25 22:06:16 +04:00
struct idmap_domain * dom ,
2010-07-07 14:35:36 +04:00
struct id_map * map )
{
2013-04-25 22:24:36 +04:00
uint32_t range_number ;
2013-04-25 21:18:27 +04:00
uint32_t domain_range_index = 0 ;
2013-04-25 22:24:36 +04:00
uint32_t normalized_id ;
uint32_t reduced_rid ;
uint32_t rid ;
2013-02-12 01:52:55 +04:00
TDB_DATA data = tdb_null ;
2010-07-07 14:35:36 +04:00
char * keystr ;
2013-04-25 21:13:45 +04:00
struct dom_sid domsid ;
2011-08-24 15:08:13 +04:00
NTSTATUS status ;
2012-12-14 19:54:55 +04:00
bool ok ;
2013-04-10 14:56:07 +04:00
const char * q = NULL ;
2010-07-07 14:35:36 +04:00
/* can this be one of our ids? */
if ( map - > xid . id < cfg - > minvalue ) {
DEBUG ( 10 , ( " id %d is lower than minimum value, "
" ignoring mapping request \n " , map - > xid . id ) ) ;
map - > status = ID_UNKNOWN ;
return NT_STATUS_OK ;
}
if ( map - > xid . id > ( cfg - > minvalue + cfg - > rangesize * cfg - > maxranges ) ) {
DEBUG ( 10 , ( " id %d is outside of maximum id value, "
" ignoring mapping request \n " , map - > xid . id ) ) ;
map - > status = ID_UNKNOWN ;
return NT_STATUS_OK ;
}
/* determine the range of this uid */
2013-04-25 22:24:36 +04:00
normalized_id = map - > xid . id - cfg - > minvalue ;
range_number = normalized_id / cfg - > rangesize ;
keystr = talloc_asprintf ( talloc_tos ( ) , " %u " , range_number ) ;
2010-07-07 14:35:36 +04:00
if ( ! keystr ) {
return NT_STATUS_NO_MEMORY ;
}
2011-08-24 15:08:13 +04:00
status = dbwrap_fetch_bystring ( autorid_db , talloc_tos ( ) , keystr , & data ) ;
2011-03-08 23:47:41 +03:00
TALLOC_FREE ( keystr ) ;
2010-07-07 14:35:36 +04:00
2011-08-24 15:08:13 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-07-07 14:35:36 +04:00
DEBUG ( 4 , ( " id %d belongs to range %d which does not have "
" domain mapping, ignoring mapping request \n " ,
2013-04-25 22:24:36 +04:00
map - > xid . id , range_number ) ) ;
2011-10-20 20:44:48 +04:00
TALLOC_FREE ( data . dptr ) ;
map - > status = ID_UNKNOWN ;
return NT_STATUS_OK ;
}
if ( strncmp ( ( const char * ) data . dptr ,
ALLOC_RANGE ,
strlen ( ALLOC_RANGE ) ) = = 0 ) {
2012-01-25 22:06:16 +04:00
/*
* this is from the alloc range , check if there is a mapping
*/
DEBUG ( 5 , ( " id %d belongs to allocation range, "
" checking for mapping \n " ,
2011-10-20 20:44:48 +04:00
map - > xid . id ) ) ;
TALLOC_FREE ( data . dptr ) ;
2014-04-10 20:20:23 +04:00
return idmap_autorid_id_to_sid_alloc ( dom , map ) ;
2011-03-08 23:45:02 +03:00
}
2010-07-07 14:35:36 +04:00
2013-04-25 21:13:45 +04:00
ok = dom_sid_parse_endp ( ( const char * ) data . dptr , & domsid , & q ) ;
2011-03-08 23:47:41 +03:00
TALLOC_FREE ( data . dptr ) ;
2012-12-14 19:54:55 +04:00
if ( ! ok ) {
map - > status = ID_UNKNOWN ;
return NT_STATUS_OK ;
}
2013-10-25 09:06:01 +04:00
if ( ( q ! = NULL ) & & ( * q ! = ' \0 ' ) )
2013-04-25 21:18:27 +04:00
if ( sscanf ( q + 1 , " % " SCNu32 , & domain_range_index ) ! = 1 ) {
DEBUG ( 10 , ( " Domain range index not found, "
2013-04-10 14:56:07 +04:00
" ignoring mapping request \n " ) ) ;
map - > status = ID_UNKNOWN ;
return NT_STATUS_OK ;
}
2010-07-07 14:35:36 +04:00
2013-04-25 22:24:36 +04:00
reduced_rid = normalized_id % cfg - > rangesize ;
rid = reduced_rid + domain_range_index * cfg - > rangesize ;
sid_compose ( map - > sid , & domsid , rid ) ;
2010-07-07 14:35:36 +04:00
2011-03-08 23:45:02 +03:00
/* We **really** should have some way of validating
the SID exists and is the correct type here . But
that is a deficiency in the idmap_rid design . */
map - > status = ID_MAPPED ;
2012-10-15 18:34:02 +04:00
map - > xid . type = ID_TYPE_BOTH ;
2010-07-07 14:35:36 +04:00
return NT_STATUS_OK ;
}
/**********************************
Single sid to id lookup function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-03-08 23:36:54 +03:00
static NTSTATUS idmap_autorid_sid_to_id ( struct autorid_global_config * global ,
2013-04-25 21:04:56 +04:00
struct autorid_range_config * range ,
2010-07-07 14:35:36 +04:00
struct id_map * map )
{
uint32_t rid ;
2013-04-25 21:47:00 +04:00
uint32_t reduced_rid ;
2010-07-07 14:35:36 +04:00
sid_peek_rid ( map - > sid , & rid ) ;
2013-04-25 21:47:00 +04:00
reduced_rid = rid % global - > rangesize ;
2013-04-25 22:12:39 +04:00
map - > xid . id = reduced_rid + range - > low_id ;
2012-10-15 18:34:02 +04:00
map - > xid . type = ID_TYPE_BOTH ;
2010-07-07 14:35:36 +04:00
map - > status = ID_MAPPED ;
return NT_STATUS_OK ;
}
/**********************************
lookup a set of unix ids .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_autorid_unixids_to_sids ( struct idmap_domain * dom ,
struct id_map * * ids )
{
2012-01-25 22:06:16 +04:00
struct idmap_tdb_common_context * commoncfg ;
2010-07-07 14:35:36 +04:00
struct autorid_global_config * globalcfg ;
NTSTATUS ret ;
int i ;
2012-01-25 22:06:16 +04:00
int num_tomap = 0 ;
int num_mapped = 0 ;
2010-07-07 14:35:36 +04:00
/* initialize the status to avoid surprise */
for ( i = 0 ; ids [ i ] ; i + + ) {
ids [ i ] - > status = ID_UNKNOWN ;
2012-01-25 22:06:16 +04:00
num_tomap + + ;
2010-07-07 14:35:36 +04:00
}
2012-01-25 22:06:16 +04:00
commoncfg =
talloc_get_type_abort ( dom - > private_data ,
struct idmap_tdb_common_context ) ;
globalcfg = talloc_get_type ( commoncfg - > private_data ,
2010-07-07 14:35:36 +04:00
struct autorid_global_config ) ;
for ( i = 0 ; ids [ i ] ; i + + ) {
2012-01-25 22:06:16 +04:00
ret = idmap_autorid_id_to_sid ( globalcfg , dom , ids [ i ] ) ;
2010-07-07 14:35:36 +04:00
if ( ( ! NT_STATUS_IS_OK ( ret ) ) & &
( ! NT_STATUS_EQUAL ( ret , NT_STATUS_NONE_MAPPED ) ) ) {
/* some fatal error occurred, log it */
DEBUG ( 3 , ( " Unexpected error resolving an ID "
" (%d) \n " , ids [ i ] - > xid . id ) ) ;
goto failure ;
}
2012-01-25 22:06:16 +04:00
if ( NT_STATUS_IS_OK ( ret ) & & ids [ i ] - > status = = ID_MAPPED ) {
num_mapped + + ;
}
2010-07-07 14:35:36 +04:00
}
2012-01-25 22:06:16 +04:00
if ( num_tomap = = num_mapped ) {
return NT_STATUS_OK ;
} else if ( num_mapped = = 0 ) {
return NT_STATUS_NONE_MAPPED ;
}
return STATUS_SOME_UNMAPPED ;
2010-07-07 14:35:36 +04:00
failure :
return ret ;
}
2012-01-25 22:06:16 +04:00
/*
* map a SID to xid using the idmap_tdb like pool
*/
2014-04-10 20:33:20 +04:00
static NTSTATUS idmap_autorid_sid_to_id_alloc ( struct idmap_domain * dom ,
struct id_map * map ,
struct idmap_tdb_common_context * ctx )
2012-01-25 22:06:16 +04:00
{
NTSTATUS ret ;
int res ;
/* see if we already have a mapping */
ret = idmap_tdb_common_sid_to_unixid ( dom , map ) ;
if ( NT_STATUS_IS_OK ( ret ) ) {
map - > status = ID_MAPPED ;
return ret ;
}
/* bad things happened */
if ( ! NT_STATUS_EQUAL ( ret , NT_STATUS_NONE_MAPPED ) ) {
2014-03-17 15:49:19 +04:00
DEBUG ( 1 , ( " Looking up SID->ID mapping for %s failed: %s \n " ,
sid_string_dbg ( map - > sid ) , nt_errstr ( ret ) ) ) ;
2012-01-25 22:06:16 +04:00
return ret ;
}
2012-05-07 16:19:26 +04:00
if ( dom - > read_only ) {
DEBUG ( 3 , ( " Not allocating new mapping for %s, because backend "
" is read-only \n " , sid_string_dbg ( map - > sid ) ) ) ;
return NT_STATUS_NONE_MAPPED ;
}
2012-01-25 22:06:16 +04:00
DEBUG ( 10 , ( " Creating new mapping in pool for %s \n " ,
sid_string_dbg ( map - > sid ) ) ) ;
/* create new mapping */
2012-05-08 19:16:49 +04:00
res = dbwrap_transaction_start ( ctx - > db ) ;
if ( res ! = 0 ) {
DEBUG ( 2 , ( " transaction_start failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2012-01-25 22:06:16 +04:00
ret = idmap_tdb_common_new_mapping ( dom , map ) ;
map - > status = ( NT_STATUS_IS_OK ( ret ) ) ? ID_MAPPED : ID_UNMAPPED ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
if ( dbwrap_transaction_cancel ( ctx - > db ) ! = 0 ) {
smb_panic ( " Cancelling transaction failed " ) ;
}
return ret ;
}
res = dbwrap_transaction_commit ( ctx - > db ) ;
if ( res = = 0 ) {
return ret ;
}
DEBUG ( 2 , ( " transaction_commit failed \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2010-07-07 14:35:36 +04:00
/**********************************
lookup a set of sids .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS idmap_autorid_sids_to_unixids ( struct idmap_domain * dom ,
struct id_map * * ids )
{
2012-01-25 22:06:16 +04:00
struct idmap_tdb_common_context * commoncfg ;
2010-07-07 14:35:36 +04:00
struct autorid_global_config * global ;
NTSTATUS ret ;
int i ;
2012-01-25 22:06:16 +04:00
int num_tomap = 0 ;
int num_mapped = 0 ;
2010-07-07 14:35:36 +04:00
/* initialize the status to avoid surprise */
for ( i = 0 ; ids [ i ] ; i + + ) {
ids [ i ] - > status = ID_UNKNOWN ;
2012-01-25 22:06:16 +04:00
num_tomap + + ;
2010-07-07 14:35:36 +04:00
}
2012-01-25 22:06:16 +04:00
commoncfg =
talloc_get_type_abort ( dom - > private_data ,
struct idmap_tdb_common_context ) ;
global = talloc_get_type ( commoncfg - > private_data ,
2010-07-07 14:35:36 +04:00
struct autorid_global_config ) ;
for ( i = 0 ; ids [ i ] ; i + + ) {
2011-03-08 23:33:58 +03:00
struct winbindd_tdc_domain * domain ;
2013-04-25 21:04:56 +04:00
struct autorid_range_config range ;
2011-03-08 23:17:37 +03:00
uint32_t rid ;
2011-10-20 20:22:19 +04:00
struct dom_sid domainsid ;
2011-03-08 23:17:37 +03:00
2013-04-25 21:04:56 +04:00
ZERO_STRUCT ( range ) ;
2011-03-08 23:33:58 +03:00
2012-05-07 21:14:56 +04:00
DEBUG ( 10 , ( " Trying to map %s \n " , sid_string_dbg ( ids [ i ] - > sid ) ) ) ;
2011-10-20 20:22:19 +04:00
sid_copy ( & domainsid , ids [ i ] - > sid ) ;
if ( ! sid_split_rid ( & domainsid , & rid ) ) {
2010-07-07 14:35:36 +04:00
DEBUG ( 4 , ( " Could not determine domain SID from %s, "
" ignoring mapping request \n " ,
sid_string_dbg ( ids [ i ] - > sid ) ) ) ;
continue ;
}
2012-01-25 22:06:16 +04:00
/* is this a well-known SID? */
if ( sid_check_is_wellknown_domain ( & domainsid , NULL ) ) {
DEBUG ( 10 , ( " SID %s is well-known, using pool \n " ,
sid_string_dbg ( ids [ i ] - > sid ) ) ) ;
2014-04-10 20:33:20 +04:00
ret = idmap_autorid_sid_to_id_alloc ( dom , ids [ i ] ,
commoncfg ) ;
2012-01-25 22:06:16 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) & &
! NT_STATUS_EQUAL ( ret , NT_STATUS_NONE_MAPPED ) ) {
DEBUG ( 3 , ( " Unexpected error resolving "
" SID (%s) \n " ,
sid_string_dbg ( ids [ i ] - > sid ) ) ) ;
goto failure ;
}
2012-05-07 16:19:26 +04:00
if ( ids [ i ] - > status = = ID_MAPPED ) {
num_mapped + + ;
}
2012-01-25 22:06:16 +04:00
continue ;
}
2012-05-07 21:14:56 +04:00
/* BUILTIN is passdb's job */
if ( dom_sid_equal ( & domainsid , & global_sid_Builtin ) & &
2013-08-28 17:07:44 +04:00
ignore_builtin ) {
2012-05-07 21:14:56 +04:00
DEBUG ( 10 , ( " Ignoring request for BUILTIN domain \n " ) ) ;
continue ;
}
2011-03-08 23:33:58 +03:00
/*
* Check if the domain is around
*/
domain = wcache_tdc_fetch_domainbysid ( talloc_tos ( ) ,
2011-10-20 20:22:19 +04:00
& domainsid ) ;
2010-07-07 14:35:36 +04:00
if ( domain = = NULL ) {
DEBUG ( 10 , ( " Ignoring unknown domain sid %s \n " ,
2011-10-20 20:22:19 +04:00
sid_string_dbg ( & domainsid ) ) ) ;
2010-07-07 14:35:36 +04:00
continue ;
}
2011-03-08 23:33:58 +03:00
TALLOC_FREE ( domain ) ;
2010-07-07 14:35:36 +04:00
2013-04-25 21:13:45 +04:00
sid_to_fstring ( range . domsid , & domainsid ) ;
2010-07-07 14:35:36 +04:00
2013-04-25 21:18:27 +04:00
/* Calculate domain_range_index for multi-range support */
range . domain_range_index = rid / ( global - > rangesize ) ;
2013-04-10 14:56:07 +04:00
2013-08-28 15:53:22 +04:00
ret = idmap_autorid_get_domainrange ( autorid_db , & range ,
dom - > read_only ) ;
2012-05-07 16:19:26 +04:00
/* read-only mode and a new domain range would be required? */
if ( NT_STATUS_EQUAL ( ret , NT_STATUS_NOT_FOUND ) & &
dom - > read_only ) {
DEBUG ( 10 , ( " read-only is enabled, did not allocate "
" new range for domain %s \n " ,
sid_string_dbg ( & domainsid ) ) ) ;
continue ;
}
2010-07-07 14:35:36 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 3 , ( " Could not determine range for domain, "
" check previous messages for reason \n " ) ) ;
goto failure ;
}
2013-04-25 21:04:56 +04:00
ret = idmap_autorid_sid_to_id ( global , & range , ids [ i ] ) ;
2010-07-07 14:35:36 +04:00
if ( ( ! NT_STATUS_IS_OK ( ret ) ) & &
( ! NT_STATUS_EQUAL ( ret , NT_STATUS_NONE_MAPPED ) ) ) {
/* some fatal error occurred, log it */
DEBUG ( 3 , ( " Unexpected error resolving a SID (%s) \n " ,
sid_string_dbg ( ids [ i ] - > sid ) ) ) ;
goto failure ;
}
2012-01-25 22:06:16 +04:00
if ( NT_STATUS_IS_OK ( ret ) ) {
num_mapped + + ;
}
}
if ( num_tomap = = num_mapped ) {
return NT_STATUS_OK ;
} else if ( num_mapped = = 0 ) {
return NT_STATUS_NONE_MAPPED ;
2010-07-07 14:35:36 +04:00
}
2012-01-25 22:06:16 +04:00
return STATUS_SOME_UNMAPPED ;
2010-07-07 14:35:36 +04:00
failure :
return ret ;
}
2012-05-04 19:56:26 +04:00
static NTSTATUS idmap_autorid_preallocate_wellknown ( struct idmap_domain * dom )
{
const char * groups [ ] = { " S-1-1-0 " , " S-1-2-0 " , " S-1-2-1 " ,
" S-1-3-0 " , " S-1-3-1 " , " S-1-3-2 " , " S-1-3-3 " , " S-1-3-4 " ,
" S-1-5-1 " , " S-1-5-2 " , " S-1-5-3 " , " S-1-5-4 " , " S-1-5-6 " ,
" S-1-5-7 " , " S-1-5-8 " , " S-1-5-9 " , " S-1-5-10 " , " S-1-5-11 " ,
" S-1-5-12 " , " S-1-5-13 " , " S-1-5-14 " , " S-1-5-15 " ,
" S-1-5-17 " , " S-1-5-18 " , " S-1-5-19 " , " S-1-5-20 "
} ;
struct id_map * * maps ;
int i , num ;
NTSTATUS status ;
2012-05-07 16:19:26 +04:00
if ( dom - > read_only ) {
return NT_STATUS_OK ;
}
2013-07-11 15:07:52 +04:00
num = ARRAY_SIZE ( groups ) ;
2012-05-04 19:56:26 +04:00
2013-07-11 15:08:39 +04:00
maps = talloc_array ( talloc_tos ( ) , struct id_map * , num + 1 ) ;
2012-05-04 19:56:26 +04:00
if ( ! maps ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num ; i + + ) {
maps [ i ] = talloc ( maps , struct id_map ) ;
2013-07-11 15:10:25 +04:00
if ( maps [ i ] = = NULL ) {
talloc_free ( maps ) ;
return NT_STATUS_NO_MEMORY ;
}
2012-05-04 19:56:26 +04:00
maps [ i ] - > xid . type = ID_TYPE_GID ;
maps [ i ] - > sid = dom_sid_parse_talloc ( maps , groups [ i ] ) ;
}
maps [ num ] = NULL ;
status = idmap_autorid_sids_to_unixids ( dom , maps ) ;
DEBUG ( 10 , ( " Preallocation run finished with status %s \n " ,
nt_errstr ( status ) ) ) ;
talloc_free ( maps ) ;
return NT_STATUS_IS_OK ( status ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
2014-03-21 03:18:36 +04:00
static NTSTATUS idmap_autorid_initialize_action ( struct db_context * db ,
void * private_data )
{
struct idmap_domain * dom ;
struct idmap_tdb_common_context * common ;
struct autorid_global_config * config ;
NTSTATUS status ;
dom = ( struct idmap_domain * ) private_data ;
common = ( struct idmap_tdb_common_context * ) dom - > private_data ;
config = ( struct autorid_global_config * ) common - > private_data ;
2014-04-03 02:06:04 +04:00
status = idmap_autorid_init_hwms ( db ) ;
2014-03-21 03:18:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2014-04-03 02:06:04 +04:00
status = idmap_autorid_saveconfig ( db , config ) ;
2014-03-21 03:18:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to store configuration data! \n " ) ) ;
return status ;
}
status = idmap_autorid_preallocate_wellknown ( dom ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to preallocate wellknown sids: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
return NT_STATUS_OK ;
}
2011-03-03 01:00:58 +03:00
static NTSTATUS idmap_autorid_initialize ( struct idmap_domain * dom )
2010-07-07 14:35:36 +04:00
{
2012-01-25 22:06:16 +04:00
struct idmap_tdb_common_context * commonconfig ;
2011-02-23 17:25:36 +03:00
struct autorid_global_config * config ;
2010-07-07 14:35:36 +04:00
NTSTATUS status ;
2011-06-07 17:53:49 +04:00
if ( ! strequal ( dom - > name , " * " ) ) {
DEBUG ( 0 , ( " idmap_autorid_initialize: Error: autorid configured "
" for domain '%s'. But autorid can only be used for "
" the default idmap configuration. \n " , dom - > name ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2012-01-25 22:06:16 +04:00
commonconfig = talloc_zero ( dom , struct idmap_tdb_common_context ) ;
if ( ! commonconfig ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2014-03-21 03:02:31 +04:00
dom - > private_data = commonconfig ;
2012-01-25 22:06:16 +04:00
commonconfig - > rw_ops = talloc_zero ( commonconfig , struct idmap_rw_ops ) ;
if ( commonconfig - > rw_ops = = NULL ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
config = talloc_zero ( commonconfig , struct autorid_global_config ) ;
2010-07-07 14:35:36 +04:00
if ( ! config ) {
DEBUG ( 0 , ( " Out of memory! \n " ) ) ;
2011-06-10 02:36:38 +04:00
return NT_STATUS_NO_MEMORY ;
2010-07-07 14:35:36 +04:00
}
2014-03-21 03:03:02 +04:00
commonconfig - > private_data = config ;
2010-07-07 14:35:36 +04:00
config - > minvalue = dom - > low_id ;
2012-01-25 22:06:16 +04:00
config - > rangesize = lp_parm_int ( - 1 , " idmap config * " ,
" rangesize " , 100000 ) ;
2010-07-07 14:35:36 +04:00
config - > maxranges = ( dom - > high_id - dom - > low_id + 1 ) /
config - > rangesize ;
if ( config - > maxranges = = 0 ) {
2014-03-20 12:20:04 +04:00
DEBUG ( 1 , ( " Allowed uid range is smaller than rangesize. "
" Increase uid range or decrease rangesize. \n " ) ) ;
2010-07-07 14:35:36 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
/* check if the high-low limit is a multiple of the rangesize */
if ( ( dom - > high_id - dom - > low_id + 1 ) % config - > rangesize ! = 0 ) {
DEBUG ( 5 , ( " High uid-low uid difference of %d "
" is not a multiple of the rangesize %d, "
" limiting ranges to lower boundary number of %d \n " ,
( dom - > high_id - dom - > low_id + 1 ) , config - > rangesize ,
config - > maxranges ) ) ;
}
DEBUG ( 5 , ( " %d domain ranges with a size of %d are available \n " ,
config - > maxranges , config - > rangesize ) ) ;
2013-08-28 17:07:44 +04:00
ignore_builtin = lp_parm_bool ( - 1 , " idmap config * " ,
" ignore builtin " , false ) ;
2012-05-07 21:14:56 +04:00
2012-01-25 22:06:16 +04:00
/* fill the TDB common configuration */
commonconfig - > max_id = config - > rangesize - 1 ;
commonconfig - > hwmkey_uid = ALLOC_HWM_UID ;
commonconfig - > hwmkey_gid = ALLOC_HWM_GID ;
commonconfig - > rw_ops - > get_new_id = idmap_autorid_allocate_id ;
commonconfig - > rw_ops - > set_mapping = idmap_tdb_common_set_mapping ;
2014-03-21 03:07:07 +04:00
status = idmap_autorid_db_open ( state_path ( " autorid.tdb " ) ,
2014-03-21 03:04:15 +04:00
NULL , /* TALLOC_CTX */
& autorid_db ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto error ;
}
commonconfig - > db = autorid_db ;
2014-03-21 03:18:36 +04:00
status = dbwrap_trans_do ( autorid_db ,
idmap_autorid_initialize_action ,
dom ) ;
2014-03-21 03:07:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-03-21 03:18:36 +04:00
DEBUG ( 1 , ( " Failed to init the idmap database: %s \n " ,
nt_errstr ( status ) ) ) ;
2014-03-21 03:07:07 +04:00
goto error ;
}
2011-06-10 02:49:37 +04:00
goto done ;
2010-07-07 14:35:36 +04:00
2011-06-10 02:49:37 +04:00
error :
2011-06-10 02:36:38 +04:00
talloc_free ( config ) ;
2011-06-10 02:49:37 +04:00
done :
2010-07-07 14:35:36 +04:00
return status ;
}
/*
Close the idmap tdb instance
*/
static struct idmap_methods autorid_methods = {
. init = idmap_autorid_initialize ,
. unixids_to_sids = idmap_autorid_unixids_to_sids ,
. sids_to_unixids = idmap_autorid_sids_to_unixids ,
2011-10-20 20:44:48 +04:00
. allocate_id = idmap_autorid_allocate_id
2010-07-07 14:35:36 +04:00
} ;
2014-04-02 02:45:38 +04:00
NTSTATUS idmap_autorid_init ( void )
2010-07-07 14:35:36 +04:00
{
return smb_register_idmap ( SMB_IDMAP_INTERFACE_VERSION ,
" autorid " , & autorid_methods ) ;
}