WERROR dsdb_replicated_objects_convert(struct ldb_context *ldb, const struct dsdb_schema *schema, const char *partition_dn_str, const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, uint32_t object_count, const struct drsuapi_DsReplicaObjectListItemEx *first_object, uint32_t linked_attributes_count, const struct drsuapi_DsReplicaLinkedAttribute *linked_attributes, const struct repsFromTo1 *source_dsa, const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector, const DATA_BLOB *gensec_skey, uint32_t dsdb_repl_flags, TALLOC_CTX *mem_ctx, struct dsdb_extended_replicated_objects **objects) { WERROR status; struct ldb_dn *partition_dn; struct dsdb_schema_prefixmap *pfm_remote; struct dsdb_extended_replicated_objects *out; const struct drsuapi_DsReplicaObjectListItemEx *cur; uint32_t i; out = talloc_zero(mem_ctx, struct dsdb_extended_replicated_objects); W_ERROR_HAVE_NO_MEMORY(out); out->version = DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION; out->dsdb_repl_flags = dsdb_repl_flags; /* * Ensure schema is kept valid for as long as 'out' * which may contain pointers to it */ schema = talloc_reference(out, schema); W_ERROR_HAVE_NO_MEMORY(schema); partition_dn = ldb_dn_new(out, ldb, partition_dn_str); W_ERROR_HAVE_NO_MEMORY_AND_FREE(partition_dn, out); status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true, out, &pfm_remote, NULL); if (!W_ERROR_IS_OK(status)) { DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s", win_errstr(status))); talloc_free(out); return status; } if (ldb_dn_compare(partition_dn, ldb_get_schema_basedn(ldb)) != 0) { /* * check for schema changes in case * we are not replicating Schema NC */ status = dsdb_schema_info_cmp(schema, mapping_ctr); if (!W_ERROR_IS_OK(status)) { DEBUG(1,("Remote schema has changed while replicating %s\n", partition_dn_str)); talloc_free(out); return status; } } out->partition_dn = partition_dn; out->source_dsa = source_dsa; out->uptodateness_vector= uptodateness_vector; out->num_objects = object_count; out->objects = talloc_array(out, struct dsdb_extended_replicated_object, out->num_objects); W_ERROR_HAVE_NO_MEMORY_AND_FREE(out->objects, out); /* pass the linked attributes down to the repl_meta_data module */ out->linked_attributes_count = linked_attributes_count; out->linked_attributes = linked_attributes; for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { if (i == out->num_objects) { talloc_free(out); return WERR_FOOBAR; } status = dsdb_convert_object_ex(ldb, schema, pfm_remote, cur, gensec_skey, NULL, dsdb_repl_flags, out->objects, &out->objects[i]); if (!W_ERROR_IS_OK(status)) { talloc_free(out); DEBUG(0,("Failed to convert object %s: %s\n", cur->object.identifier->dn, win_errstr(status))); return status; } } if (i != out->num_objects) { talloc_free(out); return WERR_FOOBAR; } /* free pfm_remote, we won't need it anymore */ talloc_free(pfm_remote); *objects = out; return WERR_OK; }
WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb, const char *partition_dn, const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, uint32_t object_count, const struct drsuapi_DsReplicaObjectListItemEx *first_object, uint32_t linked_attributes_count, const struct drsuapi_DsReplicaLinkedAttribute *linked_attributes, const struct repsFromTo1 *source_dsa, const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector, const DATA_BLOB *gensec_skey, TALLOC_CTX *mem_ctx, struct dsdb_extended_replicated_objects **objects) { WERROR status; const struct dsdb_schema *schema; struct dsdb_extended_replicated_objects *out; const struct drsuapi_DsReplicaObjectListItemEx *cur; uint32_t i; schema = dsdb_get_schema(ldb); if (!schema) { return WERR_DS_SCHEMA_NOT_LOADED; } status = dsdb_schema_pfm_contains_drsuapi_pfm(schema->prefixmap, mapping_ctr); W_ERROR_NOT_OK_RETURN(status); out = talloc_zero(mem_ctx, struct dsdb_extended_replicated_objects); W_ERROR_HAVE_NO_MEMORY(out); out->version = DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION; out->partition_dn = ldb_dn_new(out, ldb, partition_dn); W_ERROR_HAVE_NO_MEMORY(out->partition_dn); out->source_dsa = source_dsa; out->uptodateness_vector= uptodateness_vector; out->num_objects = object_count; out->objects = talloc_array(out, struct dsdb_extended_replicated_object, out->num_objects); W_ERROR_HAVE_NO_MEMORY(out->objects); /* pass the linked attributes down to the repl_meta_data module */ out->linked_attributes_count = linked_attributes_count; out->linked_attributes = linked_attributes; for (i=0, cur = first_object; cur; cur = cur->next_object, i++) { if (i == out->num_objects) { return WERR_FOOBAR; } status = dsdb_convert_object_ex(ldb, schema, cur, gensec_skey, out->objects, &out->objects[i]); if (!W_ERROR_IS_OK(status)) { DEBUG(0,("Failed to convert object %s\n", cur->object.identifier->dn)); return status; } } if (i != out->num_objects) { return WERR_FOOBAR; } *objects = out; return WERR_OK; }
WERROR dsdb_repl_resolve_working_schema(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap *pfm_remote, uint32_t cycle_before_switching, struct dsdb_schema *initial_schema, struct dsdb_schema *resulting_schema, uint32_t object_count, const struct drsuapi_DsReplicaObjectListItemEx *first_object) { struct schema_list { struct schema_list *next, *prev; const struct drsuapi_DsReplicaObjectListItemEx *obj; }; struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item; WERROR werr; struct dsdb_schema *working_schema; const struct drsuapi_DsReplicaObjectListItemEx *cur; DATA_BLOB empty_key = data_blob_null; int ret, pass_no; uint32_t ignore_attids[] = { DRSUAPI_ATTID_auxiliaryClass, DRSUAPI_ATTID_mayContain, DRSUAPI_ATTID_mustContain, DRSUAPI_ATTID_possSuperiors, DRSUAPI_ATTID_systemPossSuperiors, DRSUAPI_ATTID_INVALID }; /* create a list of objects yet to be converted */ for (cur = first_object; cur; cur = cur->next_object) { schema_list_item = talloc(mem_ctx, struct schema_list); if (schema_list_item == NULL) { return WERR_NOMEM; } schema_list_item->obj = cur; DLIST_ADD_END(schema_list, schema_list_item, struct schema_list); } /* resolve objects until all are resolved and in local schema */ pass_no = 1; working_schema = initial_schema; while (schema_list) { uint32_t converted_obj_count = 0; uint32_t failed_obj_count = 0; if (resulting_schema != working_schema) { /* * If the selfmade schema is not the schema used to * translate and validate replicated object, * Which means that we are using the bootstrap schema * Then we add attributes and classes that were already * translated to the working schema, the idea is that * we might need to add new attributes and classes * to be able to translate critical replicated objects * and without that we wouldn't be able to translate them */ werr = dsdb_repl_merge_working_schema(ldb, working_schema, resulting_schema); if (!W_ERROR_IS_OK(werr)) { return werr; } } for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) { struct dsdb_extended_replicated_object object; cur = schema_list_item->obj; /* * Save the next item, now we have saved out * the current one, so we can DLIST_REMOVE it * safely */ schema_list_next_item = schema_list_item->next; /* * Convert the objects into LDB messages using the * schema we have so far. It's ok if we fail to convert * an object. We should convert more objects on next pass. */ werr = dsdb_convert_object_ex(ldb, working_schema, pfm_remote, cur, &empty_key, ignore_attids, 0, schema_list_item, &object); if (!W_ERROR_IS_OK(werr)) { DEBUG(4,("debug: Failed to convert schema " "object %s into ldb msg, " "will try during next loop\n", cur->object.identifier->dn)); failed_obj_count++; } else { /* * Convert the schema from ldb_message format * (OIDs as OID strings) into schema, using * the remote prefixMap * * It's not likely, but possible to get the * same object twice and we should keep * the last instance. */ werr = dsdb_schema_set_el_from_ldb_msg_dups(ldb, resulting_schema, object.msg, true); if (!W_ERROR_IS_OK(werr)) { DEBUG(4,("debug: failed to convert " "object %s into a schema element, " "will try during next loop: %s\n", ldb_dn_get_linearized(object.msg->dn), win_errstr(werr))); failed_obj_count++; } else { DEBUG(8,("Converted object %s into a schema element\n", ldb_dn_get_linearized(object.msg->dn))); DLIST_REMOVE(schema_list, schema_list_item); TALLOC_FREE(schema_list_item); converted_obj_count++; } } } DEBUG(4,("Schema load pass %d: converted %d, %d of %d objects left to be converted.\n", pass_no, converted_obj_count, failed_obj_count, object_count)); /* check if we converted any objects in this pass */ if (converted_obj_count == 0) { DEBUG(0,("Can't continue Schema load: " "didn't manage to convert any objects: " "all %d remaining of %d objects " "failed to convert\n", failed_obj_count, object_count)); return WERR_INTERNAL_ERROR; } /* * Don't try to load the schema if there is missing object * _and_ we are on the first pass as some critical objects * might be missing. */ if (failed_obj_count == 0 || pass_no > cycle_before_switching) { /* prepare for another cycle */ working_schema = resulting_schema; ret = dsdb_setup_sorted_accessors(ldb, working_schema); if (LDB_SUCCESS != ret) { DEBUG(0,("Failed to create schema-cache indexes!\n")); return WERR_INTERNAL_ERROR; } } pass_no++; } return WERR_OK; }