summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libnet/libnet_vampire.c174
1 files changed, 117 insertions, 57 deletions
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
index 84fe2944e0..1d5489cc5a 100644
--- a/source4/libnet/libnet_vampire.c
+++ b/source4/libnet/libnet_vampire.c
@@ -59,8 +59,18 @@ struct libnet_vampire_cb_state {
const char *domain_name;
const char *realm;
struct cli_credentials *machine_account;
- struct dsdb_schema *self_made_schema;
+
+ /* Schema loaded from local LDIF files */
struct dsdb_schema *provision_schema;
+
+ /* 1st pass, with some OIDs/attribute names/class names not
+ * converted, because we may not know them yet */
+ struct dsdb_schema *self_made_schema;
+
+ /* 2nd pass, with full ID->OID->name table */
+ struct dsdb_schema *self_corrected_schema;
+
+ /* prefixMap in LDB format, from the remote DRS server */
DATA_BLOB prefixmap_blob;
const struct dsdb_schema *schema;
@@ -192,17 +202,16 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
uint32_t object_count;
struct drsuapi_DsReplicaObjectListItemEx *first_object;
+ const struct drsuapi_DsReplicaObjectListItemEx *cur;
uint32_t linked_attributes_count;
struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
- struct dsdb_extended_replicated_objects *schema_objs_1, *schema_objs_2;
+ struct dsdb_extended_replicated_objects *schema_objs;
struct repsFromTo1 *s_dsa;
char *tmp_dns_name;
struct ldb_context *schema_ldb;
struct ldb_message *msg;
- struct ldb_val prefixMap_val;
struct ldb_message_element *prefixMap_el;
- struct ldb_val schemaInfo_val;
uint32_t i;
int ret;
bool ok;
@@ -269,49 +278,91 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
s->provision_schema->relax_OID_conversions = true;
- /* Now convert the schema elements again, using the schema we just imported */
- status = dsdb_extended_replicated_objects_convert(s->ldb,
- c->partition->nc.dn,
- mapping_ctr,
- object_count,
- first_object,
- linked_attributes_count,
- linked_attributes,
- s_dsa,
- uptodateness_vector,
- c->gensec_skey,
- s, &schema_objs_1);
- if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("Failed to convert objects when trying to import over DRS (1st pass, to create local schema): %s\n", win_errstr(status)));
- return werror_to_ntstatus(status);
+ /* Now convert the schema elements, using the schema we loaded locally */
+ for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
+ struct dsdb_extended_replicated_object object;
+ TALLOC_CTX *tmp_ctx = talloc_new(s);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ /* Convert the objects into LDB messages using the
+ * provision schema, and either the provision or DRS
+ * prefix map - it should not matter, as these are
+ * just schema objects, so the critical parts. At
+ * most we would mix up the mayContain etc for new
+ * schema classes */
+ status = dsdb_convert_object_ex(s->ldb, s->provision_schema,
+ cur, c->gensec_skey,
+ tmp_ctx, &object);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
+ } else {
+ /* Convert the schema from ldb_message format
+ * (OIDs as OID strings) into schema, using
+ * the remote prefixMap */
+ status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, object.msg);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
+ ldb_dn_get_linearized(object.msg->dn),
+ win_errstr(status)));
+ }
+ }
+ talloc_free(tmp_ctx);
+ }
+
+ /* attach the schema we just brought over DRS to the ldb, so we can use it in dsdb_convert_object_ex below */
+ ret = dsdb_set_schema(s->ldb, s->self_made_schema);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,("Failed to attach 1st pass schema from DRS.\n"));
+ return NT_STATUS_FOOBAR;
}
- for (i=0; i < schema_objs_1->num_objects; i++) {
- status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_made_schema, schema_objs_1->objects[i].msg);
+ /* Now convert the schema elements again, using the schema we loaded over DRS */
+ for (i=0, cur = first_object; cur; cur = cur->next_object, i++) {
+ struct dsdb_extended_replicated_object object;
+ TALLOC_CTX *tmp_ctx = talloc_new(s);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ /* Convert the objects into LDB messages using the
+ * self_made_schema, and the DRS prefix map. We now
+ * know the full schema int->OID->name mapping, so we
+ * can get it right this time */
+ status = dsdb_convert_object_ex(s->ldb, s->self_made_schema,
+ cur, c->gensec_skey,
+ tmp_ctx, &object);
if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("Failed to convert object %s into a schema element: %s\n",
- ldb_dn_get_linearized(schema_objs_1->objects[i].msg->dn),
- win_errstr(status)));
- return werror_to_ntstatus(status);
+ DEBUG(0,("ERROR: Failed to convert schema object %s into ldb msg\n", cur->object.identifier->dn));
+ } else {
+ /* Convert the schema from ldb_message format
+ * (OIDs as OID strings) into schema, using
+ * the remote prefixMap, now that we know
+ * names for all the schema elements (from the
+ * first conversion) */
+ status = dsdb_schema_set_el_from_ldb_msg(s->ldb, s->self_corrected_schema, object.msg);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("ERROR: failed to convert object %s into a schema element: %s\n",
+ ldb_dn_get_linearized(object.msg->dn),
+ win_errstr(status)));
+ }
}
+ talloc_free(tmp_ctx);
}
- /* We don't need the first conversion of the schema any more */
- talloc_free(schema_objs_1);
+
+ /* We don't want to use the s->self_made_schema any more */
+ s->self_made_schema = NULL;
/* attach the schema we just brought over DRS to the ldb */
- ret = dsdb_set_schema(s->ldb, s->self_made_schema);
+ ret = dsdb_set_schema(s->ldb, s->self_corrected_schema);
if (ret != LDB_SUCCESS) {
- DEBUG(0,("Failed to attach schema from DRS.\n"));
+ DEBUG(0,("Failed to attach 2nd pass (corrected) schema from DRS.\n"));
return NT_STATUS_FOOBAR;
}
/* we don't want to access the self made schema anymore */
- s->schema = s->self_made_schema;
- s->self_made_schema = NULL;
+ s->schema = s->self_corrected_schema;
+ s->self_corrected_schema = NULL;
- /* Now convert the schema elements again, using the schema we just imported - we do this
- 'just in case' the schema in our LDIF was wrong, but correct enough to read a valid schema */
- status = dsdb_extended_replicated_objects_convert(s->ldb,
+ /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
+ status = dsdb_extended_replicated_objects_convert(s->ldb,
c->partition->nc.dn,
mapping_ctr,
object_count,
@@ -321,54 +372,55 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
s_dsa,
uptodateness_vector,
c->gensec_skey,
- s, &schema_objs_2);
+ s, &schema_objs);
if (!W_ERROR_IS_OK(status)) {
DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
return werror_to_ntstatus(status);
}
if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
- for (i=0; i < schema_objs_2->num_objects; i++) {
+ for (i=0; i < schema_objs->num_objects; i++) {
struct ldb_ldif ldif;
fprintf(stdout, "#\n");
ldif.changetype = LDB_CHANGETYPE_NONE;
- ldif.msg = schema_objs_2->objects[i].msg;
+ ldif.msg = schema_objs->objects[i].msg;
ldb_ldif_write_file(s->ldb, stdout, &ldif);
- NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs_2->objects[i].meta_data);
+ NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
}
}
- status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs_2, &seq_num);
+ status = dsdb_extended_replicated_objects_commit(s->ldb, schema_objs, &seq_num);
if (!W_ERROR_IS_OK(status)) {
DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
return werror_to_ntstatus(status);
}
- msg = ldb_msg_new(schema_objs_2);
+ msg = ldb_msg_new(schema_objs);
NT_STATUS_HAVE_NO_MEMORY(msg);
- msg->dn = schema_objs_2->partition_dn;
-
- status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
- if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
- return werror_to_ntstatus(status);
- }
-
- /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
- ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
+ msg->dn = schema_objs->partition_dn;
+
+ /* We must ensure a prefixMap has been written. Unlike other
+ * attributes (including schemaInfo), it is not replicated in
+ * the normal replication stream. We can use the one from
+ * s->prefixmap_blob because we operate with one, unchanging
+ * prefixMap for this entire operation. */
+ ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
if (ret != LDB_SUCCESS) {
return NT_STATUS_FOOBAR;
}
- prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
+ /* We want to know if a prefixMap was written already, as it
+ * would mean that the above comment was not true, and we have
+ * somehow updated the prefixMap during this transaction */
+ prefixMap_el->flags = LDB_FLAG_MOD_ADD;
ret = ldb_modify(s->ldb, msg);
if (ret != LDB_SUCCESS) {
- DEBUG(0,("Failed to add prefixMap: %s\n", ldb_strerror(ret)));
+ DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
return NT_STATUS_FOOBAR;
}
talloc_free(s_dsa);
- talloc_free(schema_objs_2);
+ talloc_free(schema_objs);
/* We must set these up to ensure the replMetaData is written
* correctly, before our NTDS Settings entry is replicated */
@@ -438,7 +490,7 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
c->partition->nc.dn, object_count, linked_attributes_count));
}
- if (!s->schema) {
+ if (!s->self_made_schema) {
WERROR werr;
struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
/* Put the DRS prefixmap aside for the schema we are
@@ -457,18 +509,26 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
return werror_to_ntstatus(werr);
}
+ /* Set up two manually-constructed schema - the local
+ * schema from the provision will be used to build
+ * one, which will then in turn be used to build the
+ * other. */
s->self_made_schema = dsdb_new_schema(s);
-
NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
+ s->self_corrected_schema = dsdb_new_schema(s);
+ NT_STATUS_HAVE_NO_MEMORY(s->self_corrected_schema);
status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
- s->schema = s->self_made_schema;
+ status = dsdb_load_prefixmap_from_drsuapi(s->self_corrected_schema, mapping_ctr);
+ if (!W_ERROR_IS_OK(status)) {
+ return werror_to_ntstatus(status);
+ }
} else {
- status = dsdb_schema_pfm_contains_drsuapi_pfm(s->schema->prefixmap, mapping_ctr);
+ status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}