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 "dsdb/repl/drepl_service.h"
2011-02-10 06:12:51 +03:00
# 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"
2011-02-10 12:21:11 +03:00
# include "libcli/security/security.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
2014-01-22 17:14:12 +04:00
if ( state - > drsuapi ! = NULL ) {
struct dcerpc_binding_handle * b =
state - > drsuapi - > pipe - > binding_handle ;
bool is_connected = dcerpc_binding_handle_is_connected ( b ) ;
if ( is_connected ) {
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
2007-04-23 04:43:47 +04:00
2014-01-22 17:14:12 +04:00
TALLOC_FREE ( conn - > drsuapi ) ;
2007-04-23 04:43:47 +04:00
}
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 ,
2011-08-01 09:39:01 +04:00
state - > drsuapi ,
2009-12-23 19:44:40 +03:00
& 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 ;
}
2014-07-04 14:45:59 +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 ;
}
2014-07-04 14:45:59 +04:00
case 32 : {
struct drsuapi_DsBindInfo32 * info32 ;
info32 = & state - > bind_r . out . bind_info - > info . info32 ;
info28 - > supported_extensions = info32 - > supported_extensions ;
info28 - > site_guid = info32 - > site_guid ;
info28 - > pid = info32 - > pid ;
info28 - > repl_epoch = info32 - > repl_epoch ;
break ;
}
2014-07-07 00:02:42 +04:00
case 48 : {
struct drsuapi_DsBindInfo48 * info48 ;
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 ;
break ;
}
2014-07-04 14:45:59 +04:00
case 52 : {
struct drsuapi_DsBindInfo52 * info52 ;
info52 = & state - > bind_r . out . bind_info - > info . info52 ;
info28 - > supported_extensions = info52 - > supported_extensions ;
info28 - > site_guid = info52 - > site_guid ;
info28 - > pid = info52 - > pid ;
info28 - > repl_epoch = info52 - > repl_epoch ;
break ;
}
default :
DEBUG ( 1 , ( " Warning: invalid info length in bind info: %d \n " ,
state - > bind_r . out . bind_info - > length ) ) ;
break ;
}
2007-04-23 04:43:47 +04:00
}
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 ;
2016-08-05 12:05:37 +03:00
/*
* Used when we have to re - try with a different NC , eg for
* EXOP retry or to get a current schema first
*/
struct dreplsrv_partition_source_dsa * source_dsa_retry ;
enum drsuapi_DsExtendedOperation extended_op_retry ;
bool retry_started ;
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
2010-09-15 14:24:50 +04:00
/*
2011-09-21 02:52:14 +04:00
get a RODC partial attribute set for a replication call
2010-09-15 14:24:50 +04:00
*/
static NTSTATUS dreplsrv_get_rodc_partial_attribute_set ( struct dreplsrv_service * service ,
TALLOC_CTX * mem_ctx ,
struct drsuapi_DsPartialAttributeSet * * _pas ,
2016-08-11 05:28:27 +03:00
struct drsuapi_DsReplicaOIDMapping_Ctr * * pfm ,
2010-09-15 14:24:50 +04:00
bool for_schema )
{
struct drsuapi_DsPartialAttributeSet * pas ;
struct dsdb_schema * schema ;
2010-09-16 16:02:21 +04:00
uint32_t i ;
2010-09-15 14:24:50 +04:00
pas = talloc_zero ( mem_ctx , struct drsuapi_DsPartialAttributeSet ) ;
NT_STATUS_HAVE_NO_MEMORY ( pas ) ;
schema = dsdb_get_schema ( service - > samdb , NULL ) ;
pas - > version = 1 ;
pas - > attids = talloc_array ( pas , enum drsuapi_DsAttributeId , schema - > num_attributes ) ;
2014-02-13 08:51:11 +04:00
if ( pas - > attids = = NULL ) {
TALLOC_FREE ( pas ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-09-15 14:24:50 +04:00
for ( i = 0 ; i < schema - > num_attributes ; i + + ) {
struct dsdb_attribute * a ;
a = schema - > attributes_by_attributeID_id [ i ] ;
if ( a - > systemFlags & ( DS_FLAG_ATTR_NOT_REPLICATED | DS_FLAG_ATTR_IS_CONSTRUCTED ) ) {
continue ;
}
if ( a - > searchFlags & SEARCH_FLAG_RODC_ATTRIBUTE ) {
continue ;
}
pas - > attids [ pas - > num_attids ] = dsdb_attribute_get_attid ( a , for_schema ) ;
pas - > num_attids + + ;
}
2011-09-21 02:52:14 +04:00
pas - > attids = talloc_realloc ( pas , pas - > attids , enum drsuapi_DsAttributeId , pas - > num_attids ) ;
2014-02-13 08:51:11 +04:00
if ( pas - > attids = = NULL ) {
TALLOC_FREE ( pas ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-09-21 02:52:14 +04:00
* _pas = pas ;
2016-08-11 05:28:27 +03:00
if ( pfm ! = NULL ) {
dsdb_get_oid_mappings_drsuapi ( schema , true , mem_ctx , pfm ) ;
}
2011-09-21 02:52:14 +04:00
return NT_STATUS_OK ;
}
/*
get a GC partial attribute set for a replication call
*/
static NTSTATUS dreplsrv_get_gc_partial_attribute_set ( struct dreplsrv_service * service ,
TALLOC_CTX * mem_ctx ,
struct drsuapi_DsPartialAttributeSet * * _pas )
{
struct drsuapi_DsPartialAttributeSet * pas ;
struct dsdb_schema * schema ;
uint32_t i ;
pas = talloc_zero ( mem_ctx , struct drsuapi_DsPartialAttributeSet ) ;
NT_STATUS_HAVE_NO_MEMORY ( pas ) ;
schema = dsdb_get_schema ( service - > samdb , NULL ) ;
pas - > version = 1 ;
pas - > attids = talloc_array ( pas , enum drsuapi_DsAttributeId , schema - > num_attributes ) ;
2014-02-13 08:51:11 +04:00
if ( pas - > attids = = NULL ) {
TALLOC_FREE ( pas ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-09-21 02:52:14 +04:00
for ( i = 0 ; i < schema - > num_attributes ; i + + ) {
struct dsdb_attribute * a ;
a = schema - > attributes_by_attributeID_id [ i ] ;
if ( a - > isMemberOfPartialAttributeSet ) {
pas - > attids [ pas - > num_attids ] = dsdb_attribute_get_attid ( a , false ) ;
pas - > num_attids + + ;
}
}
pas - > attids = talloc_realloc ( pas , pas - > attids , enum drsuapi_DsAttributeId , pas - > num_attids ) ;
2014-02-13 08:51:11 +04:00
if ( pas - > attids = = NULL ) {
TALLOC_FREE ( pas ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-09-21 02:52:14 +04:00
2010-09-15 14:24:50 +04:00
* _pas = pas ;
return NT_STATUS_OK ;
}
2010-09-21 07:36:36 +04:00
/*
convert from one udv format to the other
*/
static WERROR udv_convert ( TALLOC_CTX * mem_ctx ,
const struct replUpToDateVectorCtr2 * udv ,
struct drsuapi_DsReplicaCursorCtrEx * udv_ex )
{
uint32_t i ;
udv_ex - > version = 2 ;
udv_ex - > reserved1 = 0 ;
udv_ex - > reserved2 = 0 ;
udv_ex - > count = udv - > count ;
udv_ex - > cursors = talloc_array ( mem_ctx , struct drsuapi_DsReplicaCursor , udv - > count ) ;
W_ERROR_HAVE_NO_MEMORY ( udv_ex - > cursors ) ;
for ( i = 0 ; i < udv - > count ; i + + ) {
udv_ex - > cursors [ i ] . source_dsa_invocation_id = udv - > cursors [ i ] . source_dsa_invocation_id ;
udv_ex - > cursors [ i ] . highest_usn = udv - > cursors [ i ] . highest_usn ;
}
return WERR_OK ;
}
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-09-15 14:24:50 +04:00
struct drsuapi_DsPartialAttributeSet * pas = NULL ;
NTSTATUS status ;
2010-09-15 14:54:09 +04:00
uint32_t replica_flags ;
2011-09-23 11:33:07 +04:00
struct drsuapi_DsReplicaHighWaterMark highwatermark ;
2014-05-23 08:06:17 +04:00
struct ldb_dn * schema_dn = ldb_get_schema_basedn ( service - > samdb ) ;
2016-08-11 05:28:27 +03:00
struct drsuapi_DsReplicaOIDMapping_Ctr * mappings = NULL ;
2010-04-16 00:39:54 +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-09-21 07:36:36 +04:00
if ( partition - > uptodatevector . count ! = 0 & &
partition - > uptodatevector_ex . count = = 0 ) {
WERROR werr ;
werr = udv_convert ( partition , & partition - > uptodatevector , & partition - > uptodatevector_ex ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
DEBUG ( 0 , ( __location__ " : Failed to convert UDV for %s : %s \n " ,
2010-11-27 22:06:18 +03:00
ldb_dn_get_linearized ( partition - > dn ) , win_errstr ( werr ) ) ) ;
2016-08-04 21:09:21 +03:00
tevent_req_nterror ( req , werror_to_ntstatus ( werr ) ) ;
return ;
2010-09-21 07:36:36 +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 ;
}
2010-09-15 14:54:09 +04:00
replica_flags = rf1 - > replica_flags ;
2011-09-23 11:33:07 +04:00
highwatermark = rf1 - > highwatermark ;
2010-09-15 14:54:09 +04:00
2015-12-09 07:05:56 +03:00
if ( state - > op - > options & DRSUAPI_DRS_GET_ANC ) {
replica_flags | = DRSUAPI_DRS_GET_ANC ;
}
2016-07-18 08:05:40 +03:00
if ( state - > op - > options & DRSUAPI_DRS_SYNC_FORCED ) {
replica_flags | = DRSUAPI_DRS_SYNC_FORCED ;
}
2011-09-21 02:52:14 +04:00
if ( partition - > partial_replica ) {
status = dreplsrv_get_gc_partial_attribute_set ( service , r , & pas ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( __location__ " : Failed to construct GC partial attribute set : %s \n " , nt_errstr ( status ) ) ) ;
2016-08-04 21:09:21 +03:00
tevent_req_nterror ( req , status ) ;
2011-09-21 02:52:14 +04:00
return ;
}
2011-09-23 11:33:07 +04:00
replica_flags & = ~ DRSUAPI_DRS_WRIT_REP ;
2011-10-06 04:24:28 +04:00
} else if ( partition - > rodc_replica ) {
2010-09-15 14:24:50 +04:00
bool for_schema = false ;
2014-05-23 08:06:17 +04:00
if ( ldb_dn_compare_base ( schema_dn , partition - > dn ) = = 0 ) {
2010-09-15 14:24:50 +04:00
for_schema = true ;
}
2016-08-11 05:28:27 +03:00
status = dreplsrv_get_rodc_partial_attribute_set ( service , r ,
& pas ,
& mappings ,
for_schema ) ;
2010-09-15 14:24:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-09-21 02:52:14 +04:00
DEBUG ( 0 , ( __location__ " : Failed to construct RODC partial attribute set : %s \n " , nt_errstr ( status ) ) ) ;
2016-08-04 21:09:21 +03:00
tevent_req_nterror ( req , status ) ;
2010-09-15 14:24:50 +04:00
return ;
}
2015-02-20 07:55:49 +03:00
replica_flags & = ~ DRSUAPI_DRS_WRIT_REP ;
2010-10-01 02:24:58 +04:00
if ( state - > op - > extended_op = = DRSUAPI_EXOP_REPL_SECRET ) {
replica_flags & = ~ DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING ;
2015-02-20 07:55:49 +03:00
} else {
replica_flags | = DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING ;
2010-10-01 02:24:58 +04:00
}
2010-09-15 14:24:50 +04:00
}
2013-01-26 13:53:28 +04:00
if ( state - > op - > extended_op ! = DRSUAPI_EXOP_NONE ) {
/*
* If it ' s an exop never set the ADD_REF even if it ' s in
* repsFrom flags .
*/
replica_flags & = ~ DRSUAPI_DRS_ADD_REF ;
}
2010-09-15 14:24:50 +04:00
2011-09-23 11:33:07 +04:00
/* is this a full resync of all objects? */
if ( state - > op - > options & DRSUAPI_DRS_FULL_SYNC_NOW ) {
ZERO_STRUCT ( highwatermark ) ;
/* clear the FULL_SYNC_NOW option for subsequent
stages of the replication cycle */
state - > op - > options & = ~ DRSUAPI_DRS_FULL_SYNC_NOW ;
state - > op - > options | = DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS ;
replica_flags | = DRSUAPI_DRS_NEVER_SYNCED ;
}
if ( state - > op - > options & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS ) {
uptodateness_vector = NULL ;
}
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 ;
2011-09-23 11:33:07 +04:00
r - > in . req - > req8 . highwatermark = highwatermark ;
2010-01-09 06:29:39 +03:00
r - > in . req - > req8 . uptodateness_vector = uptodateness_vector ;
2010-09-15 14:54:09 +04:00
r - > in . req - > req8 . replica_flags = replica_flags ;
2008-10-17 22:32:36 +04:00
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 ;
2010-09-15 14:24:50 +04:00
r - > in . req - > req8 . partial_attribute_set = pas ;
2008-10-17 22:32:36 +04:00
r - > in . req - > req8 . partial_attribute_set_ex = NULL ;
2016-08-11 05:28:27 +03:00
r - > in . req - > req8 . mapping_ctr . num_mappings = mappings = = NULL ? 0 : mappings - > num_mappings ;
r - > in . req - > req8 . mapping_ctr . mappings = mappings = = NULL ? NULL : mappings - > mappings ;
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 ;
2011-09-23 11:33:07 +04:00
r - > in . req - > req5 . highwatermark = highwatermark ;
2010-01-09 06:29:39 +03:00
r - > in . req - > req5 . uptodateness_vector = uptodateness_vector ;
2010-09-15 14:54:09 +04:00
r - > in . req - > req5 . replica_flags = replica_flags ;
2008-10-17 22:32:36 +04:00
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 ;
2015-02-25 15:19:44 +03:00
enum drsuapi_DsExtendedError extended_ret = DRSUAPI_EXOP_ERR_NONE ;
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 ;
2014-05-23 08:06:17 +04:00
struct ldb_dn * schema_dn = ldb_get_schema_basedn ( service - > samdb ) ;
2010-11-26 03:38:39 +03:00
struct dsdb_schema * schema ;
2010-12-10 04:55:24 +03:00
struct dsdb_schema * working_schema = NULL ;
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 ;
2011-09-23 11:33:07 +04:00
uint32_t dsdb_repl_flags = 0 ;
2016-03-21 05:49:33 +03:00
struct ldb_dn * nc_root = NULL ;
int ret ;
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 ;
2012-12-19 20:31:28 +04:00
rf1 . source_dsa_obj_guid = ctr1 - > source_dsa_guid ;
rf1 . source_dsa_invocation_id = ctr1 - > source_dsa_invocation_id ;
2007-04-23 04:43:47 +04:00
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 ;
2012-12-19 20:31:28 +04:00
rf1 . source_dsa_obj_guid = ctr6 - > source_dsa_guid ;
rf1 . source_dsa_invocation_id = ctr6 - > source_dsa_invocation_id ;
2007-04-23 04:43:47 +04:00
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 ;
}
2016-06-07 07:41:15 +03:00
schema = dsdb_get_schema ( service - > samdb , state ) ;
2010-11-26 03:38:39 +03:00
if ( ! schema ) {
DEBUG ( 0 , ( __location__ " : Schema is not loaded yet! \n " ) ) ;
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2010-11-30 02:38:16 +03:00
2010-12-10 05:17:09 +03:00
/*
* Decide what working schema to use for object conversion .
* We won ' t need a working schema for empty replicas sent .
*/
2014-05-23 08:06:17 +04:00
if ( first_object ) {
bool is_schema = ldb_dn_compare ( partition - > dn , schema_dn ) = = 0 ;
if ( is_schema ) {
/* create working schema to convert objects with */
status = dsdb_repl_make_working_schema ( service - > samdb ,
schema ,
mapping_ctr ,
object_count ,
first_object ,
& drsuapi - > gensec_skey ,
state , & working_schema ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to create working schema: %s \n " ,
win_errstr ( status ) ) ) ;
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2010-11-30 02:38:16 +03:00
}
}
2010-11-26 03:38:39 +03:00
2011-10-06 04:24:28 +04:00
if ( partition - > partial_replica | | partition - > rodc_replica ) {
2011-09-23 11:33:07 +04:00
dsdb_repl_flags | = DSDB_REPL_FLAG_PARTIAL_REPLICA ;
}
if ( state - > op - > options & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS ) {
dsdb_repl_flags | = DSDB_REPL_FLAG_PRIORITISE_INCOMING ;
}
2015-08-19 04:26:41 +03:00
if ( state - > op - > options & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING ) {
dsdb_repl_flags | = DSDB_REPL_FLAG_EXPECT_NO_SECRETS ;
}
2011-09-23 11:33:07 +04:00
2016-03-21 05:49:33 +03:00
if ( state - > op - > extended_op ! = DRSUAPI_EXOP_NONE ) {
ret = dsdb_find_nc_root ( service - > samdb , partition ,
partition - > dn , & nc_root ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 0 , ( __location__ " : Failed to find nc_root for %s \n " ,
ldb_dn_get_linearized ( partition - > dn ) ) ) ;
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
} else {
nc_root = partition - > dn ;
}
2010-11-08 00:04:33 +03:00
status = dsdb_replicated_objects_convert ( service - > samdb ,
2010-12-10 04:55:24 +03:00
working_schema ? working_schema : schema ,
2016-03-21 05:49:33 +03:00
nc_root ,
2010-11-08 00:04:33 +03:00
mapping_ctr ,
object_count ,
first_object ,
linked_attributes_count ,
linked_attributes ,
& rf1 ,
uptodateness_vector ,
& drsuapi - > gensec_skey ,
2011-09-23 11:33:07 +04:00
dsdb_repl_flags ,
2010-11-08 00:04:33 +03:00
state , & objects ) ;
2016-05-04 07:19:09 +03:00
2016-08-05 12:05:37 +03:00
if ( W_ERROR_EQUAL ( status , WERR_DS_DRA_SCHEMA_MISMATCH ) ) {
2016-05-04 07:19:09 +03:00
struct dreplsrv_partition * p ;
2016-08-05 12:05:37 +03:00
if ( state - > retry_started ) {
nt_status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
DEBUG ( 0 , ( " Failed to convert objects after retry: %s/%s \n " ,
win_errstr ( status ) , nt_errstr ( nt_status ) ) ) ;
tevent_req_nterror ( req , nt_status ) ;
return ;
}
2016-05-04 07:19:09 +03:00
/*
* Change info sync or extended operation into a fetch
* of the schema partition , so we get all the schema
* objects we need .
*
* We don ' t want to re - do the remote exop ,
* unless it was REPL_SECRET so we set the
* fallback operation to just be a fetch of
* the relevent partition .
*/
if ( state - > op - > extended_op = = DRSUAPI_EXOP_REPL_SECRET ) {
2016-08-05 12:05:37 +03:00
state - > extended_op_retry = state - > op - > extended_op ;
2016-05-04 07:19:09 +03:00
} else {
2016-08-05 12:05:37 +03:00
state - > extended_op_retry = DRSUAPI_EXOP_NONE ;
2016-05-04 07:19:09 +03:00
}
state - > op - > extended_op = DRSUAPI_EXOP_NONE ;
if ( ldb_dn_compare ( nc_root , partition - > dn ) = = 0 ) {
2016-08-05 12:05:37 +03:00
state - > source_dsa_retry = state - > op - > source_dsa ;
2016-05-04 07:19:09 +03:00
} else {
status = dreplsrv_partition_find_for_nc ( service ,
NULL , NULL ,
ldb_dn_get_linearized ( nc_root ) ,
& p ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 2 , ( " Failed to find requested Naming Context for %s: %s " ,
ldb_dn_get_linearized ( nc_root ) ,
win_errstr ( status ) ) ) ;
nt_status = werror_to_ntstatus ( status ) ;
tevent_req_nterror ( req , nt_status ) ;
return ;
}
status = dreplsrv_partition_source_dsa_by_guid ( p ,
& state - > op - > source_dsa - > repsFrom1 - > source_dsa_obj_guid ,
2016-08-05 12:05:37 +03:00
& state - > source_dsa_retry ) ;
2016-05-04 07:19:09 +03:00
if ( ! W_ERROR_IS_OK ( status ) ) {
struct GUID_txt_buf str ;
DEBUG ( 2 , ( " Failed to find requested source DSA for %s and %s: %s " ,
ldb_dn_get_linearized ( nc_root ) ,
GUID_buf_string ( & state - > op - > source_dsa - > repsFrom1 - > source_dsa_obj_guid , & str ) ,
win_errstr ( status ) ) ) ;
nt_status = werror_to_ntstatus ( status ) ;
tevent_req_nterror ( req , nt_status ) ;
return ;
}
}
2016-07-21 00:08:11 +03:00
/* Find schema naming context to be synchronized first */
2016-05-04 07:19:09 +03:00
status = dreplsrv_partition_find_for_nc ( service ,
NULL , NULL ,
ldb_dn_get_linearized ( schema_dn ) ,
& p ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
DEBUG ( 2 , ( " Failed to find requested Naming Context for schema: %s " ,
win_errstr ( status ) ) ) ;
nt_status = werror_to_ntstatus ( status ) ;
tevent_req_nterror ( req , nt_status ) ;
return ;
}
status = dreplsrv_partition_source_dsa_by_guid ( p ,
& state - > op - > source_dsa - > repsFrom1 - > source_dsa_obj_guid ,
& state - > op - > source_dsa ) ;
if ( ! W_ERROR_IS_OK ( status ) ) {
struct GUID_txt_buf str ;
DEBUG ( 2 , ( " Failed to find requested source DSA for %s and %s: %s " ,
ldb_dn_get_linearized ( schema_dn ) ,
GUID_buf_string ( & state - > op - > source_dsa - > repsFrom1 - > source_dsa_obj_guid , & str ) ,
win_errstr ( status ) ) ) ;
nt_status = werror_to_ntstatus ( status ) ;
tevent_req_nterror ( req , nt_status ) ;
return ;
}
DEBUG ( 4 , ( " Wrong schema when applying reply GetNCChanges, retrying \n " ) ) ;
2016-08-05 12:05:37 +03:00
state - > retry_started = true ;
2016-05-04 07:19:09 +03:00
dreplsrv_op_pull_source_get_changes_trigger ( req ) ;
return ;
} else 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 ;
}
2010-11-07 23:51:11 +03:00
status = dsdb_replicated_objects_commit ( service - > samdb ,
2010-12-10 04:55:24 +03:00
working_schema ,
2010-11-07 23:51:11 +03:00
objects ,
& state - > op - > source_dsa - > notify_uSN ) ;
2009-11-09 13:26:02 +03:00
talloc_free ( objects ) ;
2016-05-04 07:19:09 +03:00
2007-04-23 04:43:47 +04:00
if ( ! W_ERROR_IS_OK ( status ) ) {
2015-12-09 07:05:56 +03:00
/*
* If we failed to apply the records due to a missing
* parent , try again after asking for the parent
* records first . Because we don ' t update the
* highwatermark , we start this part of the cycle
* again .
*/
if ( ( ( state - > op - > options & DRSUAPI_DRS_GET_ANC ) = = 0 )
& & W_ERROR_EQUAL ( status , WERR_DS_DRA_MISSING_PARENT ) ) {
state - > op - > options | = DRSUAPI_DRS_GET_ANC ;
DEBUG ( 4 , ( " Missing parent object when we didn't set the DRSUAPI_DRS_GET_ANC flag, retrying \n " ) ) ;
dreplsrv_op_pull_source_get_changes_trigger ( req ) ;
return ;
} else if ( ( ( state - > op - > options & DRSUAPI_DRS_GET_ANC ) )
& & W_ERROR_EQUAL ( status , WERR_DS_DRA_MISSING_PARENT ) ) {
DEBUG ( 1 , ( " Missing parent object despite setting DRSUAPI_DRS_GET_ANC flag \n " ) ) ;
nt_status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
} else {
nt_status = werror_to_ntstatus ( WERR_BAD_NET_RESP ) ;
}
2009-12-30 19:11:51 +03:00
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 ;
}
2010-12-10 03:55:30 +03:00
2010-08-26 12:19:24 +04:00
if ( state - > op - > extended_op = = DRSUAPI_EXOP_NONE ) {
/* if it applied fine, we need to update the highwatermark */
* state - > op - > source_dsa - > repsFrom1 = rf1 ;
}
2007-04-23 04:43:47 +04:00
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 ;
}
2016-05-04 07:19:09 +03:00
/*
* If we had to divert via doing some other thing , such as
* pulling the schema , then go back and do the original
* operation once we are done .
*/
2016-08-05 12:05:37 +03:00
if ( state - > source_dsa_retry ! = NULL ) {
state - > op - > source_dsa = state - > source_dsa_retry ;
state - > op - > extended_op = state - > extended_op_retry ;
state - > source_dsa_retry = NULL ;
2016-05-04 07:19:09 +03:00
dreplsrv_op_pull_source_get_changes_trigger ( req ) ;
return ;
}
2010-09-30 09:08:48 +04:00
if ( state - > op - > extended_op ! = DRSUAPI_EXOP_NONE | |
state - > op - > service - > am_rodc ) {
/*
we don ' t do the UpdateRefs for extended ops or if we
are a RODC
*/
tevent_req_done ( req ) ;
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-09-30 09:08:48 +04:00
dreplsrv_update_refs_trigger ( req ) ;
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_dns_name ;
2010-03-08 18:23:17 +03:00
struct tevent_req * subreq ;
2009-12-30 19:11:51 +03:00
r = talloc ( state , struct drsuapi_DsReplicaUpdateRefs ) ;
if ( tevent_req_nomem ( r , req ) ) {
return ;
}
2011-08-22 11:30:15 +04:00
ntds_dns_name = samdb_ntds_msdcs_dns_name ( service - > samdb , r , & service - > ntds_guid ) ;
2009-12-30 19:11:51 +03:00
if ( tevent_req_nomem ( ntds_dns_name , req ) ) {
2011-08-22 11:30:15 +04:00
talloc_free ( r ) ;
2009-12-30 19:11:51 +03:00
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-09-15 14:24:50 +04:00
if ( ! service - > 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 ) ) {
2011-08-22 11:30:15 +04:00
talloc_free ( r ) ;
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 ) ) ;
2011-11-27 15:24:23 +04:00
/*
* TODO we are currently not sending the
* DsReplicaUpdateRefs at the correct moment ,
* we do it just after a GetNcChanges which is
* not always correct .
* Especially when another DC is trying to demote
* it will sends us a DsReplicaSync that will trigger a getNcChanges
* this call will succeed but the DsRecplicaUpdateRefs that we send
* just after will not because the DC is in a demote state and
* will reply us a WERR_DS_DRA_BUSY , this error will cause us to
* answer to the DsReplicaSync with a non OK status , the other DC
* will stop the demote due to this error .
* In order to cope with this we will for the moment concider
* a DS_DRA_BUSY not as an error .
* It ' s not ideal but it should not have a too huge impact for
* running production as this error otherwise never happen and
* due to the fact the send a DsReplicaUpdateRefs after each getNcChanges
*/
2011-11-22 02:37:03 +04:00
if ( ! W_ERROR_EQUAL ( r - > out . result , WERR_DS_DRA_BUSY ) ) {
2011-11-27 15:24:23 +04:00
tevent_req_nterror ( req , status ) ;
return ;
}
2009-09-09 11:04:16 +04:00
}
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