s4:dsdb/repl: Improve memory handling in replicated schema code
[sfrench/samba-autobuild/.git] / source4 / libnet / libnet_vampire.c
index f06e4a4cb2e025172647844c2be9ab616c371959..60bfa419f90b544fe68840492f518f66bc1ba80e 100644 (file)
@@ -162,7 +162,7 @@ NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
        settings.server_dn_str = p->dest_dsa->server_dn_str;
        settings.machine_password = generate_random_password(s, 16, 255);
        settings.targetdir = s->targetdir;
-
+       settings.use_ntvfs = true;
        status = provision_bare(s, s->lp_ctx, &settings, &result);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -219,20 +219,12 @@ NTSTATUS libnet_vampire_cb_check_options(void *private_data,
 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
                                               const struct libnet_BecomeDC_StoreChunk *c)
 {
-       struct schema_list {
-               struct schema_list *next, *prev;
-               const struct drsuapi_DsReplicaObjectListItemEx *obj;
-       };
-
        WERROR status;
        struct dsdb_schema_prefixmap *pfm_remote;
        const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
-       struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item;
-       struct dsdb_schema *working_schema;
        struct dsdb_schema *provision_schema;
        uint32_t object_count = 0;
        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;
@@ -240,20 +232,14 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
        struct repsFromTo1 *s_dsa;
        char *tmp_dns_name;
        struct ldb_context *schema_ldb;
+       struct ldb_dn *partition_dn;
        struct ldb_message *msg;
        struct ldb_message_element *prefixMap_el;
        uint32_t i;
-       int ret, pass_no;
+       int ret;
        bool ok;
-       uint64_t seq_num;
-       uint32_t ignore_attids[] = {
-                       DRSUAPI_ATTID_auxiliaryClass,
-                       DRSUAPI_ATTID_mayContain,
-                       DRSUAPI_ATTID_mustContain,
-                       DRSUAPI_ATTID_possSuperiors,
-                       DRSUAPI_ATTID_systemPossSuperiors,
-                       DRSUAPI_ATTID_INVALID
-       };
+       uint64_t seq_num = 0;
+       uint32_t cycle_before_switching;
 
        DEBUG(0,("Analyze and apply schema objects\n"));
 
@@ -288,6 +274,18 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
        default:
                return NT_STATUS_INVALID_PARAMETER;
        }
+       /* We must set these up to ensure the replMetaData is written
+        * correctly, before our NTDS Settings entry is replicated */
+       ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
+       if (!ok) {
+               DEBUG(0,("Failed to set cached ntds invocationId\n"));
+               return NT_STATUS_FOOBAR;
+       }
+       ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
+       if (!ok) {
+               DEBUG(0,("Failed to set cached ntds objectGUID\n"));
+               return NT_STATUS_FOOBAR;
+       }
 
        status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
                                                  s, &pfm_remote, NULL);
@@ -308,6 +306,11 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
        NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
        s_dsa->other_info->dns_name = tmp_dns_name;
 
+       if (s->self_made_schema == NULL) {
+               DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
        schema_ldb = provision_get_schema(s, s->lp_ctx,
                                          c->forest->schema_dn_str,
                                          &s->prefixmap_blob);
@@ -325,95 +328,25 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
                talloc_free(schema_ldb);
        }
 
-       /* create a list of objects yet to be converted */
-       for (cur = first_object; cur; cur = cur->next_object) {
-               schema_list_item = talloc(s, struct schema_list);
-               schema_list_item->obj = cur;
-               DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
-       }
+       cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
+                                                "become dc",
+                                                "schema convert retrial", 1);
 
-       /* resolve objects until all are resolved and in local schema */
-       pass_no = 1;
-       working_schema = provision_schema;
-
-       while (schema_list) {
-               uint32_t converted_obj_count = 0;
-               uint32_t failed_obj_count = 0;
-               TALLOC_CTX *tmp_ctx = talloc_new(s);
-               NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
-
-               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.
-                        */
-                       status = dsdb_convert_object_ex(s->ldb, working_schema, pfm_remote,
-                                                       cur, c->gensec_skey,
-                                                       ignore_attids,
-                                                       0,
-                                                       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));
-
-                               failed_obj_count++;
-                       } 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)));
-                                       failed_obj_count++;
-                               } else {
-                                       DLIST_REMOVE(schema_list, schema_list_item);
-                                       converted_obj_count++;
-                               }
-                       }
-               }
-               talloc_free(tmp_ctx);
-
-               DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
-                        pass_no, failed_obj_count, converted_obj_count, object_count));
-               pass_no++;
-
-               /* 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 NT_STATUS_INTERNAL_ERROR;
-               }
-
-               if (schema_list) {
-                       /* prepare for another cycle */
-                       working_schema = s->self_made_schema;
-
-                       ret = dsdb_setup_sorted_accessors(s->ldb, working_schema);
-                       if (LDB_SUCCESS != ret) {
-                               DEBUG(0,("Failed to create schema-cache indexes!\n"));
-                               return NT_STATUS_INTERNAL_ERROR;
-                       }
-               }
-       };
+       status = dsdb_repl_resolve_working_schema(s->ldb,
+                                                 pfm_remote,
+                                                 cycle_before_switching,
+                                                 provision_schema,
+                                                 s->self_made_schema,
+                                                 object_count,
+                                                 first_object);
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
+                         __location__, win_errstr(status)));
+               return werror_to_ntstatus(status);
+       }
 
        /* free temp objects for 1st conversion phase */
        talloc_unlink(s, provision_schema);
-       TALLOC_FREE(schema_list);
 
        /*
         * attach the schema we just brought over DRS to the ldb,
@@ -429,10 +362,16 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
        s->schema = s->self_made_schema;
        s->self_made_schema = NULL;
 
+       partition_dn = ldb_dn_new(s, s->ldb, c->partition->nc.dn);
+       if (partition_dn == NULL) {
+               DEBUG(0,("Failed to parse partition DN from DRS.\n"));
+               return NT_STATUS_FOOBAR;
+       }
+
        /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
        status = dsdb_replicated_objects_convert(s->ldb,
                                                 s->schema,
-                                                c->partition->nc.dn,
+                                                partition_dn,
                                                 mapping_ctr,
                                                 object_count,
                                                 first_object,
@@ -492,19 +431,6 @@ static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s
        talloc_free(s_dsa);
        talloc_free(schema_objs);
 
-       /* We must set these up to ensure the replMetaData is written
-        * correctly, before our NTDS Settings entry is replicated */
-       ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
-       if (!ok) {
-               DEBUG(0,("Failed to set cached ntds invocationId\n"));
-               return NT_STATUS_FOOBAR;
-       }
-       ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
-       if (!ok) {
-               DEBUG(0,("Failed to set cached ntds objectGUID\n"));
-               return NT_STATUS_FOOBAR;
-       }
-
        s->schema = dsdb_get_schema(s->ldb, s);
        if (!s->schema) {
                DEBUG(0,("Failed to get loaded dsdb_schema\n"));
@@ -527,7 +453,6 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
        struct drsuapi_DsReplicaObjectListItemEx *cur;
        uint32_t nc_linked_attributes_count;
        uint32_t linked_attributes_count;
-       struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
 
        switch (c->ctr_level) {
        case 1:
@@ -537,7 +462,6 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
                first_object                    = c->ctr1->first_object;
                nc_linked_attributes_count      = 0;
                linked_attributes_count         = 0;
-               linked_attributes               = NULL;
                break;
        case 6:
                mapping_ctr                     = &c->ctr6->mapping_ctr;
@@ -546,7 +470,6 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
                first_object                    = c->ctr6->first_object;
                nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
                linked_attributes_count         = c->ctr6->linked_attributes_count;
-               linked_attributes               = c->ctr6->linked_attributes;
                break;
        default:
                return NT_STATUS_INVALID_PARAMETER;
@@ -592,11 +515,6 @@ NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
                s->self_made_schema = dsdb_new_schema(s);
                NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
 
-               s->self_made_schema->base_dn = ldb_dn_new(s->self_made_schema,
-                                               s->ldb,
-                                               c->forest->schema_dn_str);
-               NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema->base_dn);
-
                status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
                if (!W_ERROR_IS_OK(status)) {
                        return werror_to_ntstatus(status);
@@ -642,10 +560,14 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
        const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
        struct dsdb_extended_replicated_objects *objs;
        uint32_t req_replica_flags;
+       uint32_t dsdb_repl_flags = 0;
        struct repsFromTo1 *s_dsa;
        char *tmp_dns_name;
        uint32_t i;
        uint64_t seq_num;
+       bool is_exop = false;
+       struct ldb_dn *partition_dn = NULL;
+       struct ldb_dn *nc_root = NULL;
 
        s_dsa                   = talloc_zero(s, struct repsFromTo1);
        NT_STATUS_HAVE_NO_MEMORY(s_dsa);
@@ -689,12 +611,21 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
                req_replica_flags = 0;
                break;
        case 5:
+               if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
+                       is_exop = true;
+               }
                req_replica_flags = c->req5->replica_flags;
                break;
        case 8:
+               if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
+                       is_exop = true;
+               }
                req_replica_flags = c->req8->replica_flags;
                break;
        case 10:
+               if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
+                       is_exop = true;
+               }
                req_replica_flags = c->req10->replica_flags;
                break;
        default:
@@ -731,13 +662,39 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
        }
        s->total_objects += object_count;
 
-       if (nc_object_count) {
-               DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
-                       c->partition->nc.dn, s->total_objects, nc_object_count,
-                       linked_attributes_count, nc_linked_attributes_count));
+       partition_dn = ldb_dn_new(s, s->ldb, c->partition->nc.dn);
+       if (partition_dn == NULL) {
+               DEBUG(0,("Failed to parse partition DN from DRS.\n"));
+               return NT_STATUS_FOOBAR;
+       }
+
+       if (is_exop) {
+               int ret;
+               if (nc_object_count) {
+                       DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
+                               c->partition->nc.dn, s->total_objects, nc_object_count,
+                               linked_attributes_count, nc_linked_attributes_count));
+               } else {
+                       DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
+                       c->partition->nc.dn, s->total_objects, linked_attributes_count));
+               }
+               ret = dsdb_find_nc_root(s->ldb, s,
+                                       partition_dn, &nc_root);
+               if (ret != LDB_SUCCESS) {
+                       DEBUG(0,(__location__ ": Failed to find nc_root for %s\n",
+                                ldb_dn_get_linearized(partition_dn)));
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
        } else {
-               DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
-               c->partition->nc.dn, s->total_objects, linked_attributes_count));
+               if (nc_object_count) {
+                       DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
+                               c->partition->nc.dn, s->total_objects, nc_object_count,
+                               linked_attributes_count, nc_linked_attributes_count));
+               } else {
+                       DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
+                       c->partition->nc.dn, s->total_objects, linked_attributes_count));
+               }
+               nc_root = partition_dn;
        }
 
 
@@ -747,9 +704,17 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
                return NT_STATUS_INTERNAL_ERROR;
        }
 
+       if (req_replica_flags & DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS) {
+               dsdb_repl_flags |= DSDB_REPL_FLAG_PRIORITISE_INCOMING;
+       }
+
+       if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
+               dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
+       }
+
        status = dsdb_replicated_objects_convert(s->ldb,
                                                 schema,
-                                                c->partition->nc.dn,
+                                                nc_root,
                                                 mapping_ctr,
                                                 object_count,
                                                 first_object,
@@ -758,7 +723,7 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
                                                 s_dsa,
                                                 uptodateness_vector,
                                                 c->gensec_skey,
-                                                0,
+                                                dsdb_repl_flags,
                                                 s, &objs);
        if (!W_ERROR_IS_OK(status)) {
                DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
@@ -816,284 +781,3 @@ NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
-                                             struct ldb_context *ldb,
-                                             const char *server_dn_str,
-                                             const char *netbios_name,
-                                             const char *realm)
-{
-       int ret;
-       struct ldb_message *msg;
-       struct ldb_message_element *el;
-       struct ldb_dn *server_dn;
-       const char *dNSHostName = strlower_talloc(mem_ctx,
-                                                 talloc_asprintf(mem_ctx,
-                                                                 "%s.%s",
-                                                                 netbios_name,
-                                                                 realm));
-       msg = ldb_msg_new(mem_ctx);
-       if (msg == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
-       if (!server_dn) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       msg->dn = server_dn;
-       ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
-       if (ret != LDB_SUCCESS) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       ret = ldb_msg_add_steal_string(msg,
-                                      "dNSHostName",
-                                      talloc_asprintf(el->values, "%s", dNSHostName));
-       if (ret != LDB_SUCCESS) {
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
-       if (ret != LDB_SUCCESS) {
-               DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
-                        ldb_errstring(ldb)));
-               return NT_STATUS_INTERNAL_ERROR;
-       }
-
-       return NT_STATUS_OK;
-}
-
-
-NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 
-                       struct libnet_Vampire *r)
-{
-       struct libnet_JoinDomain *join;
-       struct libnet_Replicate rep;
-       NTSTATUS status;
-
-       const char *account_name;
-       const char *netbios_name;
-       
-       r->out.error_string = NULL;
-
-       join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
-       if (!join) {
-               return NT_STATUS_NO_MEMORY;
-       }
-               
-       if (r->in.netbios_name != NULL) {
-               netbios_name = r->in.netbios_name;
-       } else {
-               netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
-               if (!netbios_name) {
-                       talloc_free(join);
-                       r->out.error_string = NULL;
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
-
-       account_name = talloc_asprintf(join, "%s$", netbios_name);
-       if (!account_name) {
-               talloc_free(join);
-               r->out.error_string = NULL;
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       /* Re-use the domain we are joining as the domain for the user
-        * to be authenticated with, unless they specified
-        * otherwise */
-       cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
-
-       join->in.domain_name    = r->in.domain_name;
-       join->in.account_name   = account_name;
-       join->in.netbios_name   = netbios_name;
-       join->in.level          = LIBNET_JOINDOMAIN_AUTOMATIC;
-       join->in.acct_type      = ACB_WSTRUST;
-       join->in.recreate_account = false;
-       status = libnet_JoinDomain(ctx, join, join);
-       if (!NT_STATUS_IS_OK(status)) {
-               r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
-               talloc_free(join);
-               return status;
-       }
-
-       rep.in.domain_name   = join->out.domain_name;
-       rep.in.netbios_name  = netbios_name;
-       rep.in.targetdir     = r->in.targetdir;
-       rep.in.domain_sid    = join->out.domain_sid;
-       rep.in.realm         = join->out.realm;
-       rep.in.server        = join->out.samr_binding->host;
-       rep.in.join_password = join->out.join_password;
-       rep.in.kvno          = join->out.kvno;
-
-       status = libnet_Replicate(ctx, mem_ctx, &rep);
-
-       r->out.domain_sid   = join->out.domain_sid;
-       r->out.domain_name  = join->out.domain_name;
-       r->out.error_string = rep.out.error_string;
-
-       return status;
-}
-
-
-
-NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
-                         struct libnet_Replicate *r)
-{
-       struct provision_store_self_join_settings *set_secrets;
-       struct libnet_BecomeDC b;
-       struct libnet_vampire_cb_state *s;
-       struct ldb_message *msg;
-       const char *error_string;
-       int ldb_ret;
-       uint32_t i;
-       NTSTATUS status;
-       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-       const char *account_name;
-       const char *netbios_name;
-
-       r->out.error_string = NULL;
-
-       netbios_name = r->in.netbios_name;
-       account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
-       if (!account_name) {
-               talloc_free(tmp_ctx);
-               r->out.error_string = NULL;
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       /* Re-use the domain we are joining as the domain for the user
-        * to be authenticated with, unless they specified
-        * otherwise */
-       cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
-
-       s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
-                                        netbios_name, r->in.domain_name, r->in.realm,
-                                        r->in.targetdir);
-       if (!s) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       talloc_steal(s, tmp_ctx);
-
-       ZERO_STRUCT(b);
-
-       /* Be more robust:
-        * We now know the domain and realm for sure - if they didn't
-        * put one on the command line, use this for the rest of the
-        * join */
-       cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
-       cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
-
-       /* Now set these values into the smb.conf - we probably had
-        * empty or useless defaults here from whatever smb.conf we
-        * started with */
-       lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
-       lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
-
-       b.in.domain_dns_name            = r->in.realm;
-       b.in.domain_netbios_name        = r->in.domain_name;
-       b.in.domain_sid                 = r->in.domain_sid;
-       b.in.source_dsa_address         = r->in.server;
-       b.in.dest_dsa_netbios_name      = netbios_name;
-
-       b.in.callbacks.private_data     = s;
-       b.in.callbacks.check_options    = libnet_vampire_cb_check_options;
-       b.in.callbacks.prepare_db       = libnet_vampire_cb_prepare_db;
-       b.in.callbacks.schema_chunk     = libnet_vampire_cb_schema_chunk;
-       b.in.callbacks.config_chunk     = libnet_vampire_cb_store_chunk;
-       b.in.callbacks.domain_chunk     = libnet_vampire_cb_store_chunk;
-
-       b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
-
-       status = libnet_BecomeDC(ctx, s, &b);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
-               talloc_free(s);
-               return status;
-       }
-
-       msg = ldb_msg_new(s);
-       if (!msg) {
-               printf("ldb_msg_new() failed\n");
-               talloc_free(s);
-               return NT_STATUS_NO_MEMORY;
-       }
-       msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
-       if (!msg->dn) {
-               printf("ldb_msg_new(@ROOTDSE) failed\n");
-               talloc_free(s);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
-       if (ldb_ret != LDB_SUCCESS) {
-               printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
-               talloc_free(s);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       for (i=0; i < msg->num_elements; i++) {
-               msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
-       }
-
-       printf("mark ROOTDSE with isSynchronized=TRUE\n");
-       ldb_ret = ldb_modify(s->ldb, msg);
-       if (ldb_ret != LDB_SUCCESS) {
-               printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
-               talloc_free(s);
-               return NT_STATUS_INTERNAL_DB_ERROR;
-       }
-       /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
-        * the attribute appears on the original DC after replication
-        */
-       status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
-               talloc_free(s);
-               return status;
-       }
-       /* prepare the transaction - this prepares to commit all the changes in
-          the ldb from the whole vampire.  Note that this 
-          triggers the writing of the linked attribute backlinks.
-       */
-       if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
-               printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
-               return NT_STATUS_INTERNAL_DB_ERROR;
-       }
-
-       set_secrets = talloc(s, struct provision_store_self_join_settings);
-       if (!set_secrets) {
-               r->out.error_string = NULL;
-               talloc_free(s);
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       ZERO_STRUCTP(set_secrets);
-       set_secrets->domain_name = r->in.domain_name;
-       set_secrets->realm = r->in.realm;
-       set_secrets->netbios_name = netbios_name;
-       set_secrets->secure_channel_type = SEC_CHAN_BDC;
-       set_secrets->machine_password = r->in.join_password;
-       set_secrets->key_version_number = r->in.kvno;
-       set_secrets->domain_sid = r->in.domain_sid;
-       
-       status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
-       if (!NT_STATUS_IS_OK(status)) {
-               r->out.error_string = talloc_steal(mem_ctx, error_string);
-               talloc_free(s);
-               return status;
-       }
-
-       /* commit the transaction now we know the secrets were written
-        * out properly
-       */
-       if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
-               printf("Failed to commit vampire transaction\n");
-               return NT_STATUS_INTERNAL_DB_ERROR;
-       }
-
-       talloc_free(s);
-
-       return NT_STATUS_OK;
-}