2007-04-23 04:43:47 +04:00
/*
Unix SMB / CIFS mplementation .
DSDB replication service helper function for outgoing traffic
Copyright ( C ) Stefan Metzmacher 2007
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
2007-04-23 04:43:47 +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/>.
2007-04-23 04:43:47 +04:00
*/
# include "includes.h"
# include "dsdb/samdb/samdb.h"
# include "auth/auth.h"
# include "smbd/service.h"
# include "lib/events/events.h"
# include "lib/messaging/irpc.h"
# include "dsdb/repl/drepl_service.h"
# include "lib/ldb/include/ldb_errors.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2007-04-23 04:43:47 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
# include "librpc/gen_ndr/ndr_drsuapi.h"
# include "librpc/gen_ndr/ndr_drsblobs.h"
# include "libcli/composite/composite.h"
# include "auth/gensec/gensec.h"
2009-09-09 11:04:16 +04:00
# include "param/param.h"
2009-12-23 19:44:40 +03:00
# include "../lib/util/tevent_ntstatus.h"
2007-04-23 04:43:47 +04:00
struct dreplsrv_out_drsuapi_state {
2010-03-08 18:23:17 +03:00
struct tevent_context * ev ;
2007-04-23 04:43:47 +04:00
struct dreplsrv_out_connection * conn ;
struct dreplsrv_drsuapi_connection * drsuapi ;
struct drsuapi_DsBindInfoCtr bind_info_ctr ;
struct drsuapi_DsBind bind_r ;
} ;
2009-12-23 19:44:40 +03:00
static void dreplsrv_out_drsuapi_connect_done ( struct composite_context * creq ) ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
struct tevent_req * dreplsrv_out_drsuapi_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dreplsrv_out_connection * conn )
2007-04-23 04:43:47 +04:00
{
2009-12-23 19:44:40 +03:00
struct tevent_req * req ;
struct dreplsrv_out_drsuapi_state * state ;
2007-04-23 04:43:47 +04:00
struct composite_context * creq ;
2009-12-23 19:44:40 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct dreplsrv_out_drsuapi_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2007-04-23 04:43:47 +04:00
2010-03-08 18:23:17 +03:00
state - > ev = ev ;
2009-12-23 19:44:40 +03:00
state - > conn = conn ;
state - > drsuapi = conn - > drsuapi ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
if ( state - > drsuapi & & ! state - > drsuapi - > pipe - > conn - > dead ) {
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
if ( state - > drsuapi & & state - > drsuapi - > pipe - > conn - > dead ) {
talloc_free ( state - > drsuapi ) ;
2007-04-23 04:43:47 +04:00
conn - > drsuapi = NULL ;
}
2009-12-23 19:44:40 +03:00
state - > drsuapi = talloc_zero ( state , struct dreplsrv_drsuapi_connection ) ;
if ( tevent_req_nomem ( state - > drsuapi , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
creq = dcerpc_pipe_connect_b_send ( state , conn - > binding , & ndr_table_drsuapi ,
2007-04-23 04:43:47 +04:00
conn - > service - > system_session_info - > credentials ,
2009-12-23 19:44:40 +03:00
ev , conn - > service - > task - > lp_ctx ) ;
if ( tevent_req_nomem ( creq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
composite_continue ( NULL , creq , dreplsrv_out_drsuapi_connect_done , req ) ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
return req ;
2007-04-23 04:43:47 +04:00
}
2010-03-08 18:23:17 +03:00
static void dreplsrv_out_drsuapi_bind_done ( struct tevent_req * subreq ) ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
static void dreplsrv_out_drsuapi_connect_done ( struct composite_context * creq )
2007-04-23 04:43:47 +04:00
{
2009-12-23 19:44:40 +03:00
struct tevent_req * req = talloc_get_type ( creq - > async . private_data ,
struct tevent_req ) ;
struct dreplsrv_out_drsuapi_state * state = tevent_req_data ( req ,
struct dreplsrv_out_drsuapi_state ) ;
NTSTATUS status ;
2010-03-08 18:23:17 +03:00
struct tevent_req * subreq ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
status = dcerpc_pipe_connect_b_recv ( creq ,
state - > drsuapi ,
& state - > drsuapi - > pipe ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2010-03-08 18:23:17 +03:00
state - > drsuapi - > drsuapi_handle = state - > drsuapi - > pipe - > binding_handle ;
2009-12-23 19:44:40 +03:00
status = gensec_session_key ( state - > drsuapi - > pipe - > conn - > security_state . generic_state ,
& state - > drsuapi - > gensec_skey ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
state - > bind_info_ctr . length = 28 ;
state - > bind_info_ctr . info . info28 = state - > conn - > service - > bind_info28 ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
state - > bind_r . in . bind_guid = & state - > conn - > service - > ntds_guid ;
state - > bind_r . in . bind_info = & state - > bind_info_ctr ;
state - > bind_r . out . bind_handle = & state - > drsuapi - > bind_handle ;
2007-04-23 04:43:47 +04:00
2010-03-08 18:23:17 +03:00
subreq = dcerpc_drsuapi_DsBind_r_send ( state ,
state - > ev ,
state - > drsuapi - > drsuapi_handle ,
& state - > bind_r ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2009-12-23 19:44:40 +03:00
return ;
}
2010-03-08 18:23:17 +03:00
tevent_req_set_callback ( subreq , dreplsrv_out_drsuapi_bind_done , req ) ;
2007-04-23 04:43:47 +04:00
}
2010-03-08 18:23:17 +03:00
static void dreplsrv_out_drsuapi_bind_done ( struct tevent_req * subreq )
2007-04-23 04:43:47 +04:00
{
2010-03-08 18:23:17 +03:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
2009-12-23 19:44:40 +03:00
struct dreplsrv_out_drsuapi_state * state = tevent_req_data ( req ,
struct dreplsrv_out_drsuapi_state ) ;
NTSTATUS status ;
2007-04-23 04:43:47 +04:00
2010-03-08 18:23:17 +03:00
status = dcerpc_drsuapi_DsBind_r_recv ( subreq , state ) ;
TALLOC_FREE ( subreq ) ;
2009-12-23 19:44:40 +03:00
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
if ( ! W_ERROR_IS_OK ( state - > bind_r . out . result ) ) {
status = werror_to_ntstatus ( state - > bind_r . out . result ) ;
tevent_req_nterror ( req , status ) ;
2007-04-23 04:43:47 +04:00
return ;
}
2009-12-23 19:44:40 +03:00
ZERO_STRUCT ( state - > drsuapi - > remote_info28 ) ;
if ( state - > bind_r . out . bind_info ) {
struct drsuapi_DsBindInfo28 * info28 ;
info28 = & state - > drsuapi - > remote_info28 ;
switch ( state - > bind_r . out . bind_info - > length ) {
2007-04-23 04:43:47 +04:00
case 24 : {
struct drsuapi_DsBindInfo24 * info24 ;
2009-12-23 19:44:40 +03:00
info24 = & state - > bind_r . out . bind_info - > info . info24 ;
info28 - > supported_extensions = info24 - > supported_extensions ;
info28 - > site_guid = info24 - > site_guid ;
info28 - > pid = info24 - > pid ;
info28 - > repl_epoch = 0 ;
2007-04-23 04:43:47 +04:00
break ;
}
2008-07-23 16:07:06 +04:00
case 48 : {
struct drsuapi_DsBindInfo48 * info48 ;
2009-12-23 19:44:40 +03:00
info48 = & state - > bind_r . out . bind_info - > info . info48 ;
info28 - > supported_extensions = info48 - > supported_extensions ;
info28 - > site_guid = info48 - > site_guid ;
info28 - > pid = info48 - > pid ;
info28 - > repl_epoch = info48 - > repl_epoch ;
2008-07-23 16:07:06 +04:00
break ;
}
2007-04-23 04:43:47 +04:00
case 28 :
2009-12-23 19:44:40 +03:00
* info28 = state - > bind_r . out . bind_info - > info . info28 ;
2007-04-23 04:43:47 +04:00
break ;
}
}
2009-12-23 19:44:40 +03:00
tevent_req_done ( req ) ;
2007-04-23 04:43:47 +04:00
}
2009-12-23 19:44:40 +03:00
NTSTATUS dreplsrv_out_drsuapi_recv ( struct tevent_req * req )
2007-04-23 04:43:47 +04:00
{
2009-12-23 19:44:40 +03:00
struct dreplsrv_out_drsuapi_state * state = tevent_req_data ( req ,
struct dreplsrv_out_drsuapi_state ) ;
2007-04-23 04:43:47 +04:00
NTSTATUS status ;
2009-12-23 19:44:40 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
2007-04-23 04:43:47 +04:00
}
2009-12-23 19:44:40 +03:00
state - > conn - > drsuapi = talloc_move ( state - > conn , & state - > drsuapi ) ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2007-04-23 04:43:47 +04:00
}
struct dreplsrv_op_pull_source_state {
2010-03-08 18:23:17 +03:00
struct tevent_context * ev ;
2007-04-23 04:43:47 +04:00
struct dreplsrv_out_operation * op ;
2010-02-27 11:46:30 +03:00
void * ndr_struct_ptr ;
2007-04-23 04:43:47 +04:00
} ;
2009-12-23 19:44:40 +03:00
static void dreplsrv_op_pull_source_connect_done ( struct tevent_req * subreq ) ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
struct tevent_req * dreplsrv_op_pull_source_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dreplsrv_out_operation * op )
2007-04-23 04:43:47 +04:00
{
2009-12-30 19:11:51 +03:00
struct tevent_req * req ;
struct dreplsrv_op_pull_source_state * state ;
2009-12-23 19:44:40 +03:00
struct tevent_req * subreq ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct dreplsrv_op_pull_source_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2010-03-08 18:23:17 +03:00
state - > ev = ev ;
2009-12-30 19:11:51 +03:00
state - > op = op ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
subreq = dreplsrv_out_drsuapi_send ( state , ev , op - > source_dsa - > conn ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , dreplsrv_op_pull_source_connect_done , req ) ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
return req ;
2007-04-23 04:43:47 +04:00
}
2009-12-30 19:11:51 +03:00
static void dreplsrv_op_pull_source_get_changes_trigger ( struct tevent_req * req ) ;
2007-04-23 04:43:47 +04:00
2009-12-23 19:44:40 +03:00
static void dreplsrv_op_pull_source_connect_done ( struct tevent_req * subreq )
2007-04-23 04:43:47 +04:00
{
2009-12-30 19:11:51 +03:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
NTSTATUS status ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
status = dreplsrv_out_drsuapi_recv ( subreq ) ;
2009-12-23 19:44:40 +03:00
TALLOC_FREE ( subreq ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
dreplsrv_op_pull_source_get_changes_trigger ( req ) ;
2007-04-23 04:43:47 +04:00
}
2010-03-08 18:23:17 +03:00
static void dreplsrv_op_pull_source_get_changes_done ( struct tevent_req * subreq ) ;
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
static void dreplsrv_op_pull_source_get_changes_trigger ( struct tevent_req * req )
2007-04-23 04:43:47 +04:00
{
2009-12-30 19:11:51 +03:00
struct dreplsrv_op_pull_source_state * state = tevent_req_data ( req ,
struct dreplsrv_op_pull_source_state ) ;
struct repsFromTo1 * rf1 = state - > op - > source_dsa - > repsFrom1 ;
struct dreplsrv_service * service = state - > op - > service ;
struct dreplsrv_partition * partition = state - > op - > source_dsa - > partition ;
struct dreplsrv_drsuapi_connection * drsuapi = state - > op - > source_dsa - > conn - > drsuapi ;
2007-04-23 04:43:47 +04:00
struct drsuapi_DsGetNCChanges * r ;
2010-01-09 06:29:39 +03:00
struct drsuapi_DsReplicaCursorCtrEx * uptodateness_vector ;
2010-03-08 18:23:17 +03:00
struct tevent_req * subreq ;
2010-04-16 00:39:54 +04:00
2010-04-26 10:44:44 +04:00
if ( ( rf1 - > replica_flags & DRSUAPI_DRS_WRIT_REP ) = = 0 & &
state - > op - > extended_op = = DRSUAPI_EXOP_NONE ) {
2010-04-16 00:39:54 +04:00
return ;
}
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
r = talloc ( state , struct drsuapi_DsGetNCChanges ) ;
if ( tevent_req_nomem ( r , req ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2010-03-05 21:33:46 +03:00
r - > out . level_out = talloc ( r , uint32_t ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nomem ( r - > out . level_out , req ) ) {
return ;
}
2008-10-17 22:32:36 +04:00
r - > in . req = talloc ( r , union drsuapi_DsGetNCChangesRequest ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nomem ( r - > in . req , req ) ) {
return ;
}
2008-10-17 22:32:36 +04:00
r - > out . ctr = talloc ( r , union drsuapi_DsGetNCChangesCtr ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nomem ( r - > out . ctr , req ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2010-01-09 06:29:39 +03:00
if ( partition - > uptodatevector_ex . count = = 0 ) {
uptodateness_vector = NULL ;
} else {
uptodateness_vector = & partition - > uptodatevector_ex ;
}
2007-04-23 04:43:47 +04:00
r - > in . bind_handle = & drsuapi - > bind_handle ;
if ( drsuapi - > remote_info28 . supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8 ) {
2008-10-17 22:32:36 +04:00
r - > in . level = 8 ;
r - > in . req - > req8 . destination_dsa_guid = service - > ntds_guid ;
r - > in . req - > req8 . source_dsa_invocation_id = rf1 - > source_dsa_invocation_id ;
r - > in . req - > req8 . naming_context = & partition - > nc ;
r - > in . req - > req8 . highwatermark = rf1 - > highwatermark ;
2010-01-09 06:29:39 +03:00
r - > in . req - > req8 . uptodateness_vector = uptodateness_vector ;
2008-10-17 22:32:36 +04:00
r - > in . req - > req8 . replica_flags = rf1 - > replica_flags ;
r - > in . req - > req8 . max_object_count = 133 ;
r - > in . req - > req8 . max_ndr_size = 1336811 ;
2009-12-30 19:11:51 +03:00
r - > in . req - > req8 . extended_op = state - > op - > extended_op ;
r - > in . req - > req8 . fsmo_info = state - > op - > fsmo_info ;
2008-10-17 22:32:36 +04:00
r - > in . req - > req8 . partial_attribute_set = NULL ;
r - > in . req - > req8 . partial_attribute_set_ex = NULL ;
r - > in . req - > req8 . mapping_ctr . num_mappings = 0 ;
r - > in . req - > req8 . mapping_ctr . mappings = NULL ;
2007-04-23 04:43:47 +04:00
} else {
2008-10-17 22:32:36 +04:00
r - > in . level = 5 ;
r - > in . req - > req5 . destination_dsa_guid = service - > ntds_guid ;
r - > in . req - > req5 . source_dsa_invocation_id = rf1 - > source_dsa_invocation_id ;
r - > in . req - > req5 . naming_context = & partition - > nc ;
r - > in . req - > req5 . highwatermark = rf1 - > highwatermark ;
2010-01-09 06:29:39 +03:00
r - > in . req - > req5 . uptodateness_vector = uptodateness_vector ;
2008-10-17 22:32:36 +04:00
r - > in . req - > req5 . replica_flags = rf1 - > replica_flags ;
r - > in . req - > req5 . max_object_count = 133 ;
r - > in . req - > req5 . max_ndr_size = 1336770 ;
2009-12-30 19:11:51 +03:00
r - > in . req - > req5 . extended_op = state - > op - > extended_op ;
r - > in . req - > req5 . fsmo_info = state - > op - > fsmo_info ;
2007-04-23 04:43:47 +04:00
}
2010-01-09 06:29:39 +03:00
#if 0
NDR_PRINT_IN_DEBUG ( drsuapi_DsGetNCChanges , r ) ;
# endif
2010-02-27 11:46:30 +03:00
state - > ndr_struct_ptr = r ;
2010-03-08 18:23:17 +03:00
subreq = dcerpc_drsuapi_DsGetNCChanges_r_send ( state ,
state - > ev ,
drsuapi - > drsuapi_handle ,
r ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2009-12-30 19:11:51 +03:00
return ;
}
2010-03-08 18:23:17 +03:00
tevent_req_set_callback ( subreq , dreplsrv_op_pull_source_get_changes_done , req ) ;
2007-04-23 04:43:47 +04:00
}
2009-12-30 19:11:51 +03:00
static void dreplsrv_op_pull_source_apply_changes_trigger ( struct tevent_req * req ,
struct drsuapi_DsGetNCChanges * r ,
uint32_t ctr_level ,
struct drsuapi_DsGetNCChangesCtr1 * ctr1 ,
struct drsuapi_DsGetNCChangesCtr6 * ctr6 ) ;
2007-04-23 04:43:47 +04:00
2010-03-08 18:23:17 +03:00
static void dreplsrv_op_pull_source_get_changes_done ( struct tevent_req * subreq )
2007-04-23 04:43:47 +04:00
{
2010-03-08 18:23:17 +03:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
2010-02-27 11:46:30 +03:00
struct dreplsrv_op_pull_source_state * state = tevent_req_data ( req ,
struct dreplsrv_op_pull_source_state ) ;
2009-12-30 19:11:51 +03:00
NTSTATUS status ;
2010-02-27 11:46:30 +03:00
struct drsuapi_DsGetNCChanges * r = talloc_get_type ( state - > ndr_struct_ptr ,
2007-04-23 04:43:47 +04:00
struct drsuapi_DsGetNCChanges ) ;
uint32_t ctr_level = 0 ;
struct drsuapi_DsGetNCChangesCtr1 * ctr1 = NULL ;
struct drsuapi_DsGetNCChangesCtr6 * ctr6 = NULL ;
2010-07-08 18:18:21 +04:00
enum drsuapi_DsExtendedError extended_ret ;
2010-02-27 11:46:30 +03:00
state - > ndr_struct_ptr = NULL ;
2010-03-08 18:23:17 +03:00
status = dcerpc_drsuapi_DsGetNCChanges_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
2009-12-30 19:11:51 +03:00
status = werror_to_ntstatus ( r - > out . result ) ;
tevent_req_nterror ( req , status ) ;
2007-04-23 04:43:47 +04:00
return ;
}
2008-10-17 22:32:36 +04:00
if ( * r - > out . level_out = = 1 ) {
2007-04-23 04:43:47 +04:00
ctr_level = 1 ;
2008-10-17 22:32:36 +04:00
ctr1 = & r - > out . ctr - > ctr1 ;
} else if ( * r - > out . level_out = = 2 & &
r - > out . ctr - > ctr2 . mszip1 . ts ) {
2007-04-23 04:43:47 +04:00
ctr_level = 1 ;
2008-10-17 22:32:36 +04:00
ctr1 = & r - > out . ctr - > ctr2 . mszip1 . ts - > ctr1 ;
} else if ( * r - > out . level_out = = 6 ) {
2007-04-23 04:43:47 +04:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr6 ;
} else if ( * r - > out . level_out = = 7 & &
r - > out . ctr - > ctr7 . level = = 6 & &
r - > out . ctr - > ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_MSZIP & &
r - > out . ctr - > ctr7 . ctr . mszip6 . ts ) {
2007-04-23 04:43:47 +04:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr7 . ctr . mszip6 . ts - > ctr6 ;
} else if ( * r - > out . level_out = = 7 & &
r - > out . ctr - > ctr7 . level = = 6 & &
r - > out . ctr - > ctr7 . type = = DRSUAPI_COMPRESSION_TYPE_XPRESS & &
r - > out . ctr - > ctr7 . ctr . xpress6 . ts ) {
2008-07-16 14:58:29 +04:00
ctr_level = 6 ;
2008-10-17 22:32:36 +04:00
ctr6 = & r - > out . ctr - > ctr7 . ctr . xpress6 . ts - > ctr6 ;
2007-04-23 04:43:47 +04:00
} else {
2009-12-30 19:11:51 +03:00
status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
tevent_req_nterror ( req , status ) ;
2007-04-23 04:43:47 +04:00
return ;
}
2008-08-19 12:36:24 +04:00
if ( ! ctr1 & & ! ctr6 ) {
2009-12-30 19:11:51 +03:00
status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
tevent_req_nterror ( req , status ) ;
2008-08-19 12:36:24 +04:00
return ;
}
2008-07-16 15:00:07 +04:00
if ( ctr_level = = 6 ) {
if ( ! W_ERROR_IS_OK ( ctr6 - > drs_error ) ) {
2009-12-30 19:11:51 +03:00
status = werror_to_ntstatus ( ctr6 - > drs_error ) ;
tevent_req_nterror ( req , status ) ;
2008-07-16 15:00:07 +04:00
return ;
}
2010-07-08 18:18:21 +04:00
extended_ret = ctr6 - > extended_ret ;
}
if ( ctr_level = = 1 ) {
extended_ret = ctr1 - > extended_ret ;
}
if ( state - > op - > extended_op ! = DRSUAPI_EXOP_NONE ) {
2010-07-08 18:20:11 +04:00
state - > op - > extended_ret = extended_ret ;
2010-07-08 18:18:21 +04:00
if ( extended_ret ! = DRSUAPI_EXOP_ERR_SUCCESS ) {
status = NT_STATUS_UNSUCCESSFUL ;
tevent_req_nterror ( req , status ) ;
return ;
}
2008-07-16 15:00:07 +04:00
}
2009-12-30 19:11:51 +03:00
dreplsrv_op_pull_source_apply_changes_trigger ( req , r , ctr_level , ctr1 , ctr6 ) ;
2007-04-23 04:43:47 +04:00
}
2009-12-30 19:11:51 +03:00
static void dreplsrv_update_refs_trigger ( struct tevent_req * req ) ;
2009-09-09 11:04:16 +04:00
2009-12-30 19:11:51 +03:00
static void dreplsrv_op_pull_source_apply_changes_trigger ( struct tevent_req * req ,
struct drsuapi_DsGetNCChanges * r ,
uint32_t ctr_level ,
struct drsuapi_DsGetNCChangesCtr1 * ctr1 ,
struct drsuapi_DsGetNCChangesCtr6 * ctr6 )
2007-04-23 04:43:47 +04:00
{
2009-12-30 19:11:51 +03:00
struct dreplsrv_op_pull_source_state * state = tevent_req_data ( req ,
struct dreplsrv_op_pull_source_state ) ;
struct repsFromTo1 rf1 = * state - > op - > source_dsa - > repsFrom1 ;
struct dreplsrv_service * service = state - > op - > service ;
struct dreplsrv_partition * partition = state - > op - > source_dsa - > partition ;
struct dreplsrv_drsuapi_connection * drsuapi = state - > op - > source_dsa - > conn - > drsuapi ;
2007-04-23 04:43:47 +04:00
const struct drsuapi_DsReplicaOIDMapping_Ctr * mapping_ctr ;
uint32_t object_count ;
struct drsuapi_DsReplicaObjectListItemEx * first_object ;
uint32_t linked_attributes_count ;
struct drsuapi_DsReplicaLinkedAttribute * linked_attributes ;
const struct drsuapi_DsReplicaCursor2CtrEx * uptodateness_vector ;
2009-11-09 13:26:02 +03:00
struct dsdb_extended_replicated_objects * objects ;
2007-04-23 04:43:47 +04:00
bool more_data = false ;
WERROR status ;
2009-12-30 19:11:51 +03:00
NTSTATUS nt_status ;
2007-04-23 04:43:47 +04:00
switch ( ctr_level ) {
case 1 :
mapping_ctr = & ctr1 - > mapping_ctr ;
object_count = ctr1 - > object_count ;
first_object = ctr1 - > first_object ;
linked_attributes_count = 0 ;
linked_attributes = NULL ;
rf1 . highwatermark = ctr1 - > new_highwatermark ;
uptodateness_vector = NULL ; /* TODO: map it */
2008-07-16 15:01:56 +04:00
more_data = ctr1 - > more_data ;
2007-04-23 04:43:47 +04:00
break ;
case 6 :
mapping_ctr = & ctr6 - > mapping_ctr ;
object_count = ctr6 - > object_count ;
first_object = ctr6 - > first_object ;
linked_attributes_count = ctr6 - > linked_attributes_count ;
linked_attributes = ctr6 - > linked_attributes ;
rf1 . highwatermark = ctr6 - > new_highwatermark ;
uptodateness_vector = ctr6 - > uptodateness_vector ;
2008-07-16 15:01:56 +04:00
more_data = ctr6 - > more_data ;
2007-04-23 04:43:47 +04:00
break ;
default :
2009-12-30 19:11:51 +03:00
nt_status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
tevent_req_nterror ( req , nt_status ) ;
2007-04-23 04:43:47 +04:00
return ;
}
2009-11-09 13:26:02 +03:00
status = dsdb_extended_replicated_objects_convert ( service - > samdb ,
partition - > nc . dn ,
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
& rf1 ,
uptodateness_vector ,
& drsuapi - > gensec_skey ,
2009-12-30 19:11:51 +03:00
state , & objects ) ;
2009-11-09 13:26:02 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2009-12-30 19:11:51 +03:00
nt_status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
DEBUG ( 0 , ( " Failed to convert objects: %s/%s \n " ,
win_errstr ( status ) , nt_errstr ( nt_status ) ) ) ;
tevent_req_nterror ( req , nt_status ) ;
2009-11-09 13:26:02 +03:00
return ;
}
2007-04-23 04:43:47 +04:00
status = dsdb_extended_replicated_objects_commit ( service - > samdb ,
2009-11-09 13:26:02 +03:00
objects ,
2009-12-30 19:11:51 +03:00
& state - > op - > source_dsa - > notify_uSN ) ;
2009-11-09 13:26:02 +03:00
talloc_free ( objects ) ;
2007-04-23 04:43:47 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2009-12-30 19:11:51 +03:00
nt_status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
DEBUG ( 0 , ( " Failed to commit objects: %s/%s \n " ,
win_errstr ( status ) , nt_errstr ( nt_status ) ) ) ;
tevent_req_nterror ( req , nt_status ) ;
2007-04-23 04:43:47 +04:00
return ;
}
/* if it applied fine, we need to update the highwatermark */
2009-12-30 19:11:51 +03:00
* state - > op - > source_dsa - > repsFrom1 = rf1 ;
2007-04-23 04:43:47 +04:00
/*
* TODO : update our uptodatevector !
*/
2009-12-30 19:11:51 +03:00
/* we don't need this maybe very large structure anymore */
TALLOC_FREE ( r ) ;
2007-04-23 04:43:47 +04:00
if ( more_data ) {
2009-12-30 19:11:51 +03:00
dreplsrv_op_pull_source_get_changes_trigger ( req ) ;
2007-04-23 04:43:47 +04:00
return ;
}
2009-09-09 11:04:16 +04:00
/* now we need to update the repsTo record for this partition
on the server . These records are initially established when
we join the domain , but they quickly expire . We do it here
so we can use the already established DRSUAPI pipe
*/
2010-04-26 12:43:46 +04:00
if ( state - > op - > extended_op = = DRSUAPI_EXOP_NONE ) {
dreplsrv_update_refs_trigger ( req ) ;
2010-04-26 15:48:06 +04:00
} else {
tevent_req_done ( req ) ;
2010-04-26 12:43:46 +04:00
}
2007-04-23 04:43:47 +04:00
}
2010-03-08 18:23:17 +03:00
static void dreplsrv_update_refs_done ( struct tevent_req * subreq ) ;
2009-12-30 19:11:51 +03:00
/*
send a UpdateRefs request to refresh our repsTo record on the server
*/
static void dreplsrv_update_refs_trigger ( struct tevent_req * req )
2007-04-23 04:43:47 +04:00
{
2009-12-30 19:11:51 +03:00
struct dreplsrv_op_pull_source_state * state = tevent_req_data ( req ,
struct dreplsrv_op_pull_source_state ) ;
struct dreplsrv_service * service = state - > op - > service ;
struct dreplsrv_partition * partition = state - > op - > source_dsa - > partition ;
struct dreplsrv_drsuapi_connection * drsuapi = state - > op - > source_dsa - > conn - > drsuapi ;
struct drsuapi_DsReplicaUpdateRefs * r ;
char * ntds_guid_str ;
char * ntds_dns_name ;
2010-03-08 18:23:17 +03:00
struct tevent_req * subreq ;
2010-04-16 00:37:40 +04:00
bool am_rodc ;
int ret ;
2009-12-30 19:11:51 +03:00
r = talloc ( state , struct drsuapi_DsReplicaUpdateRefs ) ;
if ( tevent_req_nomem ( r , req ) ) {
return ;
}
ntds_guid_str = GUID_string ( r , & service - > ntds_guid ) ;
if ( tevent_req_nomem ( ntds_guid_str , req ) ) {
return ;
}
ntds_dns_name = talloc_asprintf ( r , " %s._msdcs.%s " ,
ntds_guid_str ,
2010-07-16 08:32:42 +04:00
lpcfg_dnsdomain ( service - > task - > lp_ctx ) ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nomem ( ntds_dns_name , req ) ) {
return ;
}
2007-04-23 04:43:47 +04:00
2009-12-30 19:11:51 +03:00
r - > in . bind_handle = & drsuapi - > bind_handle ;
r - > in . level = 1 ;
r - > in . req . req1 . naming_context = & partition - > nc ;
r - > in . req . req1 . dest_dsa_dns_name = ntds_dns_name ;
r - > in . req . req1 . dest_dsa_guid = service - > ntds_guid ;
2010-01-14 06:37:22 +03:00
r - > in . req . req1 . options = DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_DEL_REF ;
2010-04-16 00:37:40 +04:00
ret = samdb_rodc ( service - > samdb , & am_rodc ) ;
if ( ret = = LDB_SUCCESS & & ! am_rodc ) {
2010-01-14 06:37:22 +03:00
r - > in . req . req1 . options | = DRSUAPI_DRS_WRIT_REP ;
2009-12-30 19:11:51 +03:00
}
2007-04-23 04:43:47 +04:00
2010-02-27 11:46:30 +03:00
state - > ndr_struct_ptr = r ;
2010-03-08 18:23:17 +03:00
subreq = dcerpc_drsuapi_DsReplicaUpdateRefs_r_send ( state ,
state - > ev ,
drsuapi - > drsuapi_handle ,
r ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2009-12-30 19:11:51 +03:00
return ;
}
2010-03-08 18:23:17 +03:00
tevent_req_set_callback ( subreq , dreplsrv_update_refs_done , req ) ;
2007-04-23 04:43:47 +04:00
}
2009-09-09 11:04:16 +04:00
/*
receive a UpdateRefs reply
*/
2010-03-08 18:23:17 +03:00
static void dreplsrv_update_refs_done ( struct tevent_req * subreq )
2009-09-09 11:04:16 +04:00
{
2010-03-08 18:23:17 +03:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2009-12-30 19:11:51 +03:00
struct tevent_req ) ;
2010-02-27 11:46:30 +03:00
struct dreplsrv_op_pull_source_state * state = tevent_req_data ( req ,
struct dreplsrv_op_pull_source_state ) ;
struct drsuapi_DsReplicaUpdateRefs * r = talloc_get_type ( state - > ndr_struct_ptr ,
2009-09-09 11:04:16 +04:00
struct drsuapi_DsReplicaUpdateRefs ) ;
2009-12-30 19:11:51 +03:00
NTSTATUS status ;
2009-09-09 11:04:16 +04:00
2010-02-27 11:46:30 +03:00
state - > ndr_struct_ptr = NULL ;
2010-03-08 18:23:17 +03:00
status = dcerpc_drsuapi_DsReplicaUpdateRefs_r_recv ( subreq , r ) ;
TALLOC_FREE ( subreq ) ;
2009-12-30 19:11:51 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-09-12 09:22:26 +04:00
DEBUG ( 0 , ( " UpdateRefs failed with %s \n " ,
2009-12-30 19:11:51 +03:00
nt_errstr ( status ) ) ) ;
tevent_req_nterror ( req , status ) ;
2009-09-09 11:04:16 +04:00
return ;
}
if ( ! W_ERROR_IS_OK ( r - > out . result ) ) {
2009-12-30 19:11:51 +03:00
status = werror_to_ntstatus ( r - > out . result ) ;
DEBUG ( 0 , ( " UpdateRefs failed with %s/%s for %s %s \n " ,
2009-09-09 11:04:16 +04:00
win_errstr ( r - > out . result ) ,
2009-12-30 19:11:51 +03:00
nt_errstr ( status ) ,
2009-09-09 11:04:16 +04:00
r - > in . req . req1 . dest_dsa_dns_name ,
r - > in . req . req1 . naming_context - > dn ) ) ;
2009-12-30 19:11:51 +03:00
tevent_req_nterror ( req , status ) ;
2009-09-09 11:04:16 +04:00
return ;
}
DEBUG ( 4 , ( " UpdateRefs OK for %s %s \n " ,
r - > in . req . req1 . dest_dsa_dns_name ,
r - > in . req . req1 . naming_context - > dn ) ) ;
2009-12-30 19:11:51 +03:00
tevent_req_done ( req ) ;
2009-09-09 11:04:16 +04:00
}
2009-12-30 19:11:51 +03:00
WERROR dreplsrv_op_pull_source_recv ( struct tevent_req * req )
2009-09-09 11:04:16 +04:00
{
2009-12-30 19:11:51 +03:00
NTSTATUS status ;
2009-09-09 11:04:16 +04:00
2009-12-30 19:11:51 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return ntstatus_to_werror ( status ) ;
2009-09-09 11:04:16 +04:00
}
2009-12-30 19:11:51 +03:00
tevent_req_received ( req ) ;
return WERR_OK ;
2009-09-09 11:04:16 +04:00
}
2009-12-30 19:11:51 +03:00