2004-05-03 14:58:08 +00:00
/*
Unix SMB / CIFS implementation .
interface functions for the sam database
Copyright ( C ) Andrew Tridgell 2004
2006-07-06 05:23:29 +00:00
Copyright ( C ) Volker Lendecke 2004
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006
2004-05-03 14:58:08 +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
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2004-05-03 14:58:08 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-05-03 14:58:08 +00:00
*/
# include "includes.h"
2004-11-02 02:57:18 +00:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_security.h"
2008-06-14 11:24:17 -04:00
# include "lib/events/events.h"
2010-10-30 11:41:11 +11:00
# include "lib/ldb-samba/ldb_wrap.h"
2011-02-10 14:12:51 +11:00
# include <ldb.h>
# include <ldb_errors.h>
2006-04-02 12:02:01 +00:00
# include "libcli/security/security.h"
2023-09-27 14:51:36 +13:00
# include "libcli/security/claims-conversions.h"
2006-11-07 00:48:36 +00:00
# include "libcli/auth/libcli_auth.h"
2007-12-06 21:39:49 +01:00
# include "libcli/ldap/ldap_ndr.h"
2005-01-12 02:40:25 +00:00
# include "system/time.h"
2005-02-10 05:09:35 +00:00
# include "system/filesys.h"
2007-11-16 20:12:00 +01:00
# include "ldb_wrap.h"
2010-10-17 14:27:18 +02:00
# include "../lib/util/util_ldb.h"
2005-12-28 15:38:36 +00:00
# include "dsdb/samdb/samdb.h"
2009-06-12 14:27:19 +02:00
# include "../libds/common/flags.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2008-04-21 19:53:29 -04:00
# include "lib/events/events.h"
2008-07-15 15:07:13 +10:00
# include "auth/credentials/credentials.h"
# include "param/secrets.h"
2010-04-19 15:51:57 +10:00
# include "auth/auth.h"
2018-04-04 12:39:55 +12:00
# include "lib/tsocket/tsocket.h"
2023-09-14 22:09:50 +12:00
# include "lib/param/loadparm.h"
2004-05-03 14:58:08 +00:00
/*
2011-08-12 15:43:04 +10:00
connect to the SAM database specified by URL
2004-05-06 12:42:42 +00:00
return an opaque context pointer on success , or NULL on failure
2004-05-03 14:58:08 +00:00
*/
2017-09-14 15:02:36 +12:00
int samdb_connect_url ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev_ctx ,
struct loadparm_context * lp_ctx ,
struct auth_session_info * session_info ,
2018-04-04 12:39:55 +12:00
unsigned int flags ,
const char * url ,
2018-04-12 06:41:30 +12:00
const struct tsocket_address * remote_address ,
2017-09-14 15:02:36 +12:00
struct ldb_context * * ldb_ret ,
char * * errstring )
2004-05-03 14:58:08 +00:00
{
2017-09-14 15:02:36 +12:00
struct ldb_context * ldb = NULL ;
2010-10-10 23:25:38 +02:00
int ret ;
2017-09-14 15:02:36 +12:00
* ldb_ret = NULL ;
* errstring = NULL ;
2018-04-04 12:39:55 +12:00
2020-11-23 19:35:37 +13:00
/* We create sam.ldb in provision, and never anywhere else */
flags | = LDB_FLG_DONT_CREATE_DB ;
2018-04-04 12:39:55 +12:00
if ( remote_address = = NULL ) {
ldb = ldb_wrap_find ( url , ev_ctx , lp_ctx ,
session_info , NULL , flags ) ;
if ( ldb ! = NULL ) {
* ldb_ret = talloc_reference ( mem_ctx , ldb ) ;
if ( * ldb_ret = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
return LDB_SUCCESS ;
2017-09-14 15:02:36 +12:00
}
}
2010-10-10 23:25:38 +02:00
2011-11-01 12:11:57 +11:00
ldb = samba_ldb_init ( mem_ctx , ev_ctx , lp_ctx , session_info , NULL ) ;
2010-10-10 23:25:38 +02:00
2017-09-14 15:02:36 +12:00
if ( ldb = = NULL ) {
* errstring = talloc_asprintf ( mem_ctx ,
" Failed to set up Samba ldb "
" wrappers with samba_ldb_init() "
" to connect to %s " ,
url ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2010-10-10 23:25:38 +02:00
dsdb_set_global_schema ( ldb ) ;
ret = samba_ldb_connect ( ldb , lp_ctx , url , flags ) ;
if ( ret ! = LDB_SUCCESS ) {
2017-09-14 15:02:36 +12:00
* errstring = talloc_asprintf ( mem_ctx ,
" Failed to connect to %s: %s " ,
url ,
ldb_errstring ( ldb ) ) ;
2010-10-10 23:25:38 +02:00
talloc_free ( ldb ) ;
2017-09-14 15:02:36 +12:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-10-07 11:31:45 +00:00
}
2010-10-10 16:56:55 +02:00
2018-04-04 12:39:55 +12:00
/*
* If a remote_address was specified , then set it on the DB
* and do not add to the wrap list ( as we need to keep the LDB
* pointer unique for the address ) .
*
* We use this for audit logging and for the " netlogon " attribute
*/
if ( remote_address ! = NULL ) {
ldb_set_opaque ( ldb , " remoteAddress " ,
2018-04-12 06:41:30 +12:00
discard_const ( remote_address ) ) ;
2018-04-04 12:39:55 +12:00
* ldb_ret = ldb ;
return LDB_SUCCESS ;
}
2024-05-30 11:23:01 +12:00
if ( flags & SAMBA_LDB_WRAP_CONNECT_FLAG_NO_SHARE_CONTEXT ) {
* ldb_ret = ldb ;
return LDB_SUCCESS ;
}
2011-11-01 12:11:57 +11:00
if ( ! ldb_wrap_add ( url , ev_ctx , lp_ctx , session_info , NULL , flags , ldb ) ) {
2017-09-14 15:02:36 +12:00
* errstring = talloc_asprintf ( mem_ctx ,
" Failed to add cached DB reference "
" to %s " ,
url ) ;
2010-10-10 23:25:38 +02:00
talloc_free ( ldb ) ;
2017-09-14 15:02:36 +12:00
return LDB_ERR_OPERATIONS_ERROR ;
2010-10-10 23:25:38 +02:00
}
2017-09-14 15:02:36 +12:00
* ldb_ret = ldb ;
return LDB_SUCCESS ;
2004-05-06 12:42:42 +00:00
}
2004-05-06 09:55:05 +00:00
2006-03-19 18:06:36 +00:00
2011-08-12 15:43:04 +10:00
/*
connect to the SAM database
return an opaque context pointer on success , or NULL on failure
*/
struct ldb_context * samdb_connect ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev_ctx ,
struct loadparm_context * lp_ctx ,
struct auth_session_info * session_info ,
2018-04-12 06:41:30 +12:00
const struct tsocket_address * remote_address ,
2011-08-12 15:43:04 +10:00
unsigned int flags )
{
2017-09-14 15:02:36 +12:00
char * errstring ;
struct ldb_context * ldb ;
2018-04-12 06:41:30 +12:00
int ret = samdb_connect_url ( mem_ctx ,
ev_ctx ,
lp_ctx ,
session_info ,
flags ,
" sam.ldb " ,
remote_address ,
& ldb ,
& errstring ) ;
2017-09-14 15:02:36 +12:00
if ( ret = = LDB_SUCCESS ) {
return ldb ;
}
return NULL ;
2011-08-12 15:43:04 +10:00
}
2006-04-27 16:09:17 +00:00
/****************************************************************************
Create the SID list for this user .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS security_token_create ( TALLOC_CTX * mem_ctx ,
2007-12-02 19:04:33 +01:00
struct loadparm_context * lp_ctx ,
2023-08-11 10:34:47 +12:00
uint32_t num_sids ,
2023-08-11 10:35:43 +12:00
const struct auth_SidAttr * sids ,
2023-09-27 14:51:36 +13:00
uint32_t num_device_sids ,
const struct auth_SidAttr * device_sids ,
struct auth_claims auth_claims ,
2010-04-19 15:51:57 +10:00
uint32_t session_info_flags ,
2006-04-27 16:09:17 +00:00
struct security_token * * token )
{
struct security_token * ptoken ;
2023-08-11 10:34:47 +12:00
uint32_t i ;
2006-04-27 16:09:17 +00:00
NTSTATUS status ;
2023-09-14 22:09:50 +12:00
enum claims_evaluation_control evaluate_claims ;
2023-09-27 14:51:36 +13:00
bool sids_are_valid = false ;
bool device_sids_are_valid = false ;
2023-09-27 14:54:06 +13:00
bool authentication_was_compounded = session_info_flags & AUTH_SESSION_INFO_FORCE_COMPOUNDED_AUTHENTICATION ;
2006-04-27 16:09:17 +00:00
2023-09-14 22:09:50 +12:00
/*
* Some special - case callers can ' t supply the lp_ctx , but do
* not interact with claims or conditional ACEs
*/
if ( lp_ctx = = NULL ) {
evaluate_claims = CLAIMS_EVALUATION_INVALID_STATE ;
} else {
enum acl_claims_evaluation claims_evaultion_setting
= lpcfg_acl_claims_evaluation ( lp_ctx ) ;
/*
* We are well inside the AD DC , so we do not need to check
* the server role etc
*/
switch ( claims_evaultion_setting ) {
case ACL_CLAIMS_EVALUATION_AD_DC_ONLY :
evaluate_claims = CLAIMS_EVALUATION_ALWAYS ;
break ;
default :
evaluate_claims = CLAIMS_EVALUATION_NEVER ;
}
}
ptoken = security_token_initialise ( mem_ctx , evaluate_claims ) ;
2006-04-27 16:09:17 +00:00
NT_STATUS_HAVE_NO_MEMORY ( ptoken ) ;
2023-08-11 10:36:04 +12:00
if ( num_sids > UINT32_MAX - 6 ) {
talloc_free ( ptoken ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2011-01-20 23:39:37 +11:00
ptoken - > sids = talloc_array ( ptoken , struct dom_sid , num_sids + 6 /* over-allocate */ ) ;
2023-08-03 11:39:12 +12:00
if ( ptoken - > sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-04-19 15:51:57 +10:00
2011-01-20 23:39:37 +11:00
ptoken - > num_sids = 0 ;
2010-04-19 15:51:57 +10:00
2011-01-20 23:39:37 +11:00
for ( i = 0 ; i < num_sids ; i + + ) {
2023-08-11 10:34:47 +12:00
uint32_t check_sid_idx ;
2011-01-20 23:39:37 +11:00
for ( check_sid_idx = 0 ;
check_sid_idx < ptoken - > num_sids ;
check_sid_idx + + ) {
2022-09-27 15:13:12 +13:00
if ( dom_sid_equal ( & ptoken - > sids [ check_sid_idx ] , & sids [ i ] . sid ) ) {
2011-01-20 23:39:37 +11:00
break ;
}
}
2010-04-19 15:51:57 +10:00
2011-01-20 23:39:37 +11:00
if ( check_sid_idx = = ptoken - > num_sids ) {
2023-09-27 14:51:36 +13:00
const struct dom_sid * sid = & sids [ i ] . sid ;
sids_are_valid = sids_are_valid | | dom_sid_equal (
sid , & global_sid_Claims_Valid ) ;
authentication_was_compounded = authentication_was_compounded | | dom_sid_equal (
sid , & global_sid_Compounded_Authentication ) ;
2011-01-20 23:39:37 +11:00
ptoken - > sids = talloc_realloc ( ptoken , ptoken - > sids , struct dom_sid , ptoken - > num_sids + 1 ) ;
2023-08-03 11:39:12 +12:00
if ( ptoken - > sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-01-20 23:39:37 +11:00
2023-09-27 14:51:36 +13:00
ptoken - > sids [ ptoken - > num_sids ] = * sid ;
2011-01-20 23:39:37 +11:00
ptoken - > num_sids + + ;
}
2010-08-14 20:33:36 +10:00
}
2006-04-27 16:09:17 +00:00
2023-10-10 16:19:53 +13:00
if ( authentication_was_compounded & & num_device_sids ) {
2023-09-27 14:51:36 +13:00
ptoken - > device_sids = talloc_array ( ptoken , struct dom_sid , num_device_sids ) ;
if ( ptoken - > device_sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_device_sids ; i + + ) {
uint32_t check_sid_idx ;
for ( check_sid_idx = 0 ;
check_sid_idx < ptoken - > num_device_sids ;
check_sid_idx + + ) {
if ( dom_sid_equal ( & ptoken - > device_sids [ check_sid_idx ] , & device_sids [ i ] . sid ) ) {
break ;
}
}
if ( check_sid_idx = = ptoken - > num_device_sids ) {
const struct dom_sid * device_sid = & device_sids [ i ] . sid ;
device_sids_are_valid = device_sids_are_valid | | dom_sid_equal (
device_sid , & global_sid_Claims_Valid ) ;
ptoken - > device_sids = talloc_realloc ( ptoken ,
ptoken - > device_sids ,
struct dom_sid ,
ptoken - > num_device_sids + 1 ) ;
if ( ptoken - > device_sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
ptoken - > device_sids [ ptoken - > num_device_sids ] = * device_sid ;
ptoken - > num_device_sids + + ;
}
}
}
2023-08-02 10:41:31 +02:00
/* The caller may have requested simple privileges, for example if there isn't a local DB */
2010-12-21 11:43:04 +11:00
if ( session_info_flags & AUTH_SESSION_INFO_SIMPLE_PRIVILEGES ) {
/* Shortcuts to prevent recursion and avoid lookups */
if ( ptoken - > sids = = NULL ) {
ptoken - > privilege_mask = 0 ;
} else if ( security_token_is_system ( ptoken ) ) {
ptoken - > privilege_mask = ~ 0 ;
} else if ( security_token_is_anonymous ( ptoken ) ) {
ptoken - > privilege_mask = 0 ;
} else if ( security_token_has_builtin_administrators ( ptoken ) ) {
ptoken - > privilege_mask = ~ 0 ;
} else {
/* All other 'users' get a empty priv set so far */
ptoken - > privilege_mask = 0 ;
}
} else {
/* setup the privilege mask for this token */
status = samdb_privilege_setup ( lp_ctx , ptoken ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( ptoken ) ;
2011-01-13 16:55:34 +11:00
DEBUG ( 1 , ( " Unable to access privileges database \n " ) ) ;
2010-12-21 11:43:04 +11:00
return status ;
}
2006-04-27 16:09:17 +00:00
}
2023-09-27 14:51:36 +13:00
/*
* TODO : we might want to regard ‘ session_info_flags ’ for the device
* SIDs as well as for the client SIDs .
*/
if ( sids_are_valid ) {
status = claims_data_security_claims ( ptoken ,
auth_claims . user_claims ,
& ptoken - > user_claims ,
& ptoken - > num_user_claims ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( ptoken ) ;
return status ;
}
}
if ( device_sids_are_valid & & authentication_was_compounded ) {
status = claims_data_security_claims ( ptoken ,
auth_claims . device_claims ,
& ptoken - > device_claims ,
& ptoken - > num_device_claims ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( ptoken ) ;
return status ;
}
}
2010-09-17 15:23:19 +10:00
security_token_debug ( 0 , 10 , ptoken ) ;
2006-04-27 16:09:17 +00:00
* token = ptoken ;
return NT_STATUS_OK ;
}