return false;
}
+static WERROR dsdb_verify_repl_meta_data(const struct drsuapi_DsReplicaMetaData *d,
+ const struct GUID *dst_invocation_id,
+ const struct GUID *src_invocation_id,
+ uint64_t src_last_hwm,
+ const * const char *error_hint)
+{
+ bool match;
+
+ *error_hint = NULL;
+
+ match = GUID_all_zero(&d->originating_invocation_id);
+ if (match) {
+ *error_hint = "got zero invocationID";
+ return WERR_DS_SRC_GUID_MISMATCH;
+ }
+
+ // TODO detect restored backup on source or destination dsa
+ // ERROR_DS_DRA_SOURCE_REINSTALLED
+ // ERROR_DS_EPOCH_MISMATCH
+ // ERROR_DS_SRC_GUID_MISMATCH
+ // ERROR_DS_OUT_OF_VERSION_STORE
+ // ERROR_DS_DIFFERENT_REPL_EPOCHS
+ // ERROR_DS_DRS_EXTENSIONS_CHANGED
+ // ERROR_DS_DUPLICATE_ID_FOUND
+ // ERROR_DS_DRA_OUT_SCHEDULE_WINDOW
+ // ERROR_DS_REPL_LIFETIME_EXCEEDED
+ // ERROR_DS_NO_NTDSA_OBJECT
+ // ERROR_DS_DRA_SOURCE_REINSTALLED
+ // ERROR_DS_DRA_INCONSISTENT_DIT
+
+ if (dst_invocation_id != NULL) {
+ match = GUID_equal(&d->originating_invocation_id,
+ dst_invocation_id);
+ if (match) {
+ *error_hint = "got destination(local) invocationID";
+ return WERR_DS_DRA_INCONSISTENT_DIT;
+ }
+ }
+
+ if (src_invocation_id != NULL) {
+ match = GUID_equal(&d->originating_invocation_id,
+ src_invocation_id);
+ if (match && d->originating_usn < src_last_hwm) {
+ *error_hint = "got old source(remote) dsa stamp";
+ return WERR_DS_DRA_SOURCE_REINSTALLED;
+ }
+ }
+
+ return WERR_OK;
+}
+
WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
const struct dsdb_schema *schema,
struct ldb_dn *partition_dn,
struct replPropertyMetaData1 *m;
struct ldb_message_element *e;
uint32_t j;
+ const char *error_hint = NULL;
a = &in->object.attribute_ctr.attributes[i];
d = &in->meta_data_ctr->meta_data[i];
continue;
}
- if (GUID_all_zero(&d->originating_invocation_id)) {
- status = WERR_DS_SRC_GUID_MISMATCH;
- DEBUG(0, ("Refusing replication of object containing invalid zero invocationID on attribute %d of %s: %s\n",
+ status = dsdb_verify_repl_meta_data(d,
+ dst_invocation_id,
+ src_invocation_id,
+ src_last_hwm,
+ &error_hint);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("Refusing replication of object on attribute %d of %s: %s - %s\n",
a->attid,
ldb_dn_get_linearized(msg->dn),
- win_errstr(status)));
+ win_errstr(status),
+ error_hint));
return status;
}
i, ra->attid, win_errstr(status)));
return status;
}
+
+ status = dsdb_verify_repl_meta_data(&la->meta_data,
+ dst_invocation_id,
+ src_invocation_id,
+ src_last_hwm,
+ &error_hint);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0, ("Refusing replication of linked on attribute %d of <GUID=%s>: %s - %s\n",
+ la->attid,
+ GUID_string(out, &la->identifier->guid),,
+ win_errstr(status),
+ error_hint));
+ return status;
+ }
}
out->linked_attributes_count = linked_attributes_count;
}
if (!GUID_equal(&req10->source_dsa_invocation_id, &invocation_id)) {
+ // TODO ERROR_DS_DRA_SOURCE_REINSTALLED ???
/*
* The given highwatermark is only valid relative to the
* specified source_dsa_invocation_id.
ZERO_STRUCT(req10->highwatermark);
}
+ if (req10->highwatermark.highest_usn > higest_local_usn) {
+ return WERR_DS_DRA_SOURCE_REINSTALLED;
+ }
+
getnc_state = b_state->getncchanges_state;
/* see if a previous replication has been abandoned */
const struct drsuapi_DsReplicaCursor *cur =
&udv->cursors[i];
+ match = GUID_equal(&cur->source_dsa_invocation_id,
+ dst_invocation_id);
+ if (match) {
+ dst_highest_usn = cur->highest_usn;
+ continue;
+ }
+
match = GUID_equal(&invocation_id,
&cur->source_dsa_invocation_id);
if (!match) {
getnc_state->max_usn = getnc_state->min_usn;
+ if (getnc_state->min_usn > higest_local_usn) {
+ return WERR_DS_DRA_SOURCE_REINSTALLED;
+ }
+
getnc_state->final_udv = talloc_zero(getnc_state,
struct drsuapi_DsReplicaCursor2CtrEx);
if (getnc_state->final_udv == NULL) {
return werr;
}
+ for (i = 0; i < getnc_state->final_udv->count; i++) {
+ bool match;
+ const struct drsuapi_DsReplicaCursor *cur =
+ &udv->cursors[i];
+
+ match = GUID_equal(&cur->source_dsa_invocation_id,
+ dst_invocation_id);
+ if (!match) {
+ continue;
+ }
+ if (dst_highest_usn < cur->highest_usn) {
+ return ERROR_DS_DUPLICATE_ID_FOUND;
+ }
+ }
+
if (req10->extended_op == DRSUAPI_EXOP_NONE) {
werr = getncchanges_collect_objects(b_state, mem_ctx, req10,
search_dn, extra_filter,