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)) {
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;
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"));
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);
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);
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,
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,
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"));
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:
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;
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;
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);
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);
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:
}
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;
}
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,
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)));
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;
-}