libnet_BecomeDC() tests
- Copyright (C) Stefan (metze) Metzmacher 2006
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "system/time.h"
#include "auth/auth.h"
-#include "lib/db_wrap.h"
+#include "lib/ldb_wrap.h"
+
+struct test_become_dc_state {
+ struct libnet_context *ctx;
+ struct torture_context *tctx;
+ const char *netbios_name;
+ struct test_join *tj;
+ struct cli_credentials *machine_account;
+ struct dsdb_schema *self_made_schema;
+ const struct dsdb_schema *schema;
+
+ struct ldb_context *ldb;
+
+ struct {
+ uint32_t object_count;
+ struct drsuapi_DsReplicaObjectListItemEx *first_object;
+ struct drsuapi_DsReplicaObjectListItemEx *last_object;
+ } schema_part;
+
+ struct {
+ const char *samdb_ldb;
+ const char *domaindn_ldb;
+ const char *configdn_ldb;
+ const char *schemadn_ldb;
+ const char *secrets_ldb;
+ const char *templates_ldb;
+ const char *secrets_keytab;
+ const char *dns_keytab;
+ } path;
+};
+
+static NTSTATUS test_become_dc_check_options(void *private_data,
+ const struct libnet_BecomeDC_CheckOptions *o)
+{
+ struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
+
+ DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
+ s->netbios_name,
+ o->domain->netbios_name, o->domain->dns_name));
+
+ DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
+ o->source_dsa->dns_name, o->source_dsa->site_name));
+
+ DEBUG(0,("Options:crossRef behavior_version[%u]\n"
+ "\tschema object_version[%u]\n"
+ "\tdomain behavior_version[%u]\n"
+ "\tdomain w2k3_update_revision[%u]\n",
+ o->forest->crossref_behavior_version,
+ o->forest->schema_object_version,
+ o->domain->behavior_version,
+ o->domain->w2k3_update_revision));
+
+ return NT_STATUS_OK;
+}
+
+#ifndef PROVISION_PYTHON
#include "lib/appweb/ejs/ejs.h"
#include "lib/appweb/ejs/ejsInternal.h"
#include "scripting/ejs/smbcalls.h"
return ejs_error;
}
-#define TORTURE_NETBIOS_NAME "smbtorturedc"
-#define TORTURE_SAMDB_LDB "test_samdb.ldb"
-
-struct test_become_dc_state {
- struct libnet_context *ctx;
- struct test_join *tj;
- struct cli_credentials *machine_account;
- struct dsdb_schema *schema;
-
- struct ldb_context *ldb;
-
- struct {
- struct drsuapi_DsReplicaObjectListItemEx *first_object;
- struct drsuapi_DsReplicaObjectListItemEx *last_object;
- } schema_part;
-};
-
-static NTSTATUS test_become_dc_check_options(void *private_data,
- const struct libnet_BecomeDC_CheckOptions *o)
-{
- DEBUG(0,("Become DC of Domain[%s]/[%s]\n",
- o->domain->netbios_name, o->domain->dns_name));
-
- DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
- o->source_dsa->dns_name, o->source_dsa->site_name));
-
- DEBUG(0,("Options:crossRef behavior_version[%u]\n"
- "\tschema object_version[%u]\n"
- "\tdomain behavior_version[%u]\n"
- "\tdomain w2k3_update_revision[%u]\n",
- o->forest->crossref_behavior_version,
- o->forest->schema_object_version,
- o->domain->behavior_version,
- o->domain->w2k3_update_revision));
-
- return NT_STATUS_OK;
-}
-
static NTSTATUS test_become_dc_prepare_db(void *private_data,
const struct libnet_BecomeDC_PrepareDB *p)
{
struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
char *ejs;
int ret;
+ bool ok;
DEBUG(0,("New Server[%s] in Site[%s]\n",
p->dest_dsa->dns_name, p->dest_dsa->site_name));
GUID_string(s, &p->dest_dsa->ntds_guid),
GUID_string(s, &p->dest_dsa->invocation_id)));
- DEBUG(0,("Schema Partition[%s]\n",
- p->forest->schema_dn_str));
+ DEBUG(0,("Pathes under PRIVATEDIR[%s]\n"
+ "SAMDB[%s] SECRETS[%s] KEYTAB[%s]\n",
+ lp_private_dir(s->tctx->lp_ctx),
+ s->path.samdb_ldb,
+ s->path.secrets_ldb,
+ s->path.secrets_keytab));
- DEBUG(0,("Config Partition[%s]\n",
- p->forest->config_dn_str));
+ DEBUG(0,("Schema Partition[%s => %s]\n",
+ p->forest->schema_dn_str, s->path.schemadn_ldb));
- DEBUG(0,("Domain Partition[%s]\n",
- p->domain->dn_str));
+ DEBUG(0,("Config Partition[%s => %s]\n",
+ p->forest->config_dn_str, s->path.configdn_ldb));
+
+ DEBUG(0,("Domain Partition[%s => %s]\n",
+ p->domain->dn_str, s->path.domaindn_ldb));
ejs = talloc_asprintf(s,
"libinclude(\"base.js\");\n"
"var subobj = provision_guess();\n"
"subobj.ROOTDN = \"%s\";\n"
"subobj.DOMAINDN = \"%s\";\n"
- "subobj.DOMAINDN_LDB = \"test_domain.ldb\";\n"
+ "subobj.DOMAINDN_LDB = \"%s\";\n"
"subobj.CONFIGDN = \"%s\";\n"
- "subobj.CONFIGDN_LDB = \"test_config.ldb\";\n"
+ "subobj.CONFIGDN_LDB = \"%s\";\n"
"subobj.SCHEMADN = \"%s\";\n"
- "subobj.SCHEMADN_LDB = \"test_schema.ldb\";\n"
+ "subobj.SCHEMADN_LDB = \"%s\";\n"
"subobj.HOSTNAME = \"%s\";\n"
- "subobj.DNSNAME = \"%s\";\n"
+ "subobj.REALM = \"%s\";\n"
+ "subobj.DOMAIN = \"%s\";\n"
"subobj.DEFAULTSITE = \"%s\";\n"
"\n"
- "modules_list = new Array(\"rootdse\",\n"
- " \"kludge_acl\",\n"
- " \"paged_results\",\n"
- " \"server_sort\",\n"
- " \"extended_dn\",\n"
- " \"asq\",\n"
- " //\"samldb\",should only handle originating changes...\n"
- " \"password_hash\",\n"
- " \"operational\",\n"
- " \"objectclass\",\n"
- " \"rdn_name\",\n"
- " \"partition\");\n"
- "subobj.MODULES_LIST = join(\",\", modules_list);\n"
- "subobj.DOMAINDN_MOD = \"objectguid\";\n"
- "subobj.CONFIGDN_MOD = \"objectguid\";\n"
- "subobj.SCHEMADN_MOD = \"objectguid\";\n"
+ "subobj.KRBTGTPASS = \"_NOT_USED_\";\n"
+ "subobj.MACHINEPASS = \"%s\";\n"
+ "subobj.ADMINPASS = \"_NOT_USED_\";\n"
"\n"
"var paths = provision_default_paths(subobj);\n"
"paths.samdb = \"%s\";\n"
+ "paths.secrets = \"%s\";\n"
+ "paths.templates = \"%s\";\n"
+ "paths.keytab = \"%s\";\n"
+ "paths.dns_keytab = \"%s\";\n"
"\n"
"var system_session = system_session();\n"
"\n"
- "var ok = provision_become_dc(subobj, message, paths, system_session);\n"
+ "var ok = provision_become_dc(subobj, message, true, paths, system_session);\n"
"assert(ok);\n"
"\n"
"return 0;\n",
- p->forest->root_dn_str,
- p->domain->dn_str,
- p->forest->config_dn_str,
- p->forest->schema_dn_str,
- p->dest_dsa->netbios_name,
- p->dest_dsa->dns_name,
- p->dest_dsa->site_name,
- TORTURE_SAMDB_LDB);
+ p->forest->root_dn_str, /* subobj.ROOTDN */
+ p->domain->dn_str, /* subobj.DOMAINDN */
+ s->path.domaindn_ldb, /* subobj.DOMAINDN_LDB */
+ p->forest->config_dn_str, /* subobj.CONFIGDN */
+ s->path.configdn_ldb, /* subobj.CONFIGDN_LDB */
+ p->forest->schema_dn_str, /* subobj.SCHEMADN */
+ s->path.schemadn_ldb, /* subobj.SCHEMADN_LDB */
+ p->dest_dsa->netbios_name, /* subobj.HOSTNAME */
+ torture_join_dom_dns_name(s->tj),/* subobj.REALM */
+ torture_join_dom_netbios_name(s->tj),/* subobj.DOMAIN */
+ p->dest_dsa->site_name, /* subobj.DEFAULTSITE */
+ cli_credentials_get_password(s->machine_account),/* subobj.MACHINEPASS */
+ s->path.samdb_ldb, /* paths.samdb */
+ s->path.templates_ldb, /* paths.templates */
+ s->path.secrets_ldb, /* paths.secrets */
+ s->path.secrets_keytab, /* paths.keytab */
+ s->path.dns_keytab); /* paths.dns_keytab */
NT_STATUS_HAVE_NO_MEMORY(ejs);
ret = test_run_ejs(ejs);
talloc_free(s->ldb);
- s->ldb = ldb_wrap_connect(s, TORTURE_SAMDB_LDB,
- system_session(s),
+ DEBUG(0,("Open the SAM LDB with system credentials: %s\n",
+ s->path.samdb_ldb));
+
+ s->ldb = ldb_wrap_connect(s, s->tctx->lp_ctx, s->path.samdb_ldb,
+ system_session(s, s->tctx->lp_ctx),
NULL, 0, NULL);
if (!s->ldb) {
DEBUG(0,("Failed to open '%s'\n",
- TORTURE_SAMDB_LDB));
+ s->path.samdb_ldb));
return NT_STATUS_INTERNAL_DB_ERROR;
}
- ret = ldb_transaction_start(s->ldb);
- if (ret != LDB_SUCCESS) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ ok = samdb_set_ntds_invocation_id(s->ldb, &p->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, &p->dest_dsa->ntds_guid);
+ if (!ok) {
+ DEBUG(0,("Failed to set cached ntds objectGUID\n"));
+ return NT_STATUS_FOOBAR;
}
return NT_STATUS_OK;
}
-static WERROR test_object_to_ldb(struct test_become_dc_state *s,
- const struct libnet_BecomeDC_StoreChunk *c,
- struct drsuapi_DsReplicaObjectListItemEx *obj,
- TALLOC_CTX *mem_ctx,
- struct ldb_message **_msg)
+#else
+#include "param/param.h"
+#include <Python.h>
+#include "scripting/python/modules.h"
+
+static NTSTATUS test_become_dc_prepare_db(void *private_data,
+ const struct libnet_BecomeDC_PrepareDB *p)
{
- NTSTATUS nt_status;
- WERROR status;
- uint32_t i;
- struct ldb_message *msg;
- struct replPropertyMetaDataBlob md;
- struct ldb_val md_value;
- struct drsuapi_DsReplicaObjMetaDataCtr mdc;
- struct ldb_val guid_value;
- NTTIME whenChanged = 0;
- time_t whenChanged_t;
- const char *whenChanged_s;
- const char *rdn_name;
- const struct ldb_val *rdn_value;
- const struct dsdb_attribute *rdn_attr;
- uint32_t rdn_attid;
- struct drsuapi_DsReplicaAttribute *name_a;
- struct drsuapi_DsReplicaMetaData *name_d;
- struct replPropertyMetaData1 *rdn_m;
- struct drsuapi_DsReplicaObjMetaData *rdn_mc;
- int ret;
+ struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
+ bool ok;
+ PyObject *provision_fn, *result, *parameters;
- if (!obj->object.identifier) {
- return WERR_FOOBAR;
- }
+ py_load_samba_modules();
+ Py_Initialize();
+
+ py_update_path("bin"); /* FIXME: Can't assume this always runs in source/... */
- if (!obj->object.identifier->dn || !obj->object.identifier->dn[0]) {
- return WERR_FOOBAR;
+ provision_fn = PyImport_Import(PyString_FromString("samba.provision.provision"));
+
+ if (provision_fn == NULL) {
+ DEBUG(0, ("Unable to import provision Python module.\n"));
+ return NT_STATUS_UNSUCCESSFUL;
}
+
+ DEBUG(0,("New Server[%s] in Site[%s]\n",
+ p->dest_dsa->dns_name, p->dest_dsa->site_name));
- msg = ldb_msg_new(mem_ctx);
- W_ERROR_HAVE_NO_MEMORY(msg);
+ DEBUG(0,("DSA Instance [%s]\n"
+ "\tobjectGUID[%s]\n"
+ "\tinvocationId[%s]\n",
+ p->dest_dsa->ntds_dn_str,
+ GUID_string(s, &p->dest_dsa->ntds_guid),
+ GUID_string(s, &p->dest_dsa->invocation_id)));
- msg->dn = ldb_dn_new(msg, s->ldb, obj->object.identifier->dn);
- W_ERROR_HAVE_NO_MEMORY(msg->dn);
+ DEBUG(0,("Pathes under PRIVATEDIR[%s]\n"
+ "SAMDB[%s] SECRETS[%s] KEYTAB[%s]\n",
+ lp_private_dir(s->tctx->lp_ctx),
+ s->path.samdb_ldb,
+ s->path.secrets_ldb,
+ s->path.secrets_keytab));
- rdn_name = ldb_dn_get_rdn_name(msg->dn);
- rdn_attr = dsdb_attribute_by_lDAPDisplayName(s->schema, rdn_name);
- if (!rdn_attr) {
- return WERR_FOOBAR;
- }
- rdn_attid = rdn_attr->attributeID_id;
- rdn_value = ldb_dn_get_rdn_val(msg->dn);
+ DEBUG(0,("Schema Partition[%s => %s]\n",
+ p->forest->schema_dn_str, s->path.schemadn_ldb));
- msg->num_elements = obj->object.attribute_ctr.num_attributes;
- msg->elements = talloc_array(msg, struct ldb_message_element,
- msg->num_elements);
- W_ERROR_HAVE_NO_MEMORY(msg->elements);
+ DEBUG(0,("Config Partition[%s => %s]\n",
+ p->forest->config_dn_str, s->path.configdn_ldb));
- for (i=0; i < msg->num_elements; i++) {
- status = dsdb_attribute_drsuapi_to_ldb(s->schema,
- &obj->object.attribute_ctr.attributes[i],
- msg->elements, &msg->elements[i]);
- W_ERROR_NOT_OK_RETURN(status);
- }
-
- if (obj->object.attribute_ctr.num_attributes != 0 && !obj->meta_data_ctr) {
- return WERR_FOOBAR;
- }
-
- if (obj->object.attribute_ctr.num_attributes != obj->meta_data_ctr->count) {
- return WERR_FOOBAR;
- }
-
- md.version = 1;
- md.reserved = 0;
- md.ctr.ctr1.count = obj->meta_data_ctr->count;
- md.ctr.ctr1.reserved = 0;
- md.ctr.ctr1.array = talloc_array(mem_ctx,
- struct replPropertyMetaData1,
- md.ctr.ctr1.count + 1);
- W_ERROR_HAVE_NO_MEMORY(md.ctr.ctr1.array);
-
- mdc.count = obj->meta_data_ctr->count;
- mdc.reserved = 0;
- mdc.array = talloc_array(mem_ctx,
- struct drsuapi_DsReplicaObjMetaData,
- mdc.count + 1);
- W_ERROR_HAVE_NO_MEMORY(mdc.array);
-
- for (i=0; i < obj->meta_data_ctr->count; i++) {
- struct drsuapi_DsReplicaAttribute *a;
- struct drsuapi_DsReplicaMetaData *d;
- struct replPropertyMetaData1 *m;
- struct drsuapi_DsReplicaObjMetaData *mc;
-
- a = &obj->object.attribute_ctr.attributes[i];
- d = &obj->meta_data_ctr->meta_data[i];
- m = &md.ctr.ctr1.array[i];
- mc = &mdc.array[i];
-
- m->attid = a->attid;
- m->version = d->version;
- m->orginating_time = d->orginating_time;
- m->orginating_invocation_id = d->orginating_invocation_id;
- m->orginating_usn = d->orginating_usn;
- m->local_usn = 0;
-
- mc->attribute_name = dsdb_lDAPDisplayName_by_id(s->schema, a->attid);
- mc->version = d->version;
- mc->originating_last_changed = d->orginating_time;
- mc->originating_dsa_invocation_id= d->orginating_invocation_id;
- mc->originating_usn = d->orginating_usn;
- mc->local_usn = 0;
-
- if (d->orginating_time > whenChanged) {
- whenChanged = d->orginating_time;
- }
+ DEBUG(0,("Domain Partition[%s => %s]\n",
+ p->domain->dn_str, s->path.domaindn_ldb));
- if (a->attid == DRSUAPI_ATTRIBUTE_name) {
- name_a = a;
- name_d = d;
- rdn_m = &md.ctr.ctr1.array[md.ctr.ctr1.count];
- rdn_mc = &mdc.array[mdc.count];
- }
- }
+ parameters = PyDict_New();
- if (!name_d) {
- return WERR_FOOBAR;
- }
+ PyDict_SetItemString(parameters, "rootdn", PyString_FromString(p->forest->root_dn_str));
+ PyDict_SetItemString(parameters, "domaindn", PyString_FromString(p->domain->dn_str));
+ PyDict_SetItemString(parameters, "domaindn_ldb", PyString_FromString(s->path.domaindn_ldb));
+ PyDict_SetItemString(parameters, "configdn", PyString_FromString(p->forest->config_dn_str));
+ PyDict_SetItemString(parameters, "configdn_ldb", PyString_FromString(s->path.configdn_ldb));
+ PyDict_SetItemString(parameters, "schema_dn_str", PyString_FromString(p->forest->schema_dn_str));
+ PyDict_SetItemString(parameters, "schemadn_ldb", PyString_FromString(s->path.schemadn_ldb));
+ PyDict_SetItemString(parameters, "netbios_name", PyString_FromString(p->dest_dsa->netbios_name));
+ PyDict_SetItemString(parameters, "dnsname", PyString_FromString(p->dest_dsa->dns_name));
+ PyDict_SetItemString(parameters, "defaultsite", PyString_FromString(p->dest_dsa->site_name));
+ PyDict_SetItemString(parameters, "machinepass", PyString_FromString(cli_credentials_get_password(s->machine_account)));
+ PyDict_SetItemString(parameters, "samdb", PyString_FromString(s->path.samdb_ldb));
+ PyDict_SetItemString(parameters, "secrets_ldb", PyString_FromString(s->path.secrets_ldb));
+ PyDict_SetItemString(parameters, "secrets_keytab", PyString_FromString(s->path.secrets_keytab));
- ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
- if (ret != LDB_SUCCESS) {
- return WERR_FOOBAR;
- }
+ result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
- nt_status = ndr_push_struct_blob(&guid_value, msg, &obj->object.identifier->guid,
- (ndr_push_flags_fn_t)ndr_push_GUID);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ntstatus_to_werror(nt_status);
- }
- ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL);
- if (ret != LDB_SUCCESS) {
- return WERR_FOOBAR;
- }
+ Py_DECREF(parameters);
- whenChanged_t = nt_time_to_unix(whenChanged);
- whenChanged_s = ldb_timestring(msg, whenChanged_t);
- W_ERROR_HAVE_NO_MEMORY(whenChanged_s);
- ret = ldb_msg_add_string(msg, "whenChanged", whenChanged_s);
- if (ret != LDB_SUCCESS) {
- return WERR_FOOBAR;
- }
-
- rdn_m->attid = rdn_attid;
- rdn_m->version = name_d->version;
- rdn_m->orginating_time = name_d->orginating_time;
- rdn_m->orginating_invocation_id = name_d->orginating_invocation_id;
- rdn_m->orginating_usn = name_d->orginating_usn;
- rdn_m->local_usn = 0;
- md.ctr.ctr1.count++;
-
- rdn_mc->attribute_name = rdn_attr->lDAPDisplayName;
- rdn_mc->version = name_d->version;
- rdn_mc->originating_last_changed = name_d->orginating_time;
- rdn_mc->originating_dsa_invocation_id = name_d->orginating_invocation_id;
- rdn_mc->originating_usn = name_d->orginating_usn;
- rdn_mc->local_usn = 0;
- mdc.count++;
-
- nt_status = ndr_push_struct_blob(&md_value, msg, &md,
- (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return ntstatus_to_werror(nt_status);
- }
- ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL);
- if (ret != LDB_SUCCESS) {
- return WERR_FOOBAR;
+ if (result == NULL) {
+ PyErr_Print();
+ PyErr_Clear();
+ return NT_STATUS_UNSUCCESSFUL;
}
- if (lp_parm_bool(-1, "become dc", "dump objects", False)) {
- struct ldb_ldif ldif;
- fprintf(stdout, "#\n");
- ldif.changetype = LDB_CHANGETYPE_NONE;
- ldif.msg = msg;
- ldb_ldif_write_file(s->ldb, stdout, &ldif);
- NDR_PRINT_DEBUG(drsuapi_DsReplicaObjMetaDataCtr, &mdc);
+ talloc_free(s->ldb);
+
+ DEBUG(0,("Open the SAM LDB with system credentials: %s\n",
+ s->path.samdb_ldb));
+
+ s->ldb = ldb_wrap_connect(s, s->tctx->lp_ctx, s->path.samdb_ldb,
+ system_session(s, s->tctx->lp_ctx),
+ NULL, 0, NULL);
+ if (!s->ldb) {
+ DEBUG(0,("Failed to open '%s'\n",
+ s->path.samdb_ldb));
+ return NT_STATUS_INTERNAL_DB_ERROR;
}
- ret = ldb_add(s->ldb, msg);
- if (ret != LDB_SUCCESS) {
- if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
- DEBUG(0,("record exists (ignored): %s: %d\n",
- obj->object.identifier->dn, ret));
- } else {
- DEBUG(0,("Failed to add record: %s: %d\n",
- obj->object.identifier->dn, ret));
- return WERR_FOOBAR;
- }
+ ok = samdb_set_ntds_invocation_id(s->ldb, &p->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, &p->dest_dsa->ntds_guid);
+ if (!ok) {
+ DEBUG(0,("Failed to set cached ntds objectGUID\n"));
+ return NT_STATUS_FOOBAR;
}
- *_msg = msg;
- return WERR_OK;
+ return NT_STATUS_OK;
}
+#endif
+
static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
const struct libnet_BecomeDC_StoreChunk *c)
{
WERROR status;
+ const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
+ uint32_t total_object_count;
+ uint32_t object_count;
+ struct drsuapi_DsReplicaObjectListItemEx *first_object;
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 *objs;
+ struct repsFromTo1 *s_dsa;
+ char *tmp_dns_name;
+ 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;
+
+ DEBUG(0,("Analyze and apply schema objects\n"));
+
+ s_dsa = talloc_zero(s, struct repsFromTo1);
+ NT_STATUS_HAVE_NO_MEMORY(s_dsa);
+ s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
+ NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
+
+ switch (c->ctr_level) {
+ case 1:
+ mapping_ctr = &c->ctr1->mapping_ctr;
+ total_object_count = c->ctr1->total_object_count;
+ object_count = s->schema_part.object_count;
+ first_object = s->schema_part.first_object;
+ linked_attributes_count = 0;
+ linked_attributes = NULL;
+ s_dsa->highwatermark = c->ctr1->new_highwatermark;
+ s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
+ s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
+ uptodateness_vector = NULL; /* TODO: map it */
+ break;
+ case 6:
+ mapping_ctr = &c->ctr6->mapping_ctr;
+ total_object_count = c->ctr6->total_object_count;
+ object_count = s->schema_part.object_count;
+ first_object = s->schema_part.first_object;
+ linked_attributes_count = 0; /* TODO: ! */
+ linked_attributes = NULL; /* TODO: ! */;
+ s_dsa->highwatermark = c->ctr6->new_highwatermark;
+ s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
+ s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
+ uptodateness_vector = c->ctr6->uptodateness_vector;
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
+ | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
+ | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
+ memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
- for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
- uint32_t i;
+ tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
+ tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
+ s_dsa->other_info->dns_name = tmp_dns_name;
+
+ for (cur = first_object; cur; cur = cur->next_object) {
bool is_attr = false;
bool is_class = false;
const char *oid = NULL;
a = &cur->object.attribute_ctr.attributes[i];
- status = dsdb_map_int2oid(s->schema, a->attid, s, &oid);
+ status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
if (is_attr) {
struct dsdb_attribute *sa;
- sa = talloc_zero(s->schema, struct dsdb_attribute);
+ sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
NT_STATUS_HAVE_NO_MEMORY(sa);
- status = dsdb_attribute_from_drsuapi(s->schema, &cur->object, s, sa);
+ status = dsdb_attribute_from_drsuapi(s->self_made_schema, &cur->object, s, sa);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
- DLIST_ADD_END(s->schema->attributes, sa, struct dsdb_attribute *);
+ DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
}
if (is_class) {
struct dsdb_class *sc;
- sc = talloc_zero(s->schema, struct dsdb_class);
+ sc = talloc_zero(s->self_made_schema, struct dsdb_class);
NT_STATUS_HAVE_NO_MEMORY(sc);
- status = dsdb_class_from_drsuapi(s->schema, &cur->object, s, sc);
+ status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
- DLIST_ADD_END(s->schema->classes, sc, struct dsdb_class *);
+ DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
}
}
- for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
- struct ldb_message *msg;
- status = test_object_to_ldb(s, c, cur, s, &msg);
- if (!W_ERROR_IS_OK(status)) {
- return werror_to_ntstatus(status);
+ /* attach the schema to the ldb */
+ ret = dsdb_set_schema(s->ldb, s->self_made_schema);
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_FOOBAR;
+ }
+ /* we don't want to access the self made schema anymore */
+ s->self_made_schema = NULL;
+ s->schema = dsdb_get_schema(s->ldb);
+
+ status = dsdb_extended_replicated_objects_commit(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, &objs);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
+ return werror_to_ntstatus(status);
+ }
+
+ if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
+ for (i=0; i < objs->num_objects; i++) {
+ struct ldb_ldif ldif;
+ fprintf(stdout, "#\n");
+ ldif.changetype = LDB_CHANGETYPE_NONE;
+ ldif.msg = objs->objects[i].msg;
+ ldb_ldif_write_file(s->ldb, stdout, &ldif);
+ NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
}
}
- ret = ldb_transaction_commit(s->ldb);
+ msg = ldb_msg_new(objs);
+ NT_STATUS_HAVE_NO_MEMORY(msg);
+ msg->dn = objs->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);
if (ret != LDB_SUCCESS) {
- DEBUG(0,("Failed to commit the schema changes: %d\n", ret));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return NT_STATUS_FOOBAR;
}
+ prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
- ret = ldb_transaction_start(s->ldb);
+ ret = ldb_modify(s->ldb, msg);
if (ret != LDB_SUCCESS) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
+ return NT_STATUS_FOOBAR;
+ }
+
+ talloc_free(s_dsa);
+ talloc_free(objs);
+
+ /* reopen the ldb */
+ talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
+ s->schema = NULL;
+
+ DEBUG(0,("Reopen the SAM LDB with system credentials and a already stored schema: %s\n", s->path.samdb_ldb));
+ s->ldb = ldb_wrap_connect(s, s->tctx->lp_ctx, s->path.samdb_ldb,
+ system_session(s, s->tctx->lp_ctx),
+ NULL, 0, NULL);
+ if (!s->ldb) {
+ DEBUG(0,("Failed to open '%s'\n",
+ s->path.samdb_ldb));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ 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);
+ if (!s->schema) {
+ DEBUG(0,("Failed to get loaded dsdb_schema\n"));
+ return NT_STATUS_FOOBAR;
}
return NT_STATUS_OK;
}
if (!s->schema) {
- s->schema = talloc_zero(s, struct dsdb_schema);
- NT_STATUS_HAVE_NO_MEMORY(s->schema);
+ s->self_made_schema = talloc_zero(s, struct dsdb_schema);
+ NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
- status = dsdb_load_oid_mappings(s->schema, mapping_ctr);
+ status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
+
+ s->schema = s->self_made_schema;
} else {
- status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
+ status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
if (!W_ERROR_IS_OK(status)) {
return werror_to_ntstatus(status);
}
}
if (!s->schema_part.first_object) {
+ s->schema_part.object_count = object_count;
s->schema_part.first_object = talloc_steal(s, first_object);
} else {
+ s->schema_part.object_count += object_count;
s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
first_object);
}
uint32_t total_object_count;
uint32_t object_count;
struct drsuapi_DsReplicaObjectListItemEx *first_object;
- 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 *objs;
+ struct repsFromTo1 *s_dsa;
+ char *tmp_dns_name;
uint32_t i;
- int ret;
+
+ s_dsa = talloc_zero(s, struct repsFromTo1);
+ NT_STATUS_HAVE_NO_MEMORY(s_dsa);
+ s_dsa->other_info = talloc(s_dsa, struct repsFromTo1OtherInfo);
+ NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
switch (c->ctr_level) {
case 1:
- mapping_ctr = &c->ctr1->mapping_ctr;
- total_object_count = c->ctr1->total_object_count;
- object_count = c->ctr1->object_count;
- first_object = c->ctr1->first_object;
- linked_attributes_count = 0;
- linked_attributes = NULL;
+ mapping_ctr = &c->ctr1->mapping_ctr;
+ total_object_count = c->ctr1->total_object_count;
+ object_count = c->ctr1->object_count;
+ first_object = c->ctr1->first_object;
+ linked_attributes_count = 0;
+ linked_attributes = NULL;
+ s_dsa->highwatermark = c->ctr1->new_highwatermark;
+ s_dsa->source_dsa_obj_guid = c->ctr1->source_dsa_guid;
+ s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
+ uptodateness_vector = NULL; /* TODO: map it */
break;
case 6:
- mapping_ctr = &c->ctr6->mapping_ctr;
- total_object_count = c->ctr6->total_object_count;
- object_count = c->ctr6->object_count;
- first_object = c->ctr6->first_object;
- linked_attributes_count = c->ctr6->linked_attributes_count;
- linked_attributes = c->ctr6->linked_attributes;
+ mapping_ctr = &c->ctr6->mapping_ctr;
+ total_object_count = c->ctr6->total_object_count;
+ object_count = c->ctr6->object_count;
+ first_object = c->ctr6->first_object;
+ linked_attributes_count = c->ctr6->linked_attributes_count;
+ linked_attributes = c->ctr6->linked_attributes;
+ s_dsa->highwatermark = c->ctr6->new_highwatermark;
+ s_dsa->source_dsa_obj_guid = c->ctr6->source_dsa_guid;
+ s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
+ uptodateness_vector = c->ctr6->uptodateness_vector;
break;
default:
return NT_STATUS_INVALID_PARAMETER;
}
+ s_dsa->replica_flags = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
+ | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
+ | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
+ memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
+
+ tmp_dns_name = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
+ tmp_dns_name = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
+ s_dsa->other_info->dns_name = tmp_dns_name;
+
if (total_object_count) {
DEBUG(0,("Partition[%s] objects[%u/%u]\n",
c->partition->nc.dn, object_count, total_object_count));
c->partition->nc.dn, object_count));
}
- status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
+ status = dsdb_extended_replicated_objects_commit(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, &objs);
if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
return werror_to_ntstatus(status);
}
- for (cur = first_object; cur; cur = cur->next_object) {
- struct ldb_message *msg;
- status = test_object_to_ldb(s, c, cur, s, &msg);
- if (!W_ERROR_IS_OK(status)) {
- return werror_to_ntstatus(status);
+ if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
+ for (i=0; i < objs->num_objects; i++) {
+ struct ldb_ldif ldif;
+ fprintf(stdout, "#\n");
+ ldif.changetype = LDB_CHANGETYPE_NONE;
+ ldif.msg = objs->objects[i].msg;
+ ldb_ldif_write_file(s->ldb, stdout, &ldif);
+ NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
}
}
+ talloc_free(s_dsa);
+ talloc_free(objs);
for (i=0; i < linked_attributes_count; i++) {
const struct dsdb_attribute *sa;
return NT_STATUS_FOOBAR;
}
- if (lp_parm_bool(-1, "become dc", "dump objects", False)) {
+ if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
DEBUG(0,("# %s\n", sa->lDAPDisplayName));
NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
dump_data(0,
}
}
- ret = ldb_transaction_commit(s->ldb);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,("Failed to commit the changes: %d\n", ret));
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- ret = ldb_transaction_start(s->ldb);
- if (ret != LDB_SUCCESS) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
return NT_STATUS_OK;
}
-BOOL torture_net_become_dc(struct torture_context *torture)
+bool torture_net_become_dc(struct torture_context *torture)
{
- BOOL ret = True;
+ bool ret = true;
NTSTATUS status;
struct libnet_BecomeDC b;
struct libnet_UnbecomeDC u;
struct test_become_dc_state *s;
+ struct ldb_message *msg;
+ int ldb_ret;
+ uint32_t i;
s = talloc_zero(torture, struct test_become_dc_state);
- if (!s) return False;
+ if (!s) return false;
+
+ s->tctx = torture;
+
+ s->netbios_name = lp_parm_string(torture->lp_ctx, NULL, "become dc", "smbtorture dc");
+ if (!s->netbios_name || !s->netbios_name[0]) {
+ s->netbios_name = "smbtorturedc";
+ }
+
+ s->path.samdb_ldb = talloc_asprintf(s, "%s_samdb.ldb", s->netbios_name);
+ if (!s->path.samdb_ldb) return false;
+ s->path.domaindn_ldb = talloc_asprintf(s, "%s_domain.ldb", s->netbios_name);
+ if (!s->path.domaindn_ldb) return false;
+ s->path.configdn_ldb = talloc_asprintf(s, "%s_config.ldb", s->netbios_name);
+ if (!s->path.configdn_ldb) return false;
+ s->path.schemadn_ldb = talloc_asprintf(s, "%s_schema.ldb", s->netbios_name);
+ if (!s->path.schemadn_ldb) return false;
+ s->path.secrets_ldb = talloc_asprintf(s, "%s_secrets.ldb", s->netbios_name);
+ if (!s->path.secrets_ldb) return false;
+ s->path.templates_ldb = talloc_asprintf(s, "%s_templates.ldb", s->netbios_name);
+ if (!s->path.templates_ldb) return false;
+ s->path.secrets_keytab = talloc_asprintf(s, "%s_secrets.keytab", s->netbios_name);
+ if (!s->path.secrets_keytab) return false;
+ s->path.dns_keytab = talloc_asprintf(s, "%s_dns.keytab", s->netbios_name);
+ if (!s->path.dns_keytab) return false;
/* Join domain as a member server. */
- s->tj = torture_join_domain(TORTURE_NETBIOS_NAME,
+ s->tj = torture_join_domain(torture, s->netbios_name,
ACB_WSTRUST,
&s->machine_account);
if (!s->tj) {
DEBUG(0, ("%s failed to join domain as workstation\n",
- TORTURE_NETBIOS_NAME));
- return False;
+ s->netbios_name));
+ return false;
}
- s->ctx = libnet_context_init(event_context_init(s));
+ s->ctx = libnet_context_init(torture->ev, torture->lp_ctx);
s->ctx->cred = cmdline_credentials;
s->ldb = ldb_init(s);
b.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
b.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
b.in.domain_sid = torture_join_sid(s->tj);
- b.in.source_dsa_address = lp_parm_string(-1, "torture", "host");
- b.in.dest_dsa_netbios_name = TORTURE_NETBIOS_NAME;
+ b.in.source_dsa_address = torture_setting_string(torture, "host", NULL);
+ b.in.dest_dsa_netbios_name = s->netbios_name;
b.in.callbacks.private_data = s;
b.in.callbacks.check_options = test_become_dc_check_options;
status = libnet_BecomeDC(s->ctx, s, &b);
if (!NT_STATUS_IS_OK(status)) {
printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
- ret = False;
+ ret = false;
+ goto cleanup;
+ }
+
+ msg = ldb_msg_new(s);
+ if (!msg) {
+ printf("ldb_msg_new() failed\n");
+ ret = false;
+ goto cleanup;
+ }
+ msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
+ if (!msg->dn) {
+ printf("ldb_msg_new(@ROOTDSE) failed\n");
+ ret = false;
+ goto cleanup;
+ }
+
+ 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);
+ ret = false;
+ goto cleanup;
+ }
+
+ 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\n", ldb_ret);
+ ret = false;
+ goto cleanup;
+ }
+
+ /* reopen the ldb */
+ talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
+ s->schema = NULL;
+
+ DEBUG(0,("Reopen the SAM LDB with system credentials and all replicated data: %s\n", s->path.samdb_ldb));
+ s->ldb = ldb_wrap_connect(s, torture->lp_ctx, s->path.samdb_ldb,
+ system_session(s, torture->lp_ctx),
+ NULL, 0, NULL);
+ if (!s->ldb) {
+ DEBUG(0,("Failed to open '%s'\n",
+ s->path.samdb_ldb));
+ ret = false;
+ goto cleanup;
+ }
+
+ s->schema = dsdb_get_schema(s->ldb);
+ if (!s->schema) {
+ DEBUG(0,("Failed to get loaded dsdb_schema\n"));
+ ret = false;
+ goto cleanup;
+ }
+
+ if (lp_parm_bool(torture->lp_ctx, NULL, "become dc", "do not unjoin", false)) {
+ talloc_free(s);
+ return ret;
}
+cleanup:
ZERO_STRUCT(u);
u.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
u.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
- u.in.source_dsa_address = lp_parm_string(-1, "torture", "host");
- u.in.dest_dsa_netbios_name = TORTURE_NETBIOS_NAME;
+ u.in.source_dsa_address = torture_setting_string(torture, "host", NULL);
+ u.in.dest_dsa_netbios_name = s->netbios_name;
status = libnet_UnbecomeDC(s->ctx, s, &u);
if (!NT_STATUS_IS_OK(status)) {
printf("libnet_UnbecomeDC() failed - %s\n", nt_errstr(status));
- ret = False;
+ ret = false;
}
/* Leave domain. */