2004-05-03 18:58:08 +04:00
/*
Unix SMB / CIFS implementation .
interface functions for the sam database
Copyright ( C ) Andrew Tridgell 2004
2006-07-06 09:23:29 +04:00
Copyright ( C ) Volker Lendecke 2004
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006
2004-05-03 18:58:08 +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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-05-03 18:58:08 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-05-03 18:58:08 +04:00
*/
# include "includes.h"
2004-11-02 05:57:18 +03:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_security.h"
2008-06-14 19:24:17 +04:00
# include "lib/events/events.h"
2010-10-30 04:41:11 +04:00
# include "lib/ldb-samba/ldb_wrap.h"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2023-09-27 04:51:36 +03:00
# include "libcli/security/claims-conversions.h"
2006-11-07 03:48:36 +03:00
# include "libcli/auth/libcli_auth.h"
2007-12-06 23:39:49 +03:00
# include "libcli/ldap/ldap_ndr.h"
2005-01-12 05:40:25 +03:00
# include "system/time.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2007-11-16 22:12:00 +03:00
# include "ldb_wrap.h"
2010-10-17 16:27:18 +04:00
# include "../lib/util/util_ldb.h"
2005-12-28 18:38:36 +03:00
# include "dsdb/samdb/samdb.h"
2009-06-12 16:27:19 +04:00
# include "../libds/common/flags.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2008-04-22 03:53:29 +04:00
# include "lib/events/events.h"
2008-07-15 09:07:13 +04:00
# include "auth/credentials/credentials.h"
# include "param/secrets.h"
2010-04-19 09:51:57 +04:00
# include "auth/auth.h"
2018-04-04 03:39:55 +03:00
# include "lib/tsocket/tsocket.h"
2023-09-14 13:09:50 +03:00
# include "lib/param/loadparm.h"
2004-05-03 18:58:08 +04:00
/*
2011-08-12 09:43:04 +04:00
connect to the SAM database specified by URL
2004-05-06 16:42:42 +04:00
return an opaque context pointer on success , or NULL on failure
2004-05-03 18:58:08 +04:00
*/
2017-09-14 06:02:36 +03: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 03:39:55 +03:00
unsigned int flags ,
const char * url ,
2018-04-11 21:41:30 +03:00
const struct tsocket_address * remote_address ,
2017-09-14 06:02:36 +03:00
struct ldb_context * * ldb_ret ,
char * * errstring )
2004-05-03 18:58:08 +04:00
{
2017-09-14 06:02:36 +03:00
struct ldb_context * ldb = NULL ;
2010-10-11 01:25:38 +04:00
int ret ;
2017-09-14 06:02:36 +03:00
* ldb_ret = NULL ;
* errstring = NULL ;
2018-04-04 03:39:55 +03:00
2020-11-23 09:35:37 +03:00
/* We create sam.ldb in provision, and never anywhere else */
flags | = LDB_FLG_DONT_CREATE_DB ;
2018-04-04 03:39:55 +03: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 06:02:36 +03:00
}
}
2010-10-11 01:25:38 +04:00
2011-11-01 05:11:57 +04:00
ldb = samba_ldb_init ( mem_ctx , ev_ctx , lp_ctx , session_info , NULL ) ;
2010-10-11 01:25:38 +04:00
2017-09-14 06:02:36 +03: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-11 01:25:38 +04:00
dsdb_set_global_schema ( ldb ) ;
ret = samba_ldb_connect ( ldb , lp_ctx , url , flags ) ;
if ( ret ! = LDB_SUCCESS ) {
2017-09-14 06:02:36 +03:00
* errstring = talloc_asprintf ( mem_ctx ,
" Failed to connect to %s: %s " ,
url ,
ldb_errstring ( ldb ) ) ;
2010-10-11 01:25:38 +04:00
talloc_free ( ldb ) ;
2017-09-14 06:02:36 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-10-07 15:31:45 +04:00
}
2010-10-10 18:56:55 +04:00
2018-04-04 03:39:55 +03: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-11 21:41:30 +03:00
discard_const ( remote_address ) ) ;
2018-04-04 03:39:55 +03:00
* ldb_ret = ldb ;
return LDB_SUCCESS ;
}
2024-05-30 02:23:01 +03:00
if ( flags & SAMBA_LDB_WRAP_CONNECT_FLAG_NO_SHARE_CONTEXT ) {
* ldb_ret = ldb ;
return LDB_SUCCESS ;
}
2011-11-01 05:11:57 +04:00
if ( ! ldb_wrap_add ( url , ev_ctx , lp_ctx , session_info , NULL , flags , ldb ) ) {
2017-09-14 06:02:36 +03:00
* errstring = talloc_asprintf ( mem_ctx ,
" Failed to add cached DB reference "
" to %s " ,
url ) ;
2010-10-11 01:25:38 +04:00
talloc_free ( ldb ) ;
2017-09-14 06:02:36 +03:00
return LDB_ERR_OPERATIONS_ERROR ;
2010-10-11 01:25:38 +04:00
}
2017-09-14 06:02:36 +03:00
* ldb_ret = ldb ;
return LDB_SUCCESS ;
2004-05-06 16:42:42 +04:00
}
2004-05-06 13:55:05 +04:00
2006-03-19 21:06:36 +03:00
2011-08-12 09:43:04 +04: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-11 21:41:30 +03:00
const struct tsocket_address * remote_address ,
2011-08-12 09:43:04 +04:00
unsigned int flags )
{
2017-09-14 06:02:36 +03:00
char * errstring ;
struct ldb_context * ldb ;
2018-04-11 21:41:30 +03:00
int ret = samdb_connect_url ( mem_ctx ,
ev_ctx ,
lp_ctx ,
session_info ,
flags ,
" sam.ldb " ,
remote_address ,
& ldb ,
& errstring ) ;
2017-09-14 06:02:36 +03:00
if ( ret = = LDB_SUCCESS ) {
return ldb ;
}
return NULL ;
2011-08-12 09:43:04 +04:00
}
2006-04-27 20:09:17 +04:00
/****************************************************************************
Create the SID list for this user .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS security_token_create ( TALLOC_CTX * mem_ctx ,
2007-12-02 21:04:33 +03:00
struct loadparm_context * lp_ctx ,
2023-08-11 01:34:47 +03:00
uint32_t num_sids ,
2023-08-11 01:35:43 +03:00
const struct auth_SidAttr * sids ,
2023-09-27 04:51:36 +03:00
uint32_t num_device_sids ,
const struct auth_SidAttr * device_sids ,
struct auth_claims auth_claims ,
2010-04-19 09:51:57 +04:00
uint32_t session_info_flags ,
2006-04-27 20:09:17 +04:00
struct security_token * * token )
{
struct security_token * ptoken ;
2023-08-11 01:34:47 +03:00
uint32_t i ;
2006-04-27 20:09:17 +04:00
NTSTATUS status ;
2023-09-14 13:09:50 +03:00
enum claims_evaluation_control evaluate_claims ;
2023-09-27 04:51:36 +03:00
bool sids_are_valid = false ;
bool device_sids_are_valid = false ;
2023-09-27 04:54:06 +03:00
bool authentication_was_compounded = session_info_flags & AUTH_SESSION_INFO_FORCE_COMPOUNDED_AUTHENTICATION ;
2006-04-27 20:09:17 +04:00
2023-09-14 13:09:50 +03: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 20:09:17 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ptoken ) ;
2023-08-11 01:36:04 +03:00
if ( num_sids > UINT32_MAX - 6 ) {
talloc_free ( ptoken ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2011-01-20 15:39:37 +03:00
ptoken - > sids = talloc_array ( ptoken , struct dom_sid , num_sids + 6 /* over-allocate */ ) ;
2023-08-03 02:39:12 +03:00
if ( ptoken - > sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-04-19 09:51:57 +04:00
2011-01-20 15:39:37 +03:00
ptoken - > num_sids = 0 ;
2010-04-19 09:51:57 +04:00
2011-01-20 15:39:37 +03:00
for ( i = 0 ; i < num_sids ; i + + ) {
2023-08-11 01:34:47 +03:00
uint32_t check_sid_idx ;
2011-01-20 15:39:37 +03:00
for ( check_sid_idx = 0 ;
check_sid_idx < ptoken - > num_sids ;
check_sid_idx + + ) {
2022-09-27 05:13:12 +03:00
if ( dom_sid_equal ( & ptoken - > sids [ check_sid_idx ] , & sids [ i ] . sid ) ) {
2011-01-20 15:39:37 +03:00
break ;
}
}
2010-04-19 09:51:57 +04:00
2011-01-20 15:39:37 +03:00
if ( check_sid_idx = = ptoken - > num_sids ) {
2023-09-27 04:51:36 +03: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 15:39:37 +03:00
ptoken - > sids = talloc_realloc ( ptoken , ptoken - > sids , struct dom_sid , ptoken - > num_sids + 1 ) ;
2023-08-03 02:39:12 +03:00
if ( ptoken - > sids = = NULL ) {
talloc_free ( ptoken ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-01-20 15:39:37 +03:00
2023-09-27 04:51:36 +03:00
ptoken - > sids [ ptoken - > num_sids ] = * sid ;
2011-01-20 15:39:37 +03:00
ptoken - > num_sids + + ;
}
2010-08-14 14:33:36 +04:00
}
2006-04-27 20:09:17 +04:00
2023-10-10 06:19:53 +03:00
if ( authentication_was_compounded & & num_device_sids ) {
2023-09-27 04:51:36 +03: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 11:41:31 +03:00
/* The caller may have requested simple privileges, for example if there isn't a local DB */
2010-12-21 03:43:04 +03: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 08:55:34 +03:00
DEBUG ( 1 , ( " Unable to access privileges database \n " ) ) ;
2010-12-21 03:43:04 +03:00
return status ;
}
2006-04-27 20:09:17 +04:00
}
2023-09-27 04:51:36 +03: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 09:23:19 +04:00
security_token_debug ( 0 , 10 , ptoken ) ;
2006-04-27 20:09:17 +04:00
* token = ptoken ;
return NT_STATUS_OK ;
}