The Samba-Bugzilla – Attachment 12824 Details for
Bug 12398
Replication with DRSUAPI_DRS_CRITICAL_ONLY and DRSUAPI_DRS_GET_ANC results in WERR_DS_DRA_MISSING_PARENT
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Possible patch for master (as a first step)
tmp.diff.txt (text/plain), 8.27 KB, created by
Stefan Metzmacher
on 2017-01-12 09:03:59 UTC
(
hide
)
Description:
Possible patch for master (as a first step)
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2017-01-12 09:03:59 UTC
Size:
8.27 KB
patch
obsolete
>From 8d156d0885e31ad6b80c1979efdfa7cfee075215 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 29 Nov 2016 11:12:22 +0100 >Subject: [PATCH] s4:rpc_server/drsuapi: implement DRSUAPI_DRS_GET_ANC more > correctly > >The most important case is the combination of >DRSUAPI_DRS_CRITICAL_ONLY and DRSUAPI_DRS_GET_ANC. > >With DRSUAPI_DRS_GET_ANC we need to make sure all ancestors >included even if they're not marked with >isCriticalSystemObject=TRUE. > >I guess we still don't behave exactly as Windows, but it's much >better than before and fixes the initial replication if >someone moved the the administrator account to an OU. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12398 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source4/rpc_server/drsuapi/getncchanges.c | 212 +++++++++++++++++++++++++++--- > 1 file changed, 194 insertions(+), 18 deletions(-) > >diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c >index 705c8cf..03a6639 100644 >--- a/source4/rpc_server/drsuapi/getncchanges.c >+++ b/source4/rpc_server/drsuapi/getncchanges.c >@@ -37,6 +37,9 @@ > #include "lib/util/tsort.h" > #include "auth/session.h" > #include "dsdb/common/util.h" >+#include "lib/dbwrap/dbwrap.h" >+#include "lib/dbwrap/dbwrap_rbt.h" >+#include "librpc/gen_ndr/ndr_misc.h" > > /* state of a partially completed getncchanges call */ > struct drsuapi_getncchanges_state { >@@ -724,16 +727,6 @@ struct drsuapi_changed_objects { > }; > > /* >- sort the objects we send by tree order >- */ >-static int site_res_cmp_anc_order(struct drsuapi_changed_objects *m1, >- struct drsuapi_changed_objects *m2, >- struct drsuapi_getncchanges_state *getnc_state) >-{ >- return ldb_dn_compare(m2->dn, m1->dn); >-} >- >-/* > sort the objects we send first by uSNChanged > */ > static int site_res_cmp_usn_order(struct drsuapi_changed_objects *m1, >@@ -1684,6 +1677,68 @@ static WERROR getncchanges_collect_objects_exop(struct drsuapi_bind_state *b_sta > } > } > >+static WERROR dcesrv_drsuapi_anc_cache_add(struct db_context *anc_cache, >+ const struct GUID *guid) >+{ >+ enum ndr_err_code ndr_err; >+ uint8_t guid_buf[16] = { 0, }; >+ DATA_BLOB b = { >+ .data = guid_buf, >+ .length = sizeof(guid_buf), >+ }; >+ TDB_DATA key = { >+ .dptr = b.data, >+ .dsize = b.length, >+ }; >+ TDB_DATA val = { >+ .dptr = NULL, >+ .dsize = 0, >+ }; >+ NTSTATUS status; >+ >+ ndr_err = ndr_push_struct_into_fixed_blob(&b, guid, >+ (ndr_push_flags_fn_t)ndr_push_GUID); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ return WERR_DS_DRA_INTERNAL_ERROR; >+ } >+ >+ status = dbwrap_store(anc_cache, key, val, TDB_REPLACE); >+ if (!NT_STATUS_IS_OK(status)) { >+ return WERR_DS_DRA_INTERNAL_ERROR; >+ } >+ >+ return WERR_OK; >+} >+ >+static WERROR dcesrv_drsuapi_anc_cache_exists(struct db_context *anc_cache, >+ const struct GUID *guid) >+{ >+ enum ndr_err_code ndr_err; >+ uint8_t guid_buf[16] = { 0, }; >+ DATA_BLOB b = { >+ .data = guid_buf, >+ .length = sizeof(guid_buf), >+ }; >+ TDB_DATA key = { >+ .dptr = b.data, >+ .dsize = b.length, >+ }; >+ bool exists; >+ >+ ndr_err = ndr_push_struct_into_fixed_blob(&b, guid, >+ (ndr_push_flags_fn_t)ndr_push_GUID); >+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { >+ return WERR_DS_DRA_INTERNAL_ERROR; >+ } >+ >+ exists = dbwrap_exists(anc_cache, key); >+ if (!exists) { >+ return WERR_OBJECT_NOT_FOUND; >+ } >+ >+ return WERR_OBJECT_NAME_EXISTS; >+} >+ > /* > drsuapi_DsGetNCChanges > >@@ -1728,6 +1783,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ > struct dsdb_schema_prefixmap *pfm_remote = NULL; > bool full = true; > uint32_t *local_pas = NULL; >+ struct db_context *anc_cache = NULL; > > DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); > b_state = h->data; >@@ -2075,11 +2131,6 @@ allowed: > /* RID_ALLOC returns 3 objects in a fixed order */ > if (req10->extended_op == DRSUAPI_EXOP_FSMO_RID_ALLOC) { > /* Do nothing */ >- } else if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) { >- LDB_TYPESAFE_QSORT(changes, >- getnc_state->num_records, >- getnc_state, >- site_res_cmp_anc_order); > } else { > LDB_TYPESAFE_QSORT(changes, > getnc_state->num_records, >@@ -2191,6 +2242,15 @@ allowed: > uint32_t_ptr_cmp); > } > >+ if (req10->extended_op != DRSUAPI_EXOP_NONE) { >+ /* Do nothing */ >+ } else if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) { >+ anc_cache = db_open_rbt(mem_ctx); >+ if (anc_cache == NULL) { >+ return WERR_NOT_ENOUGH_MEMORY; >+ } >+ } >+ > for (i=getnc_state->num_processed; > i<getnc_state->num_records && > !null_scope && >@@ -2198,6 +2258,7 @@ allowed: > && !max_wait_reached; > i++) { > int uSN; >+ struct drsuapi_DsReplicaObjectListItemEx *new_objs = NULL; > struct drsuapi_DsReplicaObjectListItemEx *obj; > struct ldb_message *msg; > static const char * const msg_attrs[] = { >@@ -2209,6 +2270,7 @@ allowed: > NULL }; > struct ldb_result *msg_res; > struct ldb_dn *msg_dn; >+ const struct GUID *next_anc_guid = NULL; > > obj = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx); > W_ERROR_HAVE_NO_MEMORY(obj); >@@ -2289,10 +2351,122 @@ allowed: > continue; > } > >- r->out.ctr->ctr6.object_count++; >+ new_objs = obj; > >- *currentObject = obj; >- currentObject = &obj->next_object; >+ if (anc_cache != NULL) { >+ werr = dcesrv_drsuapi_anc_cache_add(anc_cache, >+ &getnc_state->guids[i]); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ next_anc_guid = obj->parent_object_guid; >+ } >+ >+ while (next_anc_guid != NULL) { >+ struct drsuapi_DsReplicaObjectListItemEx *anc_obj = NULL; >+ struct ldb_message *anc_msg = NULL; >+ struct ldb_result *anc_res = NULL; >+ struct ldb_dn *anc_dn = NULL; >+ >+ werr = dcesrv_drsuapi_anc_cache_exists(anc_cache, >+ next_anc_guid); >+ if (W_ERROR_EQUAL(werr, WERR_OBJECT_NAME_EXISTS)) { >+ /* >+ * We don't need to send it twice. >+ */ >+ break; >+ } >+ if (W_ERROR_IS_OK(werr)) { >+ return WERR_INTERNAL_ERROR; >+ } >+ if (!W_ERROR_EQUAL(werr, WERR_OBJECT_NOT_FOUND)) { >+ return werr; >+ } >+ werr = WERR_OK; >+ >+ anc_obj = talloc_zero(mem_ctx, >+ struct drsuapi_DsReplicaObjectListItemEx); >+ if (anc_obj == NULL) { >+ return WERR_NOT_ENOUGH_MEMORY; >+ } >+ >+ anc_dn = ldb_dn_new_fmt(anc_obj, sam_ctx, "<GUID=%s>", >+ GUID_string(anc_obj, next_anc_guid)); >+ if (anc_dn == NULL) { >+ return WERR_NOT_ENOUGH_MEMORY; >+ } >+ >+ ret = drsuapi_search_with_extended_dn(sam_ctx, anc_obj, >+ &anc_res, anc_dn, >+ LDB_SCOPE_BASE, >+ msg_attrs, NULL); >+ if (ret != LDB_SUCCESS) { >+ const char *anc_str = NULL; >+ const char *obj_str = NULL; >+ >+ anc_str = ldb_dn_get_extended_linearized(anc_obj, >+ anc_dn, >+ 1); >+ obj_str = ldb_dn_get_extended_linearized(anc_obj, >+ msg->dn, >+ 1), >+ >+ DBG_ERR("getncchanges: failed to fetch ANC " >+ "DN %s for DN %s - %s\n", >+ anc_str, obj_str, >+ ldb_errstring(sam_ctx)); >+ return WERR_DS_DRA_INCONSISTENT_DIT; >+ } >+ >+ anc_msg = anc_res->msgs[0]; >+ >+ werr = get_nc_changes_build_object(anc_obj, anc_msg, >+ sam_ctx, >+ getnc_state->ncRoot_dn, >+ getnc_state->is_schema_nc, >+ schema, &session_key, >+ getnc_state->min_usn, >+ req10->replica_flags, >+ req10->partial_attribute_set, >+ req10->uptodateness_vector, >+ req10->extended_op, >+ true, /* ??? max_wait_reached */ >+ local_pas); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ anc_msg = NULL; >+ TALLOC_FREE(anc_res); >+ TALLOC_FREE(anc_dn); >+ >+ werr = dcesrv_drsuapi_anc_cache_add(anc_cache, >+ next_anc_guid); >+ if (!W_ERROR_IS_OK(werr)) { >+ return werr; >+ } >+ >+ /* >+ * prepend it to the list >+ */ >+ anc_obj->next_object = new_objs; >+ new_objs = anc_obj; >+ >+ /* >+ * We may need to resolve more... >+ */ >+ next_anc_guid = anc_obj->parent_object_guid; >+ } >+ >+ *currentObject = new_objs; >+ while (new_objs != NULL) { >+ r->out.ctr->ctr6.object_count += 1; >+ if (new_objs->next_object == NULL) { >+ currentObject = &new_objs->next_object; >+ } >+ new_objs = new_objs->next_object; >+ } > > DEBUG(8,(__location__ ": replicating object %s\n", ldb_dn_get_linearized(msg->dn))); > >@@ -2435,6 +2609,8 @@ allowed: > } > } > >+ TALLOC_FREE(anc_cache); >+ > if (!r->out.ctr->ctr6.more_data) { > talloc_steal(mem_ctx, getnc_state->la_list); > >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 12398
:
12612
| 12824 |
12911