From beba977213daf5ff4004954e03481e970d1749cb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 19 Dec 2009 12:24:09 +1100 Subject: s4-dsdb: ask for REVEAL_INTERNALS in getncchanges We need this for the linked attribute meta data --- source4/rpc_server/drsuapi/drsutil.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/drsutil.c b/source4/rpc_server/drsuapi/drsutil.c index a62f911537..43692ac5b4 100644 --- a/source4/rpc_server/drsuapi/drsutil.c +++ b/source4/rpc_server/drsuapi/drsutil.c @@ -86,6 +86,11 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb, return ret; } + ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + if (sort_attrib) { struct ldb_server_sort_control **sort_control; sort_control = talloc_array(req, struct ldb_server_sort_control *, 2); -- cgit From fde3f6437369365af7bb72bcff1666bf0ce98948 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 19 Dec 2009 12:25:09 +1100 Subject: s4-drs: added linked attribute replication to getncchanges --- source4/rpc_server/drsuapi/getncchanges.c | 218 ++++++++++++++++++++++++++++-- 1 file changed, 203 insertions(+), 15 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 488ecd129e..e07aca6e65 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -30,6 +30,32 @@ #include "../libcli/drsuapi/drsuapi.h" #include "libcli/security/security.h" +/* + build a DsReplicaObjectIdentifier from a ldb msg + */ +static struct drsuapi_DsReplicaObjectIdentifier *get_object_identifier(TALLOC_CTX *mem_ctx, + struct ldb_message *msg) +{ + struct drsuapi_DsReplicaObjectIdentifier *identifier; + struct dom_sid *sid; + + identifier = talloc(mem_ctx, struct drsuapi_DsReplicaObjectIdentifier); + if (identifier == NULL) { + return NULL; + } + + identifier->dn = ldb_dn_alloc_linearized(identifier, msg->dn); + identifier->guid = samdb_result_guid(msg, "objectGUID"); + + sid = samdb_result_dom_sid(identifier, msg, "objectSid"); + if (sid) { + identifier->sid = *sid; + } else { + ZERO_STRUCT(identifier->sid); + } + return identifier; +} + /* drsuapi_DsGetNCChanges for one object */ @@ -44,9 +70,7 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem { const struct ldb_val *md_value; int i, n; - struct ldb_dn *obj_dn; struct replPropertyMetaDataBlob md; - struct dom_sid *sid; uint32_t rid = 0; enum ndr_err_code ndr_err; uint32_t *attids; @@ -104,17 +128,11 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem obj->meta_data_ctr = talloc(obj, struct drsuapi_DsReplicaMetaDataCtr); attids = talloc_array(obj, uint32_t, md.ctr.ctr1.count); - obj->object.identifier = talloc(obj, struct drsuapi_DsReplicaObjectIdentifier); - obj_dn = ldb_msg_find_attr_as_dn(sam_ctx, obj, msg, "distinguishedName"); - obj->object.identifier->dn = ldb_dn_get_linearized(obj_dn); - obj->object.identifier->guid = samdb_result_guid(msg, "objectGUID"); - sid = samdb_result_dom_sid(obj, msg, "objectSid"); - if (sid) { - dom_sid_split_rid(NULL, sid, NULL, &rid); - obj->object.identifier->sid = *sid; - } else { - ZERO_STRUCT(obj->object.identifier->sid); + obj->object.identifier = get_object_identifier(obj, msg); + if (obj->object.identifier == NULL) { + return WERR_NOMEM; } + dom_sid_split_rid(NULL, &obj->object.identifier->sid, NULL, &rid); obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count); for (n=i=0; iidentifier = get_object_identifier(*la_list, msg); + W_ERROR_HAVE_NO_MEMORY(la->identifier); + + active = ldb_dn_get_extended_component(dsdb_dn->dn, "DELETED")?false:true; + + la->attid = sa->attributeID_id; + la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0; + + status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->originating_add_time, "RMD_ADDTIME"); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + status = dsdb_get_extended_dn_uint32(dsdb_dn->dn, &la->meta_data.version, "RMD_VERSION"); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->meta_data.originating_change_time, "RMD_CHANGETIME"); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &la->meta_data.originating_invocation_id, "RMD_INVOCID"); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &la->meta_data.originating_usn, "RMD_ORIGINATING_USN"); + if (!NT_STATUS_IS_OK(status)) { + return ntstatus_to_werror(status); + } + + /* we need a message_element with just one value in it */ + v = data_blob_string_const(dsdb_dn_get_linearized(*la_list, dsdb_dn)); + + val_el = *el; + val_el.values = &v; + val_el.num_values = 1; + + werr = sa->syntax->ldb_to_drsuapi(sam_ctx, schema, sa, &val_el, *la_list, &drs); + W_ERROR_NOT_OK_RETURN(werr); + + if (drs.value_ctr.num_values != 1) { + DEBUG(1,(__location__ ": Failed to build DRS blob for linked attribute %s in %s\n", + el->name, ldb_dn_get_linearized(msg->dn))); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + la->value.blob = drs.value_ctr.values[0].blob; + + (*la_count)++; + return WERR_OK; +} + + +/* + add linked attributes from an object to the list of linked + attributes in a getncchanges request + */ +static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, + TALLOC_CTX *mem_ctx, + struct ldb_dn *ncRoot_dn, + struct dsdb_schema *schema, + uint64_t highest_usn, + uint32_t replica_flags, + struct ldb_message *msg, + struct drsuapi_DsReplicaLinkedAttribute **la_list, + uint32_t *la_count) +{ + int i; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + + for (i=0; inum_elements; i++) { + struct ldb_message_element *el = &msg->elements[i]; + const struct dsdb_attribute *sa; + int j; + + sa = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + + if (!sa || sa->linkID == 0 || (sa->linkID & 1)) { + /* we only want forward links */ + continue; + } + + for (j=0; jnum_values; j++) { + struct dsdb_dn *dsdb_dn; + uint64_t local_usn; + NTSTATUS status; + WERROR werr; + + dsdb_dn = dsdb_dn_parse(tmp_ctx, sam_ctx, &el->values[j], sa->syntax->ldap_oid); + if (dsdb_dn == NULL) { + DEBUG(1,(__location__ ": Failed to parse DN for %s in %s\n", + el->name, ldb_dn_get_linearized(msg->dn))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + + status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &local_usn, "RMD_LOCAL_USN"); + if (!NT_STATUS_IS_OK(status)) { + /* this can happen for attributes + given to us with old style meta + data */ + continue; + } + + if (local_usn < highest_usn) { + continue; + } + + werr = get_nc_changes_add_la(mem_ctx, sam_ctx, schema, sa, msg, + el, dsdb_dn, la_list, la_count); + if (!W_ERROR_IS_OK(werr)) { + talloc_free(tmp_ctx); + return werr; + } + } + } + + talloc_free(tmp_ctx); + return WERR_OK; +} + /* load replUpToDateVector from a DN */ @@ -494,15 +660,24 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ r->out.ctr->ctr6.first_object = NULL; currentObject = &r->out.ctr->ctr6.first_object; +#if 0 + /* use this to force single objects at a time, which is useful + * for working out what object is giving problems + */ + req8->max_object_count = 1; +#endif + for(i=getnc_state->num_sent; isite_res->count && (r->out.ctr->ctr6.object_count < req8->max_object_count); i++) { int uSN; struct drsuapi_DsReplicaObjectListItemEx *obj; + struct ldb_message *msg = getnc_state->site_res->msgs[i]; + obj = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx); - uSN = ldb_msg_find_attr_as_int(getnc_state->site_res->msgs[i], "uSNChanged", -1); + uSN = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); if (uSN > r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn) { r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn = uSN; } @@ -510,7 +685,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ getnc_state->highest_usn = uSN; } - werr = get_nc_changes_build_object(obj, getnc_state->site_res->msgs[i], + werr = get_nc_changes_build_object(obj, msg, b_state->sam_ctx, getnc_state->ncRoot_dn, schema, &session_key, getnc_state->min_usn, req8->replica_flags); @@ -518,9 +693,20 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ return werr; } + werr = get_nc_changes_add_links(b_state->sam_ctx, mem_ctx, + getnc_state->ncRoot_dn, + schema, getnc_state->min_usn, + req8->replica_flags, + msg, + &r->out.ctr->ctr6.linked_attributes, + &r->out.ctr->ctr6.linked_attributes_count); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + if (obj->meta_data_ctr == NULL) { DEBUG(0,(__location__ ": getncchanges skipping send of object %s\n", - ldb_dn_get_linearized(getnc_state->site_res->msgs[i]->dn))); + ldb_dn_get_linearized(msg->dn))); /* no attributes to send */ talloc_free(obj); continue; @@ -530,6 +716,8 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ *currentObject = obj; currentObject = &obj->next_object; + + DEBUG(8,(__location__ ": replicating object %s\n", ldb_dn_get_linearized(msg->dn))); } getnc_state->num_sent += r->out.ctr->ctr6.object_count; -- cgit From 225bcfa4e6ad7efa7596e0324fd3faf1c195f820 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 19 Dec 2009 20:59:04 +1100 Subject: s4-drs: handle mixtures of old and new style links in getncchanges We need to send non-upgraded links using the old format --- source4/rpc_server/drsuapi/getncchanges.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index e07aca6e65..b3808206cb 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -136,6 +136,7 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count); for (n=i=0; iattributeID_id) continue; + sa = dsdb_attribute_by_attributeID_id(schema, md.ctr.ctr1.array[i].attid); + if (sa->linkID) { + struct ldb_message_element *el; + el = ldb_msg_find_element(msg, sa->lDAPDisplayName); + if (el && el->num_values && dsdb_dn_is_upgraded_link_val(&el->values[0])) { + /* don't send upgraded links inline */ + continue; + } + } + obj->meta_data_ctr->meta_data[n].originating_change_time = md.ctr.ctr1.array[i].originating_change_time; obj->meta_data_ctr->meta_data[n].version = md.ctr.ctr1.array[i].version; obj->meta_data_ctr->meta_data[n].originating_invocation_id = md.ctr.ctr1.array[i].originating_invocation_id; @@ -326,6 +337,12 @@ static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, continue; } + if (el->num_values && !dsdb_dn_is_upgraded_link_val(&el->values[0])) { + /* its an old style link, it will have been + * sent in the main replication data */ + continue; + } + for (j=0; jnum_values; j++) { struct dsdb_dn *dsdb_dn; uint64_t local_usn; -- cgit From bcc952d19dd5e1731386ccd1d7150e4bc306c60c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 20 Dec 2009 00:12:35 +1100 Subject: s4-drs: some useful debugging options for getncchanges Added two debugging parametric options drs:max object sync = drs:extra filter = --- source4/rpc_server/drsuapi/getncchanges.c | 53 ++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index b3808206cb..84dc21d1b7 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -25,6 +25,7 @@ #include "dsdb/samdb/samdb.h" #include "param/param.h" #include "librpc/gen_ndr/ndr_drsblobs.h" +#include "librpc/gen_ndr/ndr_drsuapi.h" #include "rpc_server/drsuapi/dcesrv_drsuapi.h" #include "rpc_server/dcerpc_server_proto.h" #include "../libcli/drsuapi/drsuapi.h" @@ -324,6 +325,7 @@ static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, { int i; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + uint64_t uSNChanged = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); for (i=0; inum_elements; i++) { struct ldb_message_element *el = &msg->elements[i]; @@ -365,6 +367,13 @@ static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, continue; } + if (local_usn > uSNChanged) { + DEBUG(1,(__location__ ": uSNChanged less than RMD_LOCAL_USN for %s on %s\n", + el->name, ldb_dn_get_linearized(msg->dn))); + talloc_free(tmp_ctx); + return WERR_DS_DRA_INTERNAL_ERROR; + } + if (local_usn < highest_usn) { continue; } @@ -472,6 +481,7 @@ struct drsuapi_getncchanges_state { struct ldb_dn *ncRoot_dn; uint64_t min_usn; uint64_t highest_usn; + struct ldb_dn *last_dn; }; /* @@ -506,6 +516,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ struct drsuapi_getncchanges_state *getnc_state; struct drsuapi_DsGetNCChangesRequest8 *req8; uint32_t options; + uint32_t max_objects; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; @@ -572,9 +583,10 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ if (getnc_state) { struct ldb_dn *new_dn = ldb_dn_new(getnc_state, b_state->sam_ctx, ncRoot->dn); if (ldb_dn_compare(new_dn, getnc_state->ncRoot_dn) != 0) { - DEBUG(0,(__location__ ": DsGetNCChanges 2nd replication on different DN %s %s\n", + DEBUG(0,(__location__ ": DsGetNCChanges 2nd replication on different DN %s %s (last_dn %s)\n", ldb_dn_get_linearized(new_dn), - ldb_dn_get_linearized(getnc_state->ncRoot_dn))); + ldb_dn_get_linearized(getnc_state->ncRoot_dn), + ldb_dn_get_linearized(getnc_state->last_dn))); talloc_free(getnc_state); getnc_state = NULL; } @@ -616,6 +628,9 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ if (getnc_state->site_res == NULL) { char* search_filter; enum ldb_scope scope = LDB_SCOPE_SUBTREE; + const char *extra_filter; + + extra_filter = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "object filter"); getnc_state->min_usn = req8->highwatermark.highest_usn; @@ -624,6 +639,10 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ "(uSNChanged>=%llu)", (unsigned long long)(getnc_state->min_usn+1)); + if (extra_filter) { + search_filter = talloc_asprintf(mem_ctx, "(&%s(%s))", search_filter, extra_filter); + } + if (req8->replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_CRITICAL_ONLY) { search_filter = talloc_asprintf(mem_ctx, "(&%s(isCriticalSystemObject=TRUE))", @@ -677,16 +696,17 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ r->out.ctr->ctr6.first_object = NULL; currentObject = &r->out.ctr->ctr6.first_object; -#if 0 /* use this to force single objects at a time, which is useful * for working out what object is giving problems */ - req8->max_object_count = 1; -#endif + max_objects = lp_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max object sync", 1000); + if (req8->max_object_count < max_objects) { + max_objects = req8->max_object_count; + } for(i=getnc_state->num_sent; isite_res->count && - (r->out.ctr->ctr6.object_count < req8->max_object_count); + (r->out.ctr->ctr6.object_count < max_objects); i++) { int uSN; struct drsuapi_DsReplicaObjectListItemEx *obj; @@ -734,6 +754,9 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ *currentObject = obj; currentObject = &obj->next_object; + talloc_free(getnc_state->last_dn); + getnc_state->last_dn = ldb_dn_copy(getnc_state, msg->dn); + DEBUG(8,(__location__ ": replicating object %s\n", ldb_dn_get_linearized(msg->dn))); } @@ -785,11 +808,19 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ b_state->getncchanges_state = NULL; } - DEBUG(2,("DsGetNCChanges with uSNChanged >= %llu flags 0x%08x on %s gave %u objects (done %d/%d)\n", - (unsigned long long)(req8->highwatermark.highest_usn+1), - req8->replica_flags, - ncRoot->dn, r->out.ctr->ctr6.object_count, - i, r->out.ctr->ctr6.more_data?getnc_state->site_res->count:i)); + DEBUG(r->out.ctr->ctr6.more_data?2:1, + ("DsGetNCChanges with uSNChanged >= %llu flags 0x%08x on %s gave %u objects (done %d/%d la=%d)\n", + (unsigned long long)(req8->highwatermark.highest_usn+1), + req8->replica_flags, + ncRoot->dn, r->out.ctr->ctr6.object_count, + i, r->out.ctr->ctr6.more_data?getnc_state->site_res->count:i, + r->out.ctr->ctr6.linked_attributes_count)); + +#if 0 + if (!r->out.ctr->ctr6.more_data) { + NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsGetNCChanges, NDR_BOTH, r); + } +#endif return WERR_OK; } -- cgit From 340d7e807b2be7fb5c50a0cddf9378aa9bd929bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 20 Dec 2009 10:27:03 +1100 Subject: s4-drs: fixed the UDV return in getncchanges We should overwrite an existing entry if found --- source4/rpc_server/drsuapi/getncchanges.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 84dc21d1b7..3189381d8e 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -447,6 +447,7 @@ static WERROR get_nc_changes_udv(struct ldb_context *sam_ctx, NTTIME now; time_t t = time(NULL); struct replUpToDateVectorBlob ouv; + int i; werr = load_udv(sam_ctx, udv, ncRoot_dn, &ouv); if (!W_ERROR_IS_OK(werr)) { @@ -459,13 +460,24 @@ static WERROR get_nc_changes_udv(struct ldb_context *sam_ctx, unix_to_nt_time(&now, t); tmp_cursor->last_sync_success = now; - udv->count = ouv.ctr.ctr2.count + 1; + udv->count = ouv.ctr.ctr2.count; udv->cursors = talloc_steal(udv, ouv.ctr.ctr2.cursors); - udv->cursors = talloc_realloc(udv, udv->cursors, struct drsuapi_DsReplicaCursor2, udv->count); - if (!udv->cursors) { - return WERR_DS_DRA_INTERNAL_ERROR; + + for (i=0; icount; i++) { + if (GUID_equal(&tmp_cursor->source_dsa_invocation_id, + &udv->cursors[i].source_dsa_invocation_id)) { + udv->cursors[i] = *tmp_cursor; + break; + } + } + if (i == udv->count) { + udv->cursors = talloc_realloc(udv, udv->cursors, struct drsuapi_DsReplicaCursor2, udv->count+1); + if (!udv->cursors) { + return WERR_DS_DRA_INTERNAL_ERROR; + } + udv->cursors[udv->count] = *tmp_cursor; + udv->count++; } - udv->cursors[udv->count - 1] = *tmp_cursor; qsort(udv->cursors, udv->count, sizeof(struct drsuapi_DsReplicaCursor2), -- cgit From cb00e443a3c63889f39132e5e954eb0b95804e74 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:05:50 +1100 Subject: s4-drs: give a reason when an AddEntry commit fails Pair-Programmed-With: Andrew Bartlett --- source4/rpc_server/drsuapi/addentry.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/addentry.c b/source4/rpc_server/drsuapi/addentry.c index 89b664d691..ac94daa6a6 100644 --- a/source4/rpc_server/drsuapi/addentry.c +++ b/source4/rpc_server/drsuapi/addentry.c @@ -199,7 +199,8 @@ WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX ret = ldb_transaction_commit(b_state->sam_ctx); if (ret != LDB_SUCCESS) { - DEBUG(0,(__location__ ": DsAddEntry commit failed\n")); + DEBUG(0,(__location__ ": DsAddEntry commit failed: %s\n", + ldb_errstring(b_state->sam_ctx))); return WERR_DS_DRA_INTERNAL_ERROR; } -- cgit From 701148bbe9de178b068d200d086b1c6ba1045c97 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:06:56 +1100 Subject: s4-drs: we are doing the sorting for getncchanges in the app code now the sorting is quite delicate, and easier to get right in the getncchanges code Pair-Programmed-With: Andrew Bartlett --- source4/rpc_server/drsuapi/dcesrv_drsuapi.h | 1 - source4/rpc_server/drsuapi/drsutil.c | 21 --------------------- 2 files changed, 22 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h index e42d9569e7..3a64ef5c9c 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.h +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.h @@ -57,7 +57,6 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb, struct ldb_dn *basedn, enum ldb_scope scope, const char * const *attrs, - const char *sort_attrib, const char *filter); WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, diff --git a/source4/rpc_server/drsuapi/drsutil.c b/source4/rpc_server/drsuapi/drsutil.c index 43692ac5b4..0a8a576d60 100644 --- a/source4/rpc_server/drsuapi/drsutil.c +++ b/source4/rpc_server/drsuapi/drsutil.c @@ -47,7 +47,6 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb, struct ldb_dn *basedn, enum ldb_scope scope, const char * const *attrs, - const char *sort_attrib, const char *filter) { int ret; @@ -91,26 +90,6 @@ int drsuapi_search_with_extended_dn(struct ldb_context *ldb, return ret; } - if (sort_attrib) { - struct ldb_server_sort_control **sort_control; - sort_control = talloc_array(req, struct ldb_server_sort_control *, 2); - if (sort_control == NULL) { - talloc_free(tmp_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - sort_control[0] = talloc(req, struct ldb_server_sort_control); - sort_control[0]->attributeName = sort_attrib; - sort_control[0]->orderingRule = NULL; - sort_control[0]->reverse = 0; - sort_control[1] = NULL; - - ret = ldb_request_add_control(req, LDB_CONTROL_SERVER_SORT_OID, true, sort_control); - if (ret != LDB_SUCCESS) { - return ret; - } - } - - ret = ldb_request(ldb, req); if (ret == LDB_SUCCESS) { ret = ldb_wait(req->handle, LDB_WAIT_ALL); -- cgit From 7653f56bd48859dce2481ef1e7ee885b25bfc709 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:10:41 +1100 Subject: s4-drs: implemented sorting functions based on replication flags I think we probably have more work to do on the sort order, but this brings us a bit closer. --- source4/rpc_server/drsuapi/getncchanges.c | 45 +++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 3189381d8e..b48bc68293 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -486,6 +486,35 @@ static WERROR get_nc_changes_udv(struct ldb_context *sam_ctx, return WERR_OK; } +/* + sort the objects we send by tree order + */ +static int site_res_cmp_parent_order(const struct ldb_message **m1, const struct ldb_message **m2) +{ + return ldb_dn_compare((*m2)->dn, (*m1)->dn); +} + +/* + sort the objects we send first by uSNChanged + */ +static int site_res_cmp_usn_order(const struct ldb_message **m1, const struct ldb_message **m2) +{ + unsigned usnchanged1, usnchanged2; + unsigned cn1, cn2; + cn1 = ldb_dn_get_comp_num((*m1)->dn); + cn2 = ldb_dn_get_comp_num((*m2)->dn); + if (cn1 != cn2) { + return cn1 > cn2 ? 1 : -1; + } + usnchanged1 = ldb_msg_find_attr_as_uint(*m1, "uSNChanged", 0); + usnchanged2 = ldb_msg_find_attr_as_uint(*m2, "uSNChanged", 0); + if (usnchanged1 == usnchanged2) { + return 0; + } + return usnchanged1 > usnchanged2 ? 1 : -1; +} + + /* state of a partially completed getncchanges call */ struct drsuapi_getncchanges_state { struct ldb_result *site_res; @@ -665,15 +694,27 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ scope = LDB_SCOPE_BASE; } - DEBUG(6,(__location__ ": getncchanges on %s using filter %s\n", + DEBUG(1,(__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, &getnc_state->site_res, getnc_state->ncRoot_dn, scope, attrs, - "uSNChanged", search_filter); if (ret != LDB_SUCCESS) { return WERR_DS_DRA_INTERNAL_ERROR; } + + if (req8->replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS) { + qsort(getnc_state->site_res->msgs, + getnc_state->site_res->count, + sizeof(getnc_state->site_res->msgs[0]), + (comparison_fn_t)site_res_cmp_parent_order); + } else { + qsort(getnc_state->site_res->msgs, + getnc_state->site_res->count, + sizeof(getnc_state->site_res->msgs[0]), + (comparison_fn_t)site_res_cmp_usn_order); + } + } /* Prefix mapping */ -- cgit From 5bf257fa9ba32ec31886be34edff35eb41f885d4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:12:19 +1100 Subject: s4-drs: use the extended linearized form for DRS replication We were sending zero GUIDs. Not good! Pair-Programmed-With: Andrew Bartlett --- source4/rpc_server/drsuapi/getncchanges.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index b48bc68293..18c9242a10 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -239,7 +239,6 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, const struct dsdb_schema *schema, const struct dsdb_attribute *sa, struct ldb_message *msg, - struct ldb_message_element *el, struct dsdb_dn *dsdb_dn, struct drsuapi_DsReplicaLinkedAttribute **la_list, uint32_t *la_count) @@ -287,9 +286,9 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, } /* we need a message_element with just one value in it */ - v = data_blob_string_const(dsdb_dn_get_linearized(*la_list, dsdb_dn)); + v = data_blob_string_const(dsdb_dn_get_extended_linearized(*la_list, dsdb_dn, 1)); - val_el = *el; + val_el.name = sa->lDAPDisplayName; val_el.values = &v; val_el.num_values = 1; @@ -298,7 +297,7 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, if (drs.value_ctr.num_values != 1) { DEBUG(1,(__location__ ": Failed to build DRS blob for linked attribute %s in %s\n", - el->name, ldb_dn_get_linearized(msg->dn))); + sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn))); return WERR_DS_DRA_INTERNAL_ERROR; } @@ -379,7 +378,7 @@ static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, } werr = get_nc_changes_add_la(mem_ctx, sam_ctx, schema, sa, msg, - el, dsdb_dn, la_list, la_count); + dsdb_dn, la_list, la_count); if (!W_ERROR_IS_OK(werr)) { talloc_free(tmp_ctx); return werr; -- cgit From ff6dd4a67fe74349a8e54766f2f0f91ded06a742 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:13:59 +1100 Subject: s4-drs: send all linked attributes at the end of a replication cycle This ensures that a link is not seen before the object it points to --- source4/rpc_server/drsuapi/getncchanges.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 18c9242a10..8ff5de5dc0 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -522,6 +522,8 @@ struct drsuapi_getncchanges_state { uint64_t min_usn; uint64_t highest_usn; struct ldb_dn *last_dn; + struct drsuapi_DsReplicaLinkedAttribute *la_list; + uint32_t la_count; }; /* @@ -782,13 +784,13 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ return werr; } - werr = get_nc_changes_add_links(b_state->sam_ctx, mem_ctx, + werr = get_nc_changes_add_links(b_state->sam_ctx, getnc_state, getnc_state->ncRoot_dn, schema, getnc_state->min_usn, req8->replica_flags, msg, - &r->out.ctr->ctr6.linked_attributes, - &r->out.ctr->ctr6.linked_attributes_count); + &getnc_state->la_list, + &getnc_state->la_count); if (!W_ERROR_IS_OK(werr)) { return werr; } @@ -842,6 +844,8 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ if (i < getnc_state->site_res->count) { r->out.ctr->ctr6.more_data = true; } else { + r->out.ctr->ctr6.linked_attributes_count = getnc_state->la_count; + r->out.ctr->ctr6.linked_attributes = talloc_steal(mem_ctx, getnc_state->la_list); r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx); r->out.ctr->ctr6.uptodateness_vector->version = 2; r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0; -- cgit From 0c2afdd5a95c247eb8e7ce7d721ac61fb111220c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 21 Dec 2009 21:16:35 +1100 Subject: s4-drs: update highwatermark after successfully encoding the object --- source4/rpc_server/drsuapi/getncchanges.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 8ff5de5dc0..cf4b637c0c 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -768,14 +768,6 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ obj = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx); - uSN = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); - if (uSN > r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn) { - r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn = uSN; - } - if (uSN > getnc_state->highest_usn) { - getnc_state->highest_usn = uSN; - } - werr = get_nc_changes_build_object(obj, msg, b_state->sam_ctx, getnc_state->ncRoot_dn, schema, &session_key, getnc_state->min_usn, @@ -795,6 +787,14 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ return werr; } + uSN = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1); + if (uSN > r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn) { + r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn = uSN; + } + if (uSN > getnc_state->highest_usn) { + getnc_state->highest_usn = uSN; + } + if (obj->meta_data_ctr == NULL) { DEBUG(0,(__location__ ": getncchanges skipping send of object %s\n", ldb_dn_get_linearized(msg->dn))); -- cgit From a81dd03917b5ae74b3b5515cbb37cbafaecc5c28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 28 Dec 2009 14:11:37 +1100 Subject: s4-drs: set flag to indicate that we do support linked attributes --- source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index 3d92880162..6a6bc8be7e 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -159,10 +159,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2; - if (0 /*domain.behavior_version == 2*/) { - /* TODO: find out how this is really triggered! */ - b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; - } + b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD; b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND; -- cgit From 38160deac4d6f4a8ae22fcedcf55114bc0372f31 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 28 Dec 2009 17:19:29 +1100 Subject: s4-drs: use dsdb linked attribute parse functions This makes the code considerably more readable --- source4/rpc_server/drsuapi/getncchanges.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index cf4b637c0c..dc4483c8f8 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -246,10 +246,7 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaLinkedAttribute *la; bool active; NTSTATUS status; - struct ldb_message_element val_el; - struct ldb_val v; WERROR werr; - struct drsuapi_DsReplicaAttribute drs; (*la_list) = talloc_realloc(mem_ctx, *la_list, struct drsuapi_DsReplicaLinkedAttribute, (*la_count)+1); W_ERROR_HAVE_NO_MEMORY(*la_list); @@ -285,24 +282,9 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, return ntstatus_to_werror(status); } - /* we need a message_element with just one value in it */ - v = data_blob_string_const(dsdb_dn_get_extended_linearized(*la_list, dsdb_dn, 1)); - - val_el.name = sa->lDAPDisplayName; - val_el.values = &v; - val_el.num_values = 1; - - werr = sa->syntax->ldb_to_drsuapi(sam_ctx, schema, sa, &val_el, *la_list, &drs); + werr = dsdb_dn_la_to_blob(sam_ctx, sa, schema, *la_list, dsdb_dn, &la->value.blob); W_ERROR_NOT_OK_RETURN(werr); - if (drs.value_ctr.num_values != 1) { - DEBUG(1,(__location__ ": Failed to build DRS blob for linked attribute %s in %s\n", - sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn))); - return WERR_DS_DRA_INTERNAL_ERROR; - } - - la->value.blob = drs.value_ctr.values[0].blob; - (*la_count)++; return WERR_OK; } -- cgit From e3cf818c277f90df37cab8a2ecbf93e6a92d8cb2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 28 Dec 2009 17:22:40 +1100 Subject: s4-drs: sort linked attributes See MS-DRSR section 4.1.10.5.17 for a description of the sorting comparison function --- source4/rpc_server/drsuapi/getncchanges.c | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index dc4483c8f8..a41d116b6a 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -467,6 +467,74 @@ static WERROR get_nc_changes_udv(struct ldb_context *sam_ctx, return WERR_OK; } + +/* comparison function for linked attributes - see CompareLinks() in + * MS-DRSR section 4.1.10.5.17 */ +static int linked_attribute_compare(const struct drsuapi_DsReplicaLinkedAttribute *la1, + const struct drsuapi_DsReplicaLinkedAttribute *la2, + struct ldb_context *sam_ctx) +{ + int c; + WERROR werr; + TALLOC_CTX *tmp_ctx; + const struct dsdb_schema *schema; + const struct dsdb_attribute *schema_attrib; + struct dsdb_dn *dn1, *dn2; + struct GUID guid1, guid2; + NTSTATUS status; + + c = GUID_compare(&la1->identifier->guid, + &la2->identifier->guid); + if (c != 0) return c; + + if (la1->attid != la2->attid) { + return la1->attid < la2->attid? -1:1; + } + + if ((la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) != + (la2->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) { + return (la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)? 1:-1; + } + + /* we need to get the target GUIDs to compare */ + tmp_ctx = talloc_new(sam_ctx); + + schema = dsdb_get_schema(sam_ctx); + schema_attrib = dsdb_attribute_by_attributeID_id(schema, la1->attid); + + werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la1->value.blob, &dn1); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,(__location__ ": Bad la1 blob in sort\n")); + talloc_free(tmp_ctx); + return 0; + } + + werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la2->value.blob, &dn2); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,(__location__ ": Bad la2 blob in sort\n")); + talloc_free(tmp_ctx); + return 0; + } + + status = dsdb_get_extended_dn_guid(dn1->dn, &guid1, "GUID"); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,(__location__ ": Bad la1 guid in sort\n")); + talloc_free(tmp_ctx); + return 0; + } + status = dsdb_get_extended_dn_guid(dn2->dn, &guid2, "GUID"); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,(__location__ ": Bad la2 guid in sort\n")); + talloc_free(tmp_ctx); + return 0; + } + + talloc_free(tmp_ctx); + + return GUID_compare(&guid1, &guid2); +} + + /* sort the objects we send by tree order */ @@ -828,6 +896,11 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ } else { r->out.ctr->ctr6.linked_attributes_count = getnc_state->la_count; r->out.ctr->ctr6.linked_attributes = talloc_steal(mem_ctx, getnc_state->la_list); + + ldb_qsort(r->out.ctr->ctr6.linked_attributes, r->out.ctr->ctr6.linked_attributes_count, + sizeof(r->out.ctr->ctr6.linked_attributes[0]), + b_state->sam_ctx, (ldb_qsort_cmp_fn_t)linked_attribute_compare); + r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx); r->out.ctr->ctr6.uptodateness_vector->version = 2; r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0; -- cgit From 00b39c70f57882a453a8d2e6b0f1f37fd39a2d2a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Jan 2010 08:14:52 +1100 Subject: s4-dsdb: switched to using RMD_FLAGS instead of DELETED in extended DNs This allows for more flags in the future --- source4/rpc_server/drsuapi/getncchanges.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index a41d116b6a..437dc87ae8 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -256,7 +256,7 @@ static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx, la->identifier = get_object_identifier(*la_list, msg); W_ERROR_HAVE_NO_MEMORY(la->identifier); - active = ldb_dn_get_extended_component(dsdb_dn->dn, "DELETED")?false:true; + active = (dsdb_dn_rmd_flags(dsdb_dn->dn) & DSDB_RMD_FLAG_DELETED) == 0; la->attid = sa->attributeID_id; la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0; -- cgit From e809b721e9d1a750c3c1bf48882532714af69e5f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Jan 2010 16:51:30 +1100 Subject: s4-drs: don't give an error on repsTo delete if add is also specified w2k8-r2 in dcpromo asks for a delete+add during its initial join. --- source4/rpc_server/drsuapi/updaterefs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/drsuapi/updaterefs.c b/source4/rpc_server/drsuapi/updaterefs.c index 6e2efed4f9..b1e3d6c352 100644 --- a/source4/rpc_server/drsuapi/updaterefs.c +++ b/source4/rpc_server/drsuapi/updaterefs.c @@ -105,7 +105,9 @@ static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return werr; } - if (!found && !(options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK)) { + if (!found && + !(options & DRSUAPI_DS_REPLICA_UPDATE_GETCHG_CHECK) && + !(options & DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE)) { return WERR_DS_DRA_REF_NOT_FOUND; } -- cgit