2004-10-10 05:35:33 +04:00
/*
Unix SMB / CIFS implementation .
endpoint server for the drsuapi pipe
Copyright ( C ) Stefan Metzmacher 2004
2006-12-28 06:31:50 +03:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006
2004-10-10 05:35:33 +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-10-10 05:35:33 +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-10-10 05:35:33 +04:00
*/
# include "includes.h"
2004-11-01 13:30:34 +03:00
# include "librpc/gen_ndr/ndr_drsuapi.h"
2004-11-02 10:42:47 +03:00
# include "rpc_server/dcerpc_server.h"
2004-10-10 05:35:33 +04:00
# include "rpc_server/common/common.h"
2005-12-28 18:38:36 +03:00
# include "dsdb/samdb/samdb.h"
2011-08-10 01:36:01 +04:00
# include "dsdb/common/util.h"
2009-09-16 06:26:33 +04:00
# include "libcli/security/security.h"
2010-09-20 08:49:39 +04:00
# include "libcli/security/session.h"
2010-11-27 21:42:31 +03:00
# include "rpc_server/drsuapi/dcesrv_drsuapi.h"
2009-10-06 11:58:13 +04:00
# include "auth/auth.h"
2010-01-16 22:52:14 +03:00
# include "param/param.h"
2010-09-15 17:41:47 +04:00
# include "lib/messaging/irpc.h"
2004-10-10 05:35:33 +04:00
2020-10-01 15:22:12 +03:00
# undef strcasecmp
2017-09-06 07:37:34 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_DRS_REPL
2010-01-15 11:34:32 +03:00
# define DRSUAPI_UNSUPPORTED(fname) do { \
DEBUG ( 1 , ( __location__ " : Unsupported DRS call %s \n " , # fname ) ) ; \
if ( DEBUGLVL ( 2 ) ) NDR_PRINT_IN_DEBUG ( fname , r ) ; \
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ; \
} while ( 0 )
2018-11-21 22:06:21 +03:00
# define DCESRV_INTERFACE_DRSUAPI_BIND(context, iface) \
dcesrv_interface_drsuapi_bind ( context , iface )
static NTSTATUS dcesrv_interface_drsuapi_bind ( struct dcesrv_connection_context * context ,
2015-07-14 10:13:00 +03:00
const struct dcesrv_interface * iface )
{
2018-11-21 22:06:21 +03:00
return dcesrv_interface_bind_require_privacy ( context , iface ) ;
2015-07-14 10:13:00 +03:00
}
2004-10-10 05:35:33 +04:00
/*
drsuapi_DsBind
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsBind ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct drsuapi_DsBind * r )
{
struct drsuapi_bind_state * b_state ;
struct dcesrv_handle * handle ;
2004-12-14 10:18:58 +03:00
struct drsuapi_DsBindInfoCtr * bind_info ;
2016-05-25 02:49:24 +03:00
struct drsuapi_DsBindInfoCtr * local_info ;
struct GUID site_guid , config_guid ;
struct ldb_result * site_res , * config_res ;
struct ldb_dn * server_site_dn , * config_dn ;
2007-12-20 02:02:15 +03:00
static const char * site_attrs [ ] = { " objectGUID " , NULL } ;
2016-05-25 02:49:24 +03:00
static const char * config_attrs [ ] = { " objectGUID " , NULL } ;
2007-02-23 10:56:29 +03:00
struct ldb_result * ntds_res ;
struct ldb_dn * ntds_dn ;
2007-12-20 02:02:15 +03:00
static const char * ntds_attrs [ ] = { " ms-DS-ReplicationEpoch " , NULL } ;
2008-07-22 17:35:23 +04:00
uint32_t pid ;
2007-02-23 10:56:29 +03:00
uint32_t repl_epoch ;
2016-05-25 02:49:24 +03:00
uint32_t supported_extensions ;
uint32_t req_length ;
2007-02-23 10:56:29 +03:00
int ret ;
2009-10-06 11:58:13 +04:00
WERROR werr ;
2004-10-10 05:35:33 +04:00
2004-10-14 15:11:21 +04:00
r - > out . bind_info = NULL ;
2004-10-10 05:35:33 +04:00
ZERO_STRUCTP ( r - > out . bind_handle ) ;
2007-02-23 10:56:29 +03:00
b_state = talloc_zero ( mem_ctx , struct drsuapi_bind_state ) ;
2006-04-29 15:48:56 +04:00
W_ERROR_HAVE_NO_MEMORY ( b_state ) ;
2004-10-10 05:35:33 +04:00
2009-10-06 11:58:13 +04:00
/* if this is a DC connecting, give them system level access */
2010-08-17 08:12:21 +04:00
werr = drs_security_level_check ( dce_call , NULL , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
2009-10-06 11:58:13 +04:00
if ( W_ERROR_IS_OK ( werr ) ) {
2021-08-05 14:31:29 +03:00
DBG_NOTICE ( " doing DsBind with system_session \n " ) ;
b_state - > sam_ctx_system = dcesrv_samdb_connect_as_system ( b_state , dce_call ) ;
if ( b_state - > sam_ctx_system = = NULL ) {
return WERR_DS_UNAVAILABLE ;
}
b_state - > sam_ctx = b_state - > sam_ctx_system ;
2009-10-06 11:58:13 +04:00
} else {
2021-08-05 14:31:29 +03:00
b_state - > sam_ctx = dcesrv_samdb_connect_as_user ( b_state , dce_call ) ;
if ( b_state - > sam_ctx = = NULL ) {
return WERR_DS_UNAVAILABLE ;
}
2004-10-10 05:35:33 +04:00
2021-08-05 14:31:29 +03:00
/*
* an RODC also needs system samdb access for secret
* attribute replication
*/
2010-08-18 08:27:17 +04:00
werr = drs_security_level_check ( dce_call , NULL , SECURITY_RO_DOMAIN_CONTROLLER ,
samdb_domain_sid ( b_state - > sam_ctx ) ) ;
if ( W_ERROR_IS_OK ( werr ) ) {
2021-08-05 14:31:29 +03:00
DBG_NOTICE ( " doing DsBind as RODC \n " ) ;
b_state - > sam_ctx_system =
dcesrv_samdb_connect_as_system ( b_state , dce_call ) ;
if ( b_state - > sam_ctx_system = = NULL ) {
return WERR_DS_UNAVAILABLE ;
2010-08-18 08:27:17 +04:00
}
}
}
2007-02-23 10:56:29 +03:00
/*
* find out the guid of our own site
*/
server_site_dn = samdb_server_site_dn ( b_state - > sam_ctx , mem_ctx ) ;
W_ERROR_HAVE_NO_MEMORY ( server_site_dn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & site_res ,
2007-02-23 10:56:29 +03:00
server_site_dn , LDB_SCOPE_BASE , site_attrs ,
" (objectClass=*) " ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( site_res - > count ! = 1 ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
site_guid = samdb_result_guid ( site_res - > msgs [ 0 ] , " objectGUID " ) ;
/*
* lookup the local servers Replication Epoch
*/
2012-08-14 10:08:47 +04:00
ntds_dn = samdb_ntds_settings_dn ( b_state - > sam_ctx , mem_ctx ) ;
2007-02-23 10:56:29 +03:00
W_ERROR_HAVE_NO_MEMORY ( ntds_dn ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & ntds_res ,
2007-02-23 10:56:29 +03:00
ntds_dn , LDB_SCOPE_BASE , ntds_attrs ,
" (objectClass=*) " ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( ntds_res - > count ! = 1 ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
2010-10-14 11:41:42 +04:00
repl_epoch = ldb_msg_find_attr_as_uint ( ntds_res - > msgs [ 0 ] ,
" ms-DS-ReplicationEpoch " , 0 ) ;
2007-02-23 10:56:29 +03:00
/*
2008-07-22 17:35:23 +04:00
* The " process identifier " of the client .
* According to the WSPP docs , sectin 5.35 , this is
* for informational and debugging purposes only .
* The assignment is implementation specific .
2007-02-23 10:56:29 +03:00
*/
2008-07-22 17:35:23 +04:00
pid = 0 ;
2007-02-23 10:56:29 +03:00
/*
* store the clients bind_guid
*/
if ( r - > in . bind_guid ) {
b_state - > remote_bind_guid = * r - > in . bind_guid ;
2004-10-10 05:35:33 +04:00
}
2007-02-23 10:56:29 +03:00
/*
* store the clients bind_info
*/
if ( r - > in . bind_info ) {
2016-05-25 02:49:24 +03:00
b_state - > remote_info = r - > in . bind_info ;
2007-02-23 10:56:29 +03:00
}
2004-10-10 05:35:33 +04:00
2007-02-23 10:56:29 +03:00
/*
2016-05-25 02:49:24 +03:00
* fill in our local bind info
*/
local_info = talloc_zero ( mem_ctx , struct drsuapi_DsBindInfoCtr ) ;
W_ERROR_HAVE_NO_MEMORY ( local_info ) ;
/*
* Fill in supported extensions
2007-02-23 10:56:29 +03:00
*/
2016-05-25 02:49:24 +03:00
supported_extensions = 0 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_BASE ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2 ;
2007-02-23 10:56:29 +03:00
#if 0 /* we don't support MSZIP compression (only decompression) */
2016-05-25 02:49:24 +03:00
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS ;
2007-02-23 10:56:29 +03:00
# endif
2016-05-25 02:49:24 +03:00
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7 ;
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT ;
2007-02-23 10:56:29 +03:00
#if 0 /* we don't support XPRESS compression yet */
2016-05-25 02:49:24 +03:00
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS ;
2007-02-23 10:56:29 +03:00
# endif
2016-05-25 02:49:24 +03:00
supported_extensions | = DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10 ;
/*
* There is a chance for r - > in . bind_info = = NULL
* Currently we don ' t care , since it seems to be used nowhere else .
* But we need a request length . So use 28 as default .
*/
req_length = 28 ;
if ( r - > in . bind_info ) {
req_length = r - > in . bind_info - > length ;
}
/*
* fill 28 or 48 info , depends on request
*/
if ( req_length < 48 ) {
local_info - > length = 28 ;
local_info - > info . info28 . supported_extensions = supported_extensions ;
local_info - > info . info28 . site_guid = site_guid ;
local_info - > info . info28 . pid = pid ;
local_info - > info . info28 . repl_epoch = repl_epoch ;
} else {
local_info - > length = 48 ;
local_info - > info . info48 . supported_extensions = supported_extensions ;
local_info - > info . info48 . site_guid = site_guid ;
local_info - > info . info48 . pid = pid ;
local_info - > info . info48 . repl_epoch = repl_epoch ;
local_info - > info . info48 . supported_extensions_ext = 0 ;
local_info - > info . info48 . supported_extensions_ext | = DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2 ;
/*
* find out the guid of our own site
*/
config_dn = ldb_get_config_basedn ( b_state - > sam_ctx ) ;
W_ERROR_HAVE_NO_MEMORY ( config_dn ) ;
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & config_res ,
config_dn , LDB_SCOPE_BASE , config_attrs ,
" (objectClass=*) " ) ;
if ( ret ! = LDB_SUCCESS ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
if ( config_res - > count ! = 1 ) {
return WERR_DS_DRA_INTERNAL_ERROR ;
}
config_guid = samdb_result_guid ( config_res - > msgs [ 0 ] , " objectGUID " ) ;
local_info - > info . info48 . config_dn_guid = config_guid ;
}
2007-02-23 10:56:29 +03:00
/*
2016-05-25 02:49:24 +03:00
* set local_info
2007-02-23 10:56:29 +03:00
*/
2016-05-25 02:49:24 +03:00
b_state - > local_info = local_info ;
2004-12-14 10:18:58 +03:00
2016-05-25 02:49:24 +03:00
/*
* set bind_info
*/
bind_info = local_info ;
2004-12-14 10:18:58 +03:00
2007-02-23 10:56:29 +03:00
/*
* allocate a bind handle
*/
2018-11-08 14:20:44 +03:00
handle = dcesrv_handle_create ( dce_call , DRSUAPI_BIND_HANDLE ) ;
2007-02-23 10:56:29 +03:00
W_ERROR_HAVE_NO_MEMORY ( handle ) ;
handle - > data = talloc_steal ( handle , b_state ) ;
2004-11-29 14:13:56 +03:00
2007-02-23 10:56:29 +03:00
/*
* prepare reply
*/
2004-11-29 14:13:56 +03:00
r - > out . bind_info = bind_info ;
2004-10-10 05:35:33 +04:00
* r - > out . bind_handle = handle - > wire_handle ;
2004-10-15 15:08:14 +04:00
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
drsuapi_DsUnbind
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsUnbind ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-01-10 15:15:26 +03:00
struct drsuapi_DsUnbind * r )
2004-10-10 05:35:33 +04:00
{
struct dcesrv_handle * h ;
* r - > out . bind_handle = * r - > in . bind_handle ;
2004-10-15 15:08:14 +04:00
DCESRV_PULL_HANDLE_WERR ( h , r - > in . bind_handle , DRSUAPI_BIND_HANDLE ) ;
2004-10-10 05:35:33 +04:00
2005-01-10 15:15:26 +03:00
talloc_free ( h ) ;
2004-10-10 05:35:33 +04:00
ZERO_STRUCTP ( r - > out . bind_handle ) ;
2004-10-15 15:08:14 +04:00
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
2004-11-29 14:13:56 +03:00
drsuapi_DsReplicaSync
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsReplicaSync ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2009-09-09 12:04:07 +04:00
struct drsuapi_DsReplicaSync * r )
2004-10-10 05:35:33 +04:00
{
2009-09-20 02:08:19 +04:00
WERROR status ;
2010-09-15 17:45:37 +04:00
uint32_t timeout ;
2009-09-20 02:08:19 +04:00
2010-08-17 08:12:21 +04:00
status = drs_security_level_check ( dce_call , " DsReplicaSync " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
2009-09-20 02:08:19 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
2009-09-09 12:04:07 +04:00
}
2010-09-15 17:45:37 +04:00
if ( r - > in . level ! = 1 ) {
DEBUG ( 0 , ( " DsReplicaSync called with unsupported level %d \n " , r - > in . level ) ) ;
return WERR_DS_DRA_INVALID_PARAMETER ;
}
if ( r - > in . req - > req1 . options & DRSUAPI_DRS_ASYNC_OP ) {
timeout = IRPC_CALL_TIMEOUT ;
} else {
/*
* use Infinite time for timeout in case
* the caller made a sync call
*/
timeout = IRPC_CALL_TIMEOUT_INF ;
}
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx ,
r , NDR_DRSUAPI_DSREPLICASYNC ,
2009-09-16 07:51:10 +04:00
& ndr_table_drsuapi ,
2010-09-15 17:41:47 +04:00
" dreplsrv " , " DsReplicaSync " ,
2010-09-15 17:45:37 +04:00
timeout ) ;
2009-09-20 02:08:19 +04:00
2004-11-29 14:13:56 +03:00
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
2009-09-16 07:51:10 +04:00
2004-10-10 05:35:33 +04:00
/*
2009-09-11 14:14:11 +04:00
drsuapi_DsReplicaAdd
2004-10-10 05:35:33 +04:00
*/
2009-09-11 14:14:11 +04:00
static WERROR dcesrv_drsuapi_DsReplicaAdd ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_DsReplicaAdd * r )
2004-10-10 05:35:33 +04:00
{
2010-09-16 07:02:23 +04:00
WERROR status ;
status = drs_security_level_check ( dce_call , " DsReplicaAdd " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
}
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx ,
r , NDR_DRSUAPI_DSREPLICAADD ,
& ndr_table_drsuapi ,
" dreplsrv " , " DsReplicaAdd " ,
IRPC_CALL_TIMEOUT ) ;
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
2009-09-11 14:14:11 +04:00
drsuapi_DsReplicaDel
2004-10-10 05:35:33 +04:00
*/
2009-09-11 14:14:11 +04:00
static WERROR dcesrv_drsuapi_DsReplicaDel ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_DsReplicaDel * r )
2004-10-10 05:35:33 +04:00
{
2010-09-16 07:02:23 +04:00
WERROR status ;
status = drs_security_level_check ( dce_call , " DsReplicaDel " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
}
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx ,
r , NDR_DRSUAPI_DSREPLICADEL ,
& ndr_table_drsuapi ,
" dreplsrv " , " DsReplicaDel " ,
IRPC_CALL_TIMEOUT ) ;
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
2009-09-11 14:14:11 +04:00
drsuapi_DsReplicaModify
2004-10-10 05:35:33 +04:00
*/
2009-09-11 14:14:11 +04:00
static WERROR dcesrv_drsuapi_DsReplicaMod ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_DsReplicaMod * r )
2004-10-10 05:35:33 +04:00
{
2010-09-16 07:02:23 +04:00
WERROR status ;
status = drs_security_level_check ( dce_call , " DsReplicaMod " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
}
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx ,
r , NDR_DRSUAPI_DSREPLICAMOD ,
& ndr_table_drsuapi ,
" dreplsrv " , " DsReplicaMod " ,
IRPC_CALL_TIMEOUT ) ;
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_VERIFY_NAMES
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_VERIFY_NAMES ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_VERIFY_NAMES * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_VERIFY_NAMES ) ;
2004-10-10 05:35:33 +04:00
}
/*
2006-07-04 14:25:04 +04:00
drsuapi_DsGetMemberships
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsGetMemberships ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2006-07-04 14:25:04 +04:00
struct drsuapi_DsGetMemberships * r )
2004-10-10 05:35:33 +04:00
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( drsuapi_DsGetMemberships ) ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_INTER_DOMAIN_MOVE
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_INTER_DOMAIN_MOVE ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_INTER_DOMAIN_MOVE * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_INTER_DOMAIN_MOVE ) ;
2004-10-10 05:35:33 +04:00
}
/*
2007-01-03 22:09:34 +03:00
drsuapi_DsGetNT4ChangeLog
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2007-01-03 22:09:34 +03:00
struct drsuapi_DsGetNT4ChangeLog * r )
2004-10-10 05:35:33 +04:00
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( drsuapi_DsGetNT4ChangeLog ) ;
2004-10-10 05:35:33 +04:00
}
/*
2005-10-24 02:20:42 +04:00
drsuapi_DsCrackNames
2004-10-10 05:35:33 +04:00
*/
2008-10-20 20:59:51 +04:00
static WERROR dcesrv_drsuapi_DsCrackNames ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-10-24 02:20:42 +04:00
struct drsuapi_DsCrackNames * r )
{
struct drsuapi_bind_state * b_state ;
struct dcesrv_handle * h ;
2008-10-17 22:08:59 +04:00
* r - > out . level_out = r - > in . level ;
2005-10-24 02:20:42 +04:00
DCESRV_PULL_HANDLE_WERR ( h , r - > in . bind_handle , DRSUAPI_BIND_HANDLE ) ;
b_state = h - > data ;
2008-10-17 22:08:59 +04:00
r - > out . ctr = talloc_zero ( mem_ctx , union drsuapi_DsNameCtr ) ;
W_ERROR_HAVE_NO_MEMORY ( r - > out . ctr ) ;
2005-10-24 02:20:42 +04:00
switch ( r - > in . level ) {
case 1 : {
2010-09-20 20:46:10 +04:00
switch ( r - > in . req - > req1 . format_offered ) {
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX :
2013-06-28 12:11:46 +04:00
case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN :
2010-09-20 20:46:10 +04:00
case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME :
case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME :
2013-06-28 12:11:46 +04:00
case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID :
2010-09-20 20:46:10 +04:00
case DRSUAPI_DS_NAME_FORMAT_LIST_NCS :
case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS :
2013-06-28 12:11:46 +04:00
case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS :
case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE :
2010-09-20 20:46:10 +04:00
case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE :
case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE :
case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE :
case DRSUAPI_DS_NAME_FORMAT_LIST_SITES :
2013-06-28 12:11:46 +04:00
case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID :
case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON :
2010-09-20 20:46:10 +04:00
DEBUG ( 0 , ( " DsCrackNames: Unsupported operation requested: %X " ,
r - > in . req - > req1 . format_offered ) ) ;
return WERR_OK ;
2012-09-25 08:34:02 +04:00
case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER :
return dcesrv_drsuapi_ListInfoServer ( b_state - > sam_ctx , mem_ctx , & r - > in . req - > req1 , & r - > out . ctr - > ctr1 ) ;
2010-09-20 20:46:10 +04:00
case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES :
return dcesrv_drsuapi_ListRoles ( b_state - > sam_ctx , mem_ctx ,
& r - > in . req - > req1 , & r - > out . ctr - > ctr1 ) ;
default : /* format_offered is in the enum drsuapi_DsNameFormat*/
return dcesrv_drsuapi_CrackNamesByNameFormat ( b_state - > sam_ctx , mem_ctx ,
& r - > in . req - > req1 , & r - > out . ctr - > ctr1 ) ;
2005-10-24 02:20:42 +04:00
}
}
}
2015-12-03 17:24:42 +03:00
return WERR_INVALID_LEVEL ;
2005-10-24 02:20:42 +04:00
}
2004-10-10 05:35:33 +04:00
/*
2006-11-22 21:40:27 +03:00
drsuapi_DsRemoveDSServer
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsRemoveDSServer ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2006-11-22 21:40:27 +03:00
struct drsuapi_DsRemoveDSServer * r )
2004-10-10 05:35:33 +04:00
{
2008-10-02 13:28:13 +04:00
struct drsuapi_bind_state * b_state ;
struct dcesrv_handle * h ;
struct ldb_dn * ntds_dn ;
int ret ;
bool ok ;
2009-09-20 02:08:19 +04:00
WERROR status ;
2008-10-02 13:28:13 +04:00
2009-09-09 15:00:01 +04:00
* r - > out . level_out = 1 ;
2008-10-02 13:28:13 +04:00
2010-08-17 08:12:21 +04:00
status = drs_security_level_check ( dce_call , " DsRemoveDSServer " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
2009-09-20 02:08:19 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
2009-09-16 06:26:33 +04:00
}
2008-10-02 13:28:13 +04:00
DCESRV_PULL_HANDLE_WERR ( h , r - > in . bind_handle , DRSUAPI_BIND_HANDLE ) ;
b_state = h - > data ;
switch ( r - > in . level ) {
case 1 :
ntds_dn = ldb_dn_new ( mem_ctx , b_state - > sam_ctx , r - > in . req - > req1 . server_dn ) ;
W_ERROR_HAVE_NO_MEMORY ( ntds_dn ) ;
ok = ldb_dn_validate ( ntds_dn ) ;
if ( ! ok ) {
return WERR_FOOBAR ;
}
/* TODO: it's likely that we need more checks here */
ok = ldb_dn_add_child_fmt ( ntds_dn , " CN=NTDS Settings " ) ;
if ( ! ok ) {
return WERR_FOOBAR ;
}
if ( r - > in . req - > req1 . commit ) {
2011-08-10 01:36:01 +04:00
ret = dsdb_delete ( b_state - > sam_ctx , ntds_dn , DSDB_TREE_DELETE ) ;
2008-10-02 13:28:13 +04:00
if ( ret ! = LDB_SUCCESS ) {
return WERR_FOOBAR ;
}
}
return WERR_OK ;
default :
break ;
}
return WERR_FOOBAR ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_REMOVE_DS_DOMAIN
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_REMOVE_DS_DOMAIN ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_REMOVE_DS_DOMAIN * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_REMOVE_DS_DOMAIN ) ;
2004-10-10 05:35:33 +04:00
}
2006-12-22 10:04:06 +03:00
/* Obtain the site name from a server DN */
2010-07-07 21:03:13 +04:00
static const char * result_site_name ( struct ldb_dn * server_dn )
2006-12-22 10:04:06 +03:00
{
/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
2010-07-07 21:03:13 +04:00
const struct ldb_val * val = ldb_dn_get_component_val ( server_dn , 2 ) ;
const char * name = ldb_dn_get_component_name ( server_dn , 2 ) ;
2006-12-22 10:04:06 +03:00
if ( ! name | | ( ldb_attr_cmp ( name , " cn " ) ! = 0 ) ) {
/* Ensure this matches the format. This gives us a
* bit more confidence that a ' cn ' value will be a
* ascii string */
return NULL ;
}
if ( val ) {
return ( char * ) val - > data ;
}
return NULL ;
}
/*
drsuapi_DsGetDomainControllerInfo
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1 ( struct drsuapi_bind_state * b_state ,
2006-12-22 10:04:06 +03:00
TALLOC_CTX * mem_ctx ,
struct drsuapi_DsGetDomainControllerInfo * r )
{
struct ldb_dn * sites_dn ;
struct ldb_result * res ;
const char * attrs_account_1 [ ] = { " cn " , " dnsHostName " , NULL } ;
const char * attrs_account_2 [ ] = { " cn " , " dnsHostName " , " objectGUID " , NULL } ;
const char * attrs_none [ ] = { NULL } ;
const char * attrs_site [ ] = { " objectGUID " , NULL } ;
const char * attrs_ntds [ ] = { " options " , " objectGUID " , NULL } ;
const char * attrs_1 [ ] = { " serverReference " , " cn " , " dnsHostName " , NULL } ;
const char * attrs_2 [ ] = { " serverReference " , " cn " , " dnsHostName " , " objectGUID " , NULL } ;
const char * * attrs ;
struct drsuapi_DsGetDCInfoCtr1 * ctr1 ;
struct drsuapi_DsGetDCInfoCtr2 * ctr2 ;
2016-05-25 02:49:24 +03:00
struct drsuapi_DsGetDCInfoCtr3 * ctr3 ;
2006-12-22 10:04:06 +03:00
2009-11-21 20:57:24 +03:00
int ret ;
unsigned int i ;
2006-12-22 10:04:06 +03:00
2008-10-17 21:10:22 +04:00
* r - > out . level_out = r - > in . req - > req1 . level ;
2012-09-25 03:09:55 +04:00
r - > out . ctr = talloc_zero ( mem_ctx , union drsuapi_DsGetDCInfoCtr ) ;
2008-10-17 21:10:22 +04:00
W_ERROR_HAVE_NO_MEMORY ( r - > out . ctr ) ;
2006-12-22 10:04:06 +03:00
2008-10-17 21:10:22 +04:00
switch ( * r - > out . level_out ) {
2006-12-22 10:04:06 +03:00
case - 1 :
2006-12-27 05:01:38 +03:00
/* this level is not like the others */
2015-12-03 17:24:42 +03:00
return WERR_INVALID_LEVEL ;
2006-12-22 10:04:06 +03:00
case 1 :
attrs = attrs_1 ;
break ;
case 2 :
2016-05-25 02:49:24 +03:00
case 3 :
2006-12-22 10:04:06 +03:00
attrs = attrs_2 ;
break ;
default :
2015-12-03 17:24:42 +03:00
return WERR_INVALID_LEVEL ;
2006-12-22 10:04:06 +03:00
}
2012-09-25 03:09:55 +04:00
sites_dn = samdb_sites_dn ( b_state - > sam_ctx , mem_ctx ) ;
if ( ! sites_dn ) {
return WERR_DS_OBJ_NOT_FOUND ;
}
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res , sites_dn , LDB_SCOPE_SUBTREE , attrs ,
2012-09-25 10:12:25 +04:00
" (&(objectClass=server)(serverReference=*)) " ) ;
2006-12-22 10:04:06 +03:00
if ( ret ) {
2007-04-23 11:26:08 +04:00
DEBUG ( 1 , ( " searching for servers in sites DN %s failed: %s \n " ,
ldb_dn_get_linearized ( sites_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
2015-12-03 17:24:22 +03:00
return WERR_GEN_FAILURE ;
2006-12-22 10:04:06 +03:00
}
2008-10-17 21:10:22 +04:00
switch ( * r - > out . level_out ) {
2006-12-22 10:04:06 +03:00
case 1 :
2008-10-17 21:10:22 +04:00
ctr1 = & r - > out . ctr - > ctr1 ;
2006-12-22 10:04:06 +03:00
ctr1 - > count = res - > count ;
ctr1 - > array = talloc_zero_array ( mem_ctx ,
struct drsuapi_DsGetDCInfo1 ,
res - > count ) ;
for ( i = 0 ; i < res - > count ; i + + ) {
struct ldb_dn * domain_dn ;
struct ldb_result * res_domain ;
struct ldb_result * res_account ;
2007-08-06 07:01:59 +04:00
struct ldb_dn * ntds_dn = ldb_dn_copy ( mem_ctx , res - > msgs [ i ] - > dn ) ;
2006-12-22 10:04:06 +03:00
struct ldb_dn * ref_dn
= ldb_msg_find_attr_as_dn ( b_state - > sam_ctx ,
mem_ctx , res - > msgs [ i ] ,
" serverReference " ) ;
if ( ! ntds_dn | | ! ldb_dn_add_child_fmt ( ntds_dn , " CN=NTDS Settings " ) ) {
2015-12-03 17:24:19 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-22 10:04:06 +03:00
}
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_account , ref_dn ,
2012-09-25 10:12:25 +04:00
LDB_SCOPE_BASE , attrs_account_1 ,
2013-06-28 04:59:39 +04:00
" (&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=%u)) " ,
2012-09-25 10:12:25 +04:00
UF_SERVER_TRUST_ACCOUNT ) ;
2007-04-23 11:26:08 +04:00
if ( ret = = LDB_SUCCESS & & res_account - > count = = 1 ) {
2007-11-14 00:38:55 +03:00
const char * errstr ;
2006-12-22 10:04:06 +03:00
ctr1 - > array [ i ] . dns_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " dNSHostName " , NULL ) ;
ctr1 - > array [ i ] . netbios_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " cn " , NULL ) ;
ctr1 - > array [ i ] . computer_dn
= ldb_dn_get_linearized ( res_account - > msgs [ 0 ] - > dn ) ;
/* Determine if this is the PDC */
2007-11-14 00:38:55 +03:00
ret = samdb_search_for_parent_domain ( b_state - > sam_ctx ,
mem_ctx , res_account - > msgs [ 0 ] - > dn ,
& domain_dn , & errstr ) ;
2006-12-22 10:04:06 +03:00
2007-11-14 00:38:55 +03:00
if ( ret = = LDB_SUCCESS ) {
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_domain , domain_dn ,
2006-12-22 10:04:06 +03:00
LDB_SCOPE_BASE , attrs_none , " fSMORoleOwner=%s " ,
ldb_dn_get_linearized ( ntds_dn ) ) ;
if ( ret ) {
2015-12-03 17:24:22 +03:00
return WERR_GEN_FAILURE ;
2006-12-22 10:04:06 +03:00
}
if ( res_domain - > count = = 1 ) {
2007-10-07 02:25:41 +04:00
ctr1 - > array [ i ] . is_pdc = true ;
2006-12-22 10:04:06 +03:00
}
}
}
2007-04-23 11:26:08 +04:00
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for computer DN %s failed: %s \n " ,
ldb_dn_get_linearized ( ref_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
2006-12-22 10:04:06 +03:00
/* Look at server DN and extract site component */
ctr1 - > array [ i ] . site_name = result_site_name ( res - > msgs [ i ] - > dn ) ;
ctr1 - > array [ i ] . server_dn = ldb_dn_get_linearized ( res - > msgs [ i ] - > dn ) ;
2007-10-07 02:25:41 +04:00
ctr1 - > array [ i ] . is_enabled = true ;
2006-12-22 10:04:06 +03:00
}
break ;
case 2 :
2008-10-17 21:10:22 +04:00
ctr2 = & r - > out . ctr - > ctr2 ;
2006-12-22 10:04:06 +03:00
ctr2 - > count = res - > count ;
ctr2 - > array = talloc_zero_array ( mem_ctx ,
struct drsuapi_DsGetDCInfo2 ,
res - > count ) ;
for ( i = 0 ; i < res - > count ; i + + ) {
struct ldb_dn * domain_dn ;
struct ldb_result * res_domain ;
struct ldb_result * res_account ;
2007-08-06 07:01:59 +04:00
struct ldb_dn * ntds_dn = ldb_dn_copy ( mem_ctx , res - > msgs [ i ] - > dn ) ;
2006-12-22 10:04:06 +03:00
struct ldb_result * res_ntds ;
2007-08-06 07:01:59 +04:00
struct ldb_dn * site_dn = ldb_dn_copy ( mem_ctx , res - > msgs [ i ] - > dn ) ;
2006-12-22 10:04:06 +03:00
struct ldb_result * res_site ;
struct ldb_dn * ref_dn
= ldb_msg_find_attr_as_dn ( b_state - > sam_ctx ,
mem_ctx , res - > msgs [ i ] ,
" serverReference " ) ;
if ( ! ntds_dn | | ! ldb_dn_add_child_fmt ( ntds_dn , " CN=NTDS Settings " ) ) {
2015-12-03 17:24:19 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-22 10:04:06 +03:00
}
/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
if ( ! site_dn | | ! ldb_dn_remove_child_components ( site_dn , 2 ) ) {
2015-12-03 17:24:19 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2006-12-22 10:04:06 +03:00
}
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_ntds , ntds_dn ,
2006-12-22 10:04:06 +03:00
LDB_SCOPE_BASE , attrs_ntds , " objectClass=nTDSDSA " ) ;
2007-04-23 11:26:08 +04:00
if ( ret = = LDB_SUCCESS & & res_ntds - > count = = 1 ) {
2006-12-22 10:04:06 +03:00
ctr2 - > array [ i ] . is_gc
2011-03-01 16:06:23 +03:00
= ( ldb_msg_find_attr_as_uint ( res_ntds - > msgs [ 0 ] , " options " , 0 ) & DS_NTDSDSA_OPT_IS_GC ) ;
2006-12-22 10:04:06 +03:00
ctr2 - > array [ i ] . ntds_guid
= samdb_result_guid ( res_ntds - > msgs [ 0 ] , " objectGUID " ) ;
ctr2 - > array [ i ] . ntds_dn = ldb_dn_get_linearized ( res_ntds - > msgs [ 0 ] - > dn ) ;
}
2007-04-23 11:26:08 +04:00
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for NTDS DN %s failed: %s \n " ,
ldb_dn_get_linearized ( ntds_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
2006-12-22 10:04:06 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_site , site_dn ,
2006-12-22 10:04:06 +03:00
LDB_SCOPE_BASE , attrs_site , " objectClass=site " ) ;
2007-04-23 11:26:08 +04:00
if ( ret = = LDB_SUCCESS & & res_site - > count = = 1 ) {
2006-12-22 10:04:06 +03:00
ctr2 - > array [ i ] . site_guid
= samdb_result_guid ( res_site - > msgs [ 0 ] , " objectGUID " ) ;
ctr2 - > array [ i ] . site_dn = ldb_dn_get_linearized ( res_site - > msgs [ 0 ] - > dn ) ;
}
2007-04-23 11:26:08 +04:00
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for site DN %s failed: %s \n " ,
ldb_dn_get_linearized ( site_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
2006-12-22 10:04:06 +03:00
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_account , ref_dn ,
2006-12-22 10:04:06 +03:00
LDB_SCOPE_BASE , attrs_account_2 , " objectClass=computer " ) ;
2007-04-23 11:26:08 +04:00
if ( ret = = LDB_SUCCESS & & res_account - > count = = 1 ) {
2007-11-14 00:38:55 +03:00
const char * errstr ;
2006-12-22 10:04:06 +03:00
ctr2 - > array [ i ] . dns_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " dNSHostName " , NULL ) ;
ctr2 - > array [ i ] . netbios_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " cn " , NULL ) ;
ctr2 - > array [ i ] . computer_dn = ldb_dn_get_linearized ( res_account - > msgs [ 0 ] - > dn ) ;
ctr2 - > array [ i ] . computer_guid
= samdb_result_guid ( res_account - > msgs [ 0 ] , " objectGUID " ) ;
/* Determine if this is the PDC */
2007-11-14 00:38:55 +03:00
ret = samdb_search_for_parent_domain ( b_state - > sam_ctx ,
mem_ctx , res_account - > msgs [ 0 ] - > dn ,
& domain_dn , & errstr ) ;
2006-12-22 10:04:06 +03:00
2007-11-14 00:38:55 +03:00
if ( ret = = LDB_SUCCESS ) {
2008-09-23 22:30:06 +04:00
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_domain , domain_dn ,
2006-12-22 10:04:06 +03:00
LDB_SCOPE_BASE , attrs_none , " fSMORoleOwner=%s " ,
ldb_dn_get_linearized ( ntds_dn ) ) ;
2007-04-23 11:26:08 +04:00
if ( ret = = LDB_SUCCESS & & res_domain - > count = = 1 ) {
2007-10-07 02:25:41 +04:00
ctr2 - > array [ i ] . is_pdc = true ;
2006-12-22 10:04:06 +03:00
}
2007-04-23 11:26:08 +04:00
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for domain DN %s failed: %s \n " ,
ldb_dn_get_linearized ( domain_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
2006-12-22 10:04:06 +03:00
}
}
2007-04-23 11:26:08 +04:00
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for computer account DN %s failed: %s \n " ,
ldb_dn_get_linearized ( ref_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
2006-12-22 10:04:06 +03:00
/* Look at server DN and extract site component */
ctr2 - > array [ i ] . site_name = result_site_name ( res - > msgs [ i ] - > dn ) ;
ctr2 - > array [ i ] . server_dn = ldb_dn_get_linearized ( res - > msgs [ i ] - > dn ) ;
ctr2 - > array [ i ] . server_guid
= samdb_result_guid ( res - > msgs [ i ] , " objectGUID " ) ;
2007-10-07 02:25:41 +04:00
ctr2 - > array [ i ] . is_enabled = true ;
2006-12-22 10:04:06 +03:00
}
break ;
2016-05-25 02:49:24 +03:00
case 3 :
ctr3 = & r - > out . ctr - > ctr3 ;
ctr3 - > count = res - > count ;
ctr3 - > array = talloc_zero_array ( mem_ctx ,
struct drsuapi_DsGetDCInfo3 ,
res - > count ) ;
for ( i = 0 ; i < res - > count ; i + + ) {
struct ldb_dn * domain_dn ;
struct ldb_result * res_domain ;
struct ldb_result * res_account ;
struct ldb_dn * ntds_dn = ldb_dn_copy ( mem_ctx , res - > msgs [ i ] - > dn ) ;
struct ldb_result * res_ntds ;
struct ldb_dn * site_dn = ldb_dn_copy ( mem_ctx , res - > msgs [ i ] - > dn ) ;
struct ldb_result * res_site ;
bool is_rodc ;
struct ldb_dn * ref_dn
= ldb_msg_find_attr_as_dn ( b_state - > sam_ctx ,
mem_ctx , res - > msgs [ i ] ,
" serverReference " ) ;
if ( ! ntds_dn | | ! ldb_dn_add_child_fmt ( ntds_dn , " CN=NTDS Settings " ) ) {
2015-12-03 17:24:19 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2016-05-25 02:49:24 +03:00
}
/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
if ( ! site_dn | | ! ldb_dn_remove_child_components ( site_dn , 2 ) ) {
2015-12-03 17:24:19 +03:00
return WERR_NOT_ENOUGH_MEMORY ;
2016-05-25 02:49:24 +03:00
}
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_ntds , ntds_dn ,
LDB_SCOPE_BASE , attrs_ntds , " objectClass=nTDSDSA " ) ;
if ( ret = = LDB_SUCCESS & & res_ntds - > count = = 1 ) {
ctr3 - > array [ i ] . is_gc
= ( ldb_msg_find_attr_as_uint ( res_ntds - > msgs [ 0 ] , " options " , 0 ) & DS_NTDSDSA_OPT_IS_GC ) ;
ctr3 - > array [ i ] . ntds_guid
= samdb_result_guid ( res_ntds - > msgs [ 0 ] , " objectGUID " ) ;
ctr3 - > array [ i ] . ntds_dn = ldb_dn_get_linearized ( res_ntds - > msgs [ 0 ] - > dn ) ;
}
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for NTDS DN %s failed: %s \n " ,
ldb_dn_get_linearized ( ntds_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_site , site_dn ,
LDB_SCOPE_BASE , attrs_site , " objectClass=site " ) ;
if ( ret = = LDB_SUCCESS & & res_site - > count = = 1 ) {
ctr3 - > array [ i ] . site_guid
= samdb_result_guid ( res_site - > msgs [ 0 ] , " objectGUID " ) ;
ctr3 - > array [ i ] . site_dn = ldb_dn_get_linearized ( res_site - > msgs [ 0 ] - > dn ) ;
}
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for site DN %s failed: %s \n " ,
ldb_dn_get_linearized ( site_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_account , ref_dn ,
LDB_SCOPE_BASE , attrs_account_2 , " objectClass=computer " ) ;
if ( ret = = LDB_SUCCESS & & res_account - > count = = 1 ) {
const char * errstr ;
ctr3 - > array [ i ] . dns_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " dNSHostName " , NULL ) ;
ctr3 - > array [ i ] . netbios_name
= ldb_msg_find_attr_as_string ( res_account - > msgs [ 0 ] , " cn " , NULL ) ;
ctr3 - > array [ i ] . computer_dn = ldb_dn_get_linearized ( res_account - > msgs [ 0 ] - > dn ) ;
ctr3 - > array [ i ] . computer_guid
= samdb_result_guid ( res_account - > msgs [ 0 ] , " objectGUID " ) ;
/* Determine if this is the PDC */
ret = samdb_search_for_parent_domain ( b_state - > sam_ctx ,
mem_ctx , res_account - > msgs [ 0 ] - > dn ,
& domain_dn , & errstr ) ;
if ( ret = = LDB_SUCCESS ) {
ret = ldb_search ( b_state - > sam_ctx , mem_ctx , & res_domain , domain_dn ,
LDB_SCOPE_BASE , attrs_none , " fSMORoleOwner=%s " ,
ldb_dn_get_linearized ( ntds_dn ) ) ;
if ( ret = = LDB_SUCCESS & & res_domain - > count = = 1 ) {
ctr3 - > array [ i ] . is_pdc = true ;
}
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for domain DN %s failed: %s \n " ,
ldb_dn_get_linearized ( domain_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
}
}
if ( ( ret ! = LDB_SUCCESS ) & & ( ret ! = LDB_ERR_NO_SUCH_OBJECT ) ) {
DEBUG ( 5 , ( " warning: searching for computer account DN %s failed: %s \n " ,
ldb_dn_get_linearized ( ref_dn ) , ldb_errstring ( b_state - > sam_ctx ) ) ) ;
}
/* Look at server DN and extract site component */
ctr3 - > array [ i ] . site_name = result_site_name ( res - > msgs [ i ] - > dn ) ;
ctr3 - > array [ i ] . server_dn = ldb_dn_get_linearized ( res - > msgs [ i ] - > dn ) ;
ctr3 - > array [ i ] . server_guid
= samdb_result_guid ( res - > msgs [ i ] , " objectGUID " ) ;
ctr3 - > array [ i ] . is_enabled = true ;
/* rodc? */
ret = samdb_is_rodc ( b_state - > sam_ctx , & ctr3 - > array [ i ] . server_guid , & is_rodc ) ;
if ( ret = = LDB_SUCCESS & & is_rodc ) {
ctr3 - > array [ i ] . is_rodc = true ;
}
}
break ;
2015-03-18 12:15:47 +03:00
default :
2015-12-03 17:24:42 +03:00
return WERR_INVALID_LEVEL ;
2006-12-22 10:04:06 +03:00
}
return WERR_OK ;
}
2004-10-10 05:35:33 +04:00
/*
2004-10-15 13:48:40 +04:00
drsuapi_DsGetDomainControllerInfo
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-09-17 05:11:50 +04:00
struct drsuapi_DsGetDomainControllerInfo * r )
2004-10-10 05:35:33 +04:00
{
2006-12-22 10:04:06 +03:00
struct dcesrv_handle * h ;
struct drsuapi_bind_state * b_state ;
DCESRV_PULL_HANDLE_WERR ( h , r - > in . bind_handle , DRSUAPI_BIND_HANDLE ) ;
b_state = h - > data ;
switch ( r - > in . level ) {
case 1 :
2007-01-17 17:49:36 +03:00
return dcesrv_drsuapi_DsGetDomainControllerInfo_1 ( b_state , mem_ctx , r ) ;
2006-12-22 10:04:06 +03:00
}
2015-12-03 17:24:42 +03:00
return WERR_INVALID_LEVEL ;
2004-10-10 05:35:33 +04:00
}
/*
2009-09-17 10:45:05 +04:00
drsuapi_DsExecuteKCC
2004-10-10 05:35:33 +04:00
*/
2009-09-17 10:45:05 +04:00
static WERROR dcesrv_drsuapi_DsExecuteKCC ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_DsExecuteKCC * r )
2004-10-10 05:35:33 +04:00
{
2009-11-11 23:25:13 +03:00
WERROR status ;
2015-05-28 07:40:31 +03:00
uint32_t timeout ;
2010-08-17 08:12:21 +04:00
status = drs_security_level_check ( dce_call , " DsExecuteKCC " , SECURITY_DOMAIN_CONTROLLER , NULL ) ;
2009-11-11 23:25:13 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
return status ;
}
2012-09-26 00:27:04 +04:00
if ( r - > in . req - > ctr1 . taskID ! = 0 ) {
2015-12-03 17:24:27 +03:00
return WERR_INVALID_PARAMETER ;
2012-09-26 00:27:04 +04:00
}
2015-05-28 07:40:31 +03:00
if ( r - > in . req - > ctr1 . flags & DRSUAPI_DS_EXECUTE_KCC_ASYNCHRONOUS_OPERATION ) {
timeout = IRPC_CALL_TIMEOUT ;
} else {
/*
* use Infinite time for timeout in case
* the caller made a sync call
*/
timeout = IRPC_CALL_TIMEOUT_INF ;
}
2009-11-11 23:25:13 +03:00
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx , r , NDR_DRSUAPI_DSEXECUTEKCC ,
2010-09-15 17:41:47 +04:00
& ndr_table_drsuapi , " kccsrv " , " DsExecuteKCC " ,
2015-05-28 07:40:31 +03:00
timeout ) ;
2016-07-04 02:17:45 +03:00
DEBUG ( 10 , ( " Forwarded the call to execute the KCC \n " ) ) ;
2009-11-11 23:25:13 +03:00
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
2004-12-07 15:20:28 +03:00
drsuapi_DsReplicaGetInfo
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsReplicaGetInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-12-07 15:20:28 +03:00
struct drsuapi_DsReplicaGetInfo * r )
2004-10-10 05:35:33 +04:00
{
2018-11-03 03:19:51 +03:00
struct auth_session_info * session_info =
dcesrv_call_session_info ( dce_call ) ;
2010-01-16 02:36:06 +03:00
enum security_user_level level ;
2010-01-15 11:36:16 +03:00
2010-07-16 08:32:42 +04:00
if ( ! lpcfg_parm_bool ( dce_call - > conn - > dce_ctx - > lp_ctx , NULL ,
2010-01-16 22:52:14 +03:00
" drs " , " disable_sec_check " , false ) ) {
2018-11-03 03:19:51 +03:00
level = security_session_user_level ( session_info , NULL ) ;
2010-11-27 15:47:03 +03:00
if ( level < SECURITY_DOMAIN_CONTROLLER ) {
2010-01-16 22:52:14 +03:00
DEBUG ( 1 , ( __location__ " : Administrator access required for DsReplicaGetInfo \n " ) ) ;
2018-05-21 04:53:01 +03:00
security_token_debug ( DBGC_DRS_REPL , 2 ,
2018-11-03 03:19:51 +03:00
session_info - > security_token ) ;
2010-01-16 22:52:14 +03:00
return WERR_DS_DRA_ACCESS_DENIED ;
}
2010-01-15 11:36:16 +03:00
}
dcesrv_irpc_forward_rpc_call ( dce_call , mem_ctx , r , NDR_DRSUAPI_DSREPLICAGETINFO ,
2010-09-15 17:41:47 +04:00
& ndr_table_drsuapi , " kccsrv " , " DsReplicaGetInfo " ,
IRPC_CALL_TIMEOUT ) ;
2010-01-15 11:36:16 +03:00
return WERR_OK ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_ADD_SID_HISTORY
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_ADD_SID_HISTORY ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_ADD_SID_HISTORY * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_ADD_SID_HISTORY ) ;
2004-10-10 05:35:33 +04:00
}
/*
2006-07-04 14:25:04 +04:00
drsuapi_DsGetMemberships2
2004-10-10 05:35:33 +04:00
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_drsuapi_DsGetMemberships2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2006-07-04 14:25:04 +04:00
struct drsuapi_DsGetMemberships2 * r )
2004-10-10 05:35:33 +04:00
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( drsuapi_DsGetMemberships2 ) ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_REPLICA_VERIFY_OBJECTS
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_REPLICA_VERIFY_OBJECTS * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_REPLICA_VERIFY_OBJECTS ) ;
2004-10-10 05:35:33 +04:00
}
/*
DRSUAPI_GET_OBJECT_EXISTENCE
*/
2007-01-17 17:49:36 +03:00
static WERROR dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-10-10 05:35:33 +04:00
struct DRSUAPI_GET_OBJECT_EXISTENCE * r )
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( DRSUAPI_GET_OBJECT_EXISTENCE ) ;
2004-10-10 05:35:33 +04:00
}
/*
2007-05-30 13:54:19 +04:00
drsuapi_QuerySitesByCost
2004-10-10 05:35:33 +04:00
*/
2007-05-30 13:54:19 +04:00
static WERROR dcesrv_drsuapi_QuerySitesByCost ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct drsuapi_QuerySitesByCost * r )
2004-10-10 05:35:33 +04:00
{
2010-01-15 11:34:32 +03:00
DRSUAPI_UNSUPPORTED ( drsuapi_QuerySitesByCost ) ;
2004-10-10 05:35:33 +04:00
}
/* include the generated boilerplate */
# include "librpc/gen_ndr/ndr_drsuapi_s.c"