The branch, master has been updated via 01043fc repl_meta_data: Do rename before deleted object cleanup via cb32e25f dsdb/subtree_rename: Rename the base before we rename children via 2d9383e getncchanges: Fill in ctr6.linked_attributes with a pointer to a zero-length array via b8f3252 getncchanges: Use the talloc_stackframe() for tempory memory via 59d6c7c getncchanges: Give the correct error when RID_ALLOC fails on an invalid destination_dsa_guid via dfda458 rpc_server/drsuapi: Return the correct 3 objects for DRSUAPI_EXOP_FSMO_RID_ALLOC from c0b17c3 ctdb:tests: timedout->timed out in 60.nfs.multi.004 test
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 01043fc5f549b61cf3e203cb660e3235d48184c0 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Mar 22 12:07:27 2016 +1300 repl_meta_data: Do rename before deleted object cleanup Following from the lesson of subtree_rename, do the rename first, as this is more likely to fail for some reason Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Wed Jun 1 14:01:36 CEST 2016 on sn-devel-144 commit cb32e25fbecb435b840deddf873aea8d89a3c506 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Mar 15 15:35:21 2016 +1300 dsdb/subtree_rename: Rename the base before we rename children Otherwise, we might rename children to be under a different, conflicting, DN. This would normally be picked up in the transaction rollback, but in replication the transaction is not aborted for this situation Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> commit 2d9383e1d4aef758ec2fdaa57203e9a0dbcbca2f Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 14 11:10:04 2016 +1300 getncchanges: Fill in ctr6.linked_attributes with a pointer to a zero-length array Our newly run repl_exop tests expect this, matching Windows 2012R2 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> commit b8f32528c7939ed47a52e99cfeb03009251bb9d7 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 14 11:09:02 2016 +1300 getncchanges: Use the talloc_stackframe() for tempory memory Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> commit 59d6c7c6749fba003ca4895cfd7c177ca455d81f Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 14 11:06:39 2016 +1300 getncchanges: Give the correct error when RID_ALLOC fails on an invalid destination_dsa_guid This is found by our new tests. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> commit dfda45802c7d30d00eab757497e598732c062e81 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Mar 4 13:12:12 2016 +1300 rpc_server/drsuapi: Return the correct 3 objects for DRSUAPI_EXOP_FSMO_RID_ALLOC Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 17 +- source4/dsdb/samdb/ldb_modules/subtree_rename.c | 80 +++----- source4/rpc_server/drsuapi/getncchanges.c | 243 ++++++++++++++++++++---- 3 files changed, 246 insertions(+), 94 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index f65cc65..c0c8de5 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -3495,14 +3495,6 @@ static int replmd_delete_internals(struct ldb_module *module, struct ldb_request * */ - ret = dsdb_module_modify(module, msg, DSDB_FLAG_OWN_MODULE, req); - if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(ldb, "replmd_delete: Failed to modify object %s in delete - %s", - ldb_dn_get_linearized(old_dn), ldb_errstring(ldb)); - talloc_free(tmp_ctx); - return ret; - } - /* * No matter what has happned with other renames, try again to * get this to be under the deleted DN. @@ -3518,6 +3510,15 @@ static int replmd_delete_internals(struct ldb_module *module, struct ldb_request talloc_free(tmp_ctx); return ret; } + msg->dn = new_dn; + } + + ret = dsdb_module_modify(module, msg, DSDB_FLAG_OWN_MODULE, req); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "replmd_delete: Failed to modify object %s in delete - %s", + ldb_dn_get_linearized(old_dn), ldb_errstring(ldb)); + talloc_free(tmp_ctx); + return ret; } talloc_free(tmp_ctx); diff --git a/source4/dsdb/samdb/ldb_modules/subtree_rename.c b/source4/dsdb/samdb/ldb_modules/subtree_rename.c index b9ecb3f..57020e1 100644 --- a/source4/dsdb/samdb/ldb_modules/subtree_rename.c +++ b/source4/dsdb/samdb/ldb_modules/subtree_rename.c @@ -39,6 +39,7 @@ struct subtree_rename_context { struct ldb_module *module; struct ldb_request *req; + bool base_renamed; }; static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module, @@ -54,48 +55,15 @@ static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module, ac->module = module; ac->req = req; + ac->base_renamed = false; return ac; } -static int subtree_rename_callback(struct ldb_request *req, - struct ldb_reply *ares) -{ - struct ldb_context *ldb; - struct subtree_rename_context *ac; - - ac = talloc_get_type(req->context, struct subtree_rename_context); - ldb = ldb_module_get_ctx(ac->module); - - if (!ares) { - return ldb_module_done(ac->req, NULL, NULL, - LDB_ERR_OPERATIONS_ERROR); - } - - if (ares->type == LDB_REPLY_REFERRAL) { - return ldb_module_send_referral(ac->req, ares->referral); - } - - if (ares->error != LDB_SUCCESS) { - return ldb_module_done(ac->req, ares->controls, - ares->response, ares->error); - } - - if (ares->type != LDB_REPLY_DONE) { - ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); - return ldb_module_done(ac->req, NULL, NULL, - LDB_ERR_OPERATIONS_ERROR); - } - - talloc_free(ares); - return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); -} - static int subtree_rename_search_onelevel_callback(struct ldb_request *req, struct ldb_reply *ares) { struct subtree_rename_context *ac; - struct ldb_request *rename_req; int ret; ac = talloc_get_type(req->context, struct subtree_rename_context); @@ -109,11 +77,26 @@ static int subtree_rename_search_onelevel_callback(struct ldb_request *req, ares->response, ares->error); } + if (ac->base_renamed == false) { + ac->base_renamed = true; + + ret = dsdb_module_rename(ac->module, + ac->req->op.rename.olddn, + ac->req->op.rename.newdn, + DSDB_FLAG_NEXT_MODULE, req); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + } + switch (ares->type) { case LDB_REPLY_ENTRY: { - struct ldb_dn *old_dn = ares->message->dn; - struct ldb_dn *new_dn = ldb_dn_copy(ares, old_dn); + struct ldb_dn *old_dn = NULL; + struct ldb_dn *new_dn = NULL; + + old_dn = ares->message->dn; + new_dn = ldb_dn_copy(ares, old_dn); if (!new_dn) { return ldb_module_oom(ac->module); } @@ -130,7 +113,7 @@ static int subtree_rename_search_onelevel_callback(struct ldb_request *req, } ret = dsdb_module_rename(ac->module, old_dn, new_dn, DSDB_FLAG_OWN_MODULE, req); if (ret != LDB_SUCCESS) { - return ret; + return ldb_module_done(ac->req, NULL, NULL, ret); } talloc_free(ares); @@ -140,22 +123,17 @@ static int subtree_rename_search_onelevel_callback(struct ldb_request *req, case LDB_REPLY_REFERRAL: /* ignore */ break; - case LDB_REPLY_DONE: - - ret = ldb_build_rename_req(&rename_req, ldb_module_get_ctx(ac->module), ac, - ac->req->op.rename.olddn, - ac->req->op.rename.newdn, - ac->req->controls, - ac, subtree_rename_callback, - ac->req); - LDB_REQ_SET_LOCATION(req); - if (ret != LDB_SUCCESS) { - return ret; - } - talloc_free(ares); - return ldb_next_request(ac->module, rename_req); + return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); + default: + { + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + + ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type); + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } } return LDB_SUCCESS; diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 319ef15..6b961bc 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -4,8 +4,9 @@ implement the DSGetNCChanges call Copyright (C) Anatoliy Atanasov 2009 - Copyright (C) Andrew Tridgell 2009 - + Copyright (C) Andrew Tridgell 2009-2010 + Copyright (C) Andrew Bartlett 2010-2016 + 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 the Free Software Foundation; either version 3 of the License, or @@ -742,9 +743,10 @@ static int site_res_cmp_usn_order(struct drsuapi_changed_objects *m1, static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, struct drsuapi_DsGetNCChangesRequest10 *req10, - struct drsuapi_DsGetNCChangesCtr6 *ctr6) + struct drsuapi_DsGetNCChangesCtr6 *ctr6, + struct ldb_dn **rid_manager_dn) { - struct ldb_dn *rid_manager_dn, *req_dn; + struct ldb_dn *req_dn, *ntds_dn = NULL; int ret; struct ldb_context *ldb = b_state->sam_ctx; struct ldb_result *ext_res; @@ -757,8 +759,8 @@ static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, - verify that we are the RID Manager */ - /* work out who is the RID Manager */ - ret = samdb_rid_manager_dn(ldb, mem_ctx, &rid_manager_dn); + /* work out who is the RID Manager, also return to caller */ + ret = samdb_rid_manager_dn(ldb, mem_ctx, rid_manager_dn); if (ret != LDB_SUCCESS) { DEBUG(0, (__location__ ": Failed to find RID Manager object - %s\n", ldb_errstring(ldb))); return WERR_DS_DRA_INTERNAL_ERROR; @@ -766,7 +768,7 @@ static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, req_dn = drs_ObjectIdentifier_to_dn(mem_ctx, ldb, req10->naming_context); if (!ldb_dn_validate(req_dn) || - ldb_dn_compare(req_dn, rid_manager_dn) != 0) { + ldb_dn_compare(req_dn, *rid_manager_dn) != 0) { /* that isn't the RID Manager DN */ DEBUG(0,(__location__ ": RID Alloc request for wrong DN %s\n", drs_ObjectIdentifier_to_string(mem_ctx, req10->naming_context))); @@ -774,8 +776,17 @@ static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, return WERR_OK; } + /* TODO: make sure ntds_dn is a valid nTDSDSA object */ + ret = dsdb_find_dn_by_guid(ldb, mem_ctx, &req10->destination_dsa_guid, 0, &ntds_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0, (__location__ ": Unable to find NTDS object for guid %s - %s\n", + GUID_string(mem_ctx, &req10->destination_dsa_guid), ldb_errstring(ldb))); + ctr6->extended_ret = DRSUAPI_EXOP_ERR_UNKNOWN_CALLER; + return WERR_OK; + } + /* find the DN of the RID Manager */ - ret = samdb_reference_dn_is_our_ntdsa(ldb, rid_manager_dn, "fSMORoleOwner", &is_us); + ret = samdb_reference_dn_is_our_ntdsa(ldb, *rid_manager_dn, "fSMORoleOwner", &is_us); if (ret != LDB_SUCCESS) { DEBUG(0,("Failed to find fSMORoleOwner in RID Manager object\n")); ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER; @@ -802,15 +813,6 @@ static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state, return WERR_DS_DRA_INTERNAL_ERROR; } - /* - * FIXME (kim): this is a temp hack to return just few object, - * but not the whole domain NC. - * We should remove this hack and implement a 'scope' - * building function to return just the set of object - * documented for DRSUAPI_EXOP_FSMO_RID_ALLOC extended_op - */ - ldb_sequence_number(ldb, LDB_SEQ_HIGHEST_SEQ, &req10->highwatermark.highest_usn); - ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID_POOL, exop, &ext_res); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ ": Failed extended allocation RID pool operation - %s\n", @@ -1382,6 +1384,9 @@ getncchanges_map_req8(TALLOC_CTX *mem_ctx, return req10; } +static const char *collect_objects_attrs[] = { "uSNChanged", + "objectGUID" , + NULL }; /** * Collects object for normal replication cycle. @@ -1398,9 +1403,6 @@ static WERROR getncchanges_collect_objects(struct drsuapi_bind_state *b_state, enum ldb_scope scope = LDB_SCOPE_SUBTREE; //const char *extra_filter; struct drsuapi_getncchanges_state *getnc_state = b_state->getncchanges_state; - const char *attrs[] = { "uSNChanged", - "objectGUID" , - NULL }; if (req10->extended_op == DRSUAPI_EXOP_REPL_OBJ || req10->extended_op == DRSUAPI_EXOP_REPL_SECRET) { @@ -1437,7 +1439,8 @@ static WERROR getncchanges_collect_objects(struct drsuapi_bind_state *b_state, DEBUG(2,(__location__ ": getncchanges on %s using filter %s\n", ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter)); ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, getnc_state, search_res, - search_dn, scope, attrs, + search_dn, scope, + collect_objects_attrs, search_filter); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; @@ -1462,10 +1465,156 @@ static WERROR getncchanges_collect_objects_exop(struct drsuapi_bind_state *b_sta return WERR_OK; } - /* TODO: implement extended op specific collection - * of objects. Right now we just normal procedure - * for collecting objects */ - return getncchanges_collect_objects(b_state, mem_ctx, req10, search_dn, extra_filter, search_res); + switch (req10->extended_op) { + case DRSUAPI_EXOP_FSMO_RID_ALLOC: + { + int ret; + struct ldb_dn *ntds_dn = NULL; + struct ldb_dn *server_dn = NULL; + struct ldb_dn *machine_dn = NULL; + struct ldb_dn *rid_set_dn = NULL; + struct ldb_result *search_res2 = NULL; + struct ldb_result *search_res3 = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + /* get RID manager, RID set and server DN (in that order) */ + + /* This first search will get the RID Manager */ + ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, frame, + search_res, + search_dn, LDB_SCOPE_BASE, + collect_objects_attrs, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get RID Manager object %s - %s", + ldb_dn_get_linearized(search_dn), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + if ((*search_res)->count != 1) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get RID Manager object %s - %u objects returned", + ldb_dn_get_linearized(search_dn), + (*search_res)->count)); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + /* Now extend it to the RID set */ + + /* Find the computer account DN for the destination + * dsa GUID specified */ + + ret = dsdb_find_dn_by_guid(b_state->sam_ctx, frame, + &req10->destination_dsa_guid, 0, + &ntds_dn); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Unable to find NTDS object for guid %s - %s\n", + GUID_string(frame, + &req10->destination_dsa_guid), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + server_dn = ldb_dn_get_parent(frame, ntds_dn); + if (!server_dn) { + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + ret = samdb_reference_dn(b_state->sam_ctx, frame, server_dn, + "serverReference", &machine_dn); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to find serverReference in %s - %s", + ldb_dn_get_linearized(server_dn), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + ret = samdb_reference_dn(b_state->sam_ctx, frame, machine_dn, + "rIDSetReferences", &rid_set_dn); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to find rIDSetReferences in %s - %s", + ldb_dn_get_linearized(server_dn), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + + /* This first search will get the RID Manager, now get the RID set */ + ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, frame, + &search_res2, + rid_set_dn, LDB_SCOPE_BASE, + collect_objects_attrs, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get RID Set object %s - %s", + ldb_dn_get_linearized(rid_set_dn), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + if (search_res2->count != 1) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get RID Set object %s - %u objects returned", + ldb_dn_get_linearized(rid_set_dn), + search_res2->count)); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + /* Finally get the server DN */ + ret = drsuapi_search_with_extended_dn(b_state->sam_ctx, frame, + &search_res3, + machine_dn, LDB_SCOPE_BASE, + collect_objects_attrs, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get server object %s - %s", + ldb_dn_get_linearized(server_dn), + ldb_errstring(b_state->sam_ctx))); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + if (search_res3->count != 1) { + DEBUG(1, ("DRSUAPI_EXOP_FSMO_RID_ALLOC: Failed to get server object %s - %u objects returned", + ldb_dn_get_linearized(server_dn), + search_res3->count)); + TALLOC_FREE(frame); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + /* Now extend the original search_res with these answers */ + (*search_res)->count = 3; + + (*search_res)->msgs = talloc_realloc(frame, (*search_res)->msgs, + struct ldb_message *, + (*search_res)->count); + if ((*search_res)->msgs == NULL) { + TALLOC_FREE(frame); + return WERR_NOMEM; + } + + + talloc_steal(mem_ctx, *search_res); + (*search_res)->msgs[1] = + talloc_steal((*search_res)->msgs, search_res2->msgs[0]); + (*search_res)->msgs[2] = + talloc_steal((*search_res)->msgs, search_res3->msgs[0]); + + TALLOC_FREE(frame); + return WERR_OK; + } + default: + /* TODO: implement extended op specific collection + * of objects. Right now we just normal procedure + * for collecting objects */ + return getncchanges_collect_objects(b_state, mem_ctx, req10, search_dn, extra_filter, search_res); + } } /* @@ -1508,6 +1657,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ bool max_wait_reached = false; bool has_get_all_changes = false; struct GUID invocation_id; + static const struct drsuapi_DsReplicaLinkedAttribute no_linked_attr; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; @@ -1519,12 +1669,15 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ *r->out.level_out = 6; /* TODO: linked attributes*/ r->out.ctr->ctr6.linked_attributes_count = 0; - r->out.ctr->ctr6.linked_attributes = NULL; + r->out.ctr->ctr6.linked_attributes = discard_const_p(struct drsuapi_DsReplicaLinkedAttribute, &no_linked_attr); r->out.ctr->ctr6.object_count = 0; r->out.ctr->ctr6.nc_object_count = 0; r->out.ctr->ctr6.more_data = false; r->out.ctr->ctr6.uptodateness_vector = NULL; + r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID(sam_ctx)); + r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx)); + r->out.ctr->ctr6.first_object = NULL; /* a RODC doesn't allow for any replication */ ret = samdb_rodc(sam_ctx, &am_rodc); @@ -1701,9 +1854,11 @@ allowed: case DRSUAPI_EXOP_NONE: break; case DRSUAPI_EXOP_FSMO_RID_ALLOC: - werr = getncchanges_rid_alloc(b_state, mem_ctx, req10, &r->out.ctr->ctr6); + werr = getncchanges_rid_alloc(b_state, mem_ctx, req10, &r->out.ctr->ctr6, &search_dn); W_ERROR_NOT_OK_RETURN(werr); - search_dn = ldb_get_default_basedn(sam_ctx); + if (r->out.ctr->ctr6.extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) { + return WERR_OK; + } break; case DRSUAPI_EXOP_REPL_SECRET: werr = getncchanges_repl_secret(b_state, mem_ctx, req10, @@ -1716,14 +1871,23 @@ allowed: case DRSUAPI_EXOP_FSMO_REQ_ROLE: werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); W_ERROR_NOT_OK_RETURN(werr); + if (r->out.ctr->ctr6.extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) { + return WERR_OK; + } break; case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE: werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); W_ERROR_NOT_OK_RETURN(werr); + if (r->out.ctr->ctr6.extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) { + return WERR_OK; + } break; case DRSUAPI_EXOP_FSMO_REQ_PDC: werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6); W_ERROR_NOT_OK_RETURN(werr); + if (r->out.ctr->ctr6.extended_ret != DRSUAPI_EXOP_ERR_SUCCESS) { -- Samba Shared Repository