2 Unix SMB/CIFS implementation.
4 libnet_BecomeDC() tests
6 Copyright (C) Stefan (metze) Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "lib/cmdline/popt_common.h"
25 #include "torture/torture.h"
26 #include "torture/rpc/rpc.h"
27 #include "libnet/libnet.h"
28 #include "lib/events/events.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "lib/util/dlinklist.h"
32 #define TORTURE_NETBIOS_NAME "smbtorturedc"
34 struct test_become_dc_state {
35 struct libnet_context *ctx;
37 struct cli_credentials *machine_account;
38 struct dsdb_schema *schema;
40 struct ldb_context *ldb;
43 struct drsuapi_DsReplicaObjectListItemEx *first_object;
44 struct drsuapi_DsReplicaObjectListItemEx *last_object;
48 static NTSTATUS test_become_dc_check_options(void *private_data,
49 const struct libnet_BecomeDC_CheckOptions *o)
51 DEBUG(0,("Become DC of Domain[%s]/[%s]\n",
52 o->domain->netbios_name, o->domain->dns_name));
54 DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
55 o->source_dsa->dns_name, o->source_dsa->site_name));
57 DEBUG(0,("Options:crossRef behavior_version[%u]\n"
58 "\tschema object_version[%u]\n"
59 "\tdomain behavior_version[%u]\n"
60 "\tdomain w2k3_update_revision[%u]\n",
61 o->forest->crossref_behavior_version,
62 o->forest->schema_object_version,
63 o->domain->behavior_version,
64 o->domain->w2k3_update_revision));
69 static NTSTATUS test_become_dc_prepare_db(void *private_data,
70 const struct libnet_BecomeDC_PrepareDB *p)
72 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
74 DEBUG(0,("New Server[%s] in Site[%s]\n",
75 p->dest_dsa->dns_name, p->dest_dsa->site_name));
77 DEBUG(0,("DSA Instance [%s]\n"
79 "\tinvocationId[%s]\n",
80 p->dest_dsa->ntds_dn_str,
81 GUID_string(s, &p->dest_dsa->ntds_guid),
82 GUID_string(s, &p->dest_dsa->invocation_id)));
84 DEBUG(0,("Schema Partition[%s]\n",
85 p->forest->schema_dn_str));
87 DEBUG(0,("Config Partition[%s]\n",
88 p->forest->config_dn_str));
90 DEBUG(0,("Domain Partition[%s]\n",
96 static WERROR test_object_to_ldb(struct test_become_dc_state *s,
97 const struct libnet_BecomeDC_StoreChunk *c,
98 struct drsuapi_DsReplicaObjectListItemEx *obj,
100 struct ldb_message **_msg)
104 struct ldb_message *msg;
106 msg = ldb_msg_new(mem_ctx);
107 W_ERROR_HAVE_NO_MEMORY(msg);
109 msg->dn = ldb_dn_new(msg, s->ldb, obj->object.identifier->dn);
110 W_ERROR_HAVE_NO_MEMORY(msg->dn);
112 msg->num_elements = obj->object.attribute_ctr.num_attributes;
113 msg->elements = talloc_array(msg, struct ldb_message_element,
115 W_ERROR_HAVE_NO_MEMORY(msg->elements);
117 for (i=0; i < msg->num_elements; i++) {
118 status = dsdb_attribute_drsuapi_to_ldb(s->schema,
119 &obj->object.attribute_ctr.attributes[i],
120 msg->elements, &msg->elements[i]);
121 W_ERROR_NOT_OK_RETURN(status);
124 if (lp_parm_bool(-1, "become dc", "dump objects", False)) {
125 struct ldb_ldif ldif;
126 fprintf(stdout, "#\n");
127 ldif.changetype = LDB_CHANGETYPE_NONE;
129 ldb_ldif_write_file(s->ldb, stdout, &ldif);
136 static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
137 const struct libnet_BecomeDC_StoreChunk *c)
140 struct drsuapi_DsReplicaObjectListItemEx *cur;
142 for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
144 bool is_attr = false;
145 bool is_class = false;
147 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
148 struct drsuapi_DsReplicaAttribute *a;
150 const char *oid = NULL;
152 a = &cur->object.attribute_ctr.attributes[i];
153 status = dsdb_map_int2oid(s->schema, a->attid, s, &oid);
154 if (!W_ERROR_IS_OK(status)) {
155 return werror_to_ntstatus(status);
159 case DRSUAPI_ATTRIBUTE_objectClass:
160 for (j=0; j < a->value_ctr.data_blob.num_values; j++) {
161 uint32_t val = 0xFFFFFFFF;
163 if (a->value_ctr.data_blob.values[i].data
164 && a->value_ctr.data_blob.values[i].data->length == 4) {
165 val = IVAL(a->value_ctr.data_blob.values[i].data->data,0);
168 if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
171 if (val == DRSUAPI_OBJECTCLASS_classSchema) {
183 struct dsdb_attribute *sa;
185 sa = talloc_zero(s->schema, struct dsdb_attribute);
186 NT_STATUS_HAVE_NO_MEMORY(sa);
188 status = dsdb_attribute_from_drsuapi(s->schema, &cur->object, s, sa);
189 if (!W_ERROR_IS_OK(status)) {
190 return werror_to_ntstatus(status);
193 DLIST_ADD_END(s->schema->attributes, sa, struct dsdb_attribute *);
197 struct dsdb_class *sc;
199 sc = talloc_zero(s->schema, struct dsdb_class);
200 NT_STATUS_HAVE_NO_MEMORY(sc);
202 status = dsdb_class_from_drsuapi(s->schema, &cur->object, s, sc);
203 if (!W_ERROR_IS_OK(status)) {
204 return werror_to_ntstatus(status);
207 DLIST_ADD_END(s->schema->classes, sc, struct dsdb_class *);
211 for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
212 struct ldb_message *msg;
213 status = test_object_to_ldb(s, c, cur, s, &msg);
214 if (!W_ERROR_IS_OK(status)) {
215 return werror_to_ntstatus(status);
222 static NTSTATUS test_become_dc_schema_chunk(void *private_data,
223 const struct libnet_BecomeDC_StoreChunk *c)
225 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
227 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
228 uint32_t total_object_count;
229 uint32_t object_count;
230 struct drsuapi_DsReplicaObjectListItemEx *first_object;
231 struct drsuapi_DsReplicaObjectListItemEx *cur;
233 switch (c->ctr_level) {
235 mapping_ctr = &c->ctr1->mapping_ctr;
236 total_object_count = c->ctr1->total_object_count;
237 object_count = c->ctr1->object_count;
238 first_object = c->ctr1->first_object;
241 mapping_ctr = &c->ctr6->mapping_ctr;
242 total_object_count = c->ctr6->total_object_count;
243 object_count = c->ctr6->object_count;
244 first_object = c->ctr6->first_object;
247 return NT_STATUS_INVALID_PARAMETER;
250 if (total_object_count) {
251 DEBUG(0,("Schema-DN[%s] objects[%u/%u]\n",
252 c->partition->nc.dn, object_count, total_object_count));
254 DEBUG(0,("Schema-DN[%s] objects[%u]\n",
255 c->partition->nc.dn, object_count));
259 s->schema = talloc_zero(s, struct dsdb_schema);
260 NT_STATUS_HAVE_NO_MEMORY(s->schema);
262 status = dsdb_load_oid_mappings(s->schema, mapping_ctr);
263 if (!W_ERROR_IS_OK(status)) {
264 return werror_to_ntstatus(status);
267 status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
268 if (!W_ERROR_IS_OK(status)) {
269 return werror_to_ntstatus(status);
273 if (!s->schema_part.first_object) {
274 s->schema_part.first_object = talloc_steal(s, first_object);
276 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
279 for (cur = first_object; cur->next_object; cur = cur->next_object) {}
280 s->schema_part.last_object = cur;
282 if (c->partition->highwatermark.tmp_highest_usn == c->partition->highwatermark.highest_usn) {
283 return test_apply_schema(s, c);
289 static NTSTATUS test_become_dc_store_chunk(void *private_data,
290 const struct libnet_BecomeDC_StoreChunk *c)
292 struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
294 const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
295 uint32_t total_object_count;
296 uint32_t object_count;
297 struct drsuapi_DsReplicaObjectListItemEx *first_object;
298 struct drsuapi_DsReplicaObjectListItemEx *cur;
300 switch (c->ctr_level) {
302 mapping_ctr = &c->ctr1->mapping_ctr;
303 total_object_count = c->ctr1->total_object_count;
304 object_count = c->ctr1->object_count;
305 first_object = c->ctr1->first_object;
308 mapping_ctr = &c->ctr6->mapping_ctr;
309 total_object_count = c->ctr6->total_object_count;
310 object_count = c->ctr6->object_count;
311 first_object = c->ctr6->first_object;
314 return NT_STATUS_INVALID_PARAMETER;
317 if (total_object_count) {
318 DEBUG(0,("Partition[%s] objects[%u/%u]\n",
319 c->partition->nc.dn, object_count, total_object_count));
321 DEBUG(0,("Partition[%s] objects[%u]\n",
322 c->partition->nc.dn, object_count));
325 status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
326 if (!W_ERROR_IS_OK(status)) {
327 return werror_to_ntstatus(status);
330 for (cur = first_object; cur; cur = cur->next_object) {
331 struct ldb_message *msg;
332 status = test_object_to_ldb(s, c, cur, s, &msg);
333 if (!W_ERROR_IS_OK(status)) {
334 return werror_to_ntstatus(status);
341 BOOL torture_net_become_dc(struct torture_context *torture)
345 struct libnet_BecomeDC b;
346 struct libnet_UnbecomeDC u;
347 struct test_become_dc_state *s;
349 s = talloc_zero(torture, struct test_become_dc_state);
350 if (!s) return False;
352 /* Join domain as a member server. */
353 s->tj = torture_join_domain(TORTURE_NETBIOS_NAME,
355 &s->machine_account);
357 DEBUG(0, ("%s failed to join domain as workstation\n",
358 TORTURE_NETBIOS_NAME));
362 s->ctx = libnet_context_init(event_context_init(s));
363 s->ctx->cred = cmdline_credentials;
365 s->ldb = ldb_init(s);
368 b.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
369 b.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
370 b.in.domain_sid = torture_join_sid(s->tj);
371 b.in.source_dsa_address = lp_parm_string(-1, "torture", "host");
372 b.in.dest_dsa_netbios_name = TORTURE_NETBIOS_NAME;
374 b.in.callbacks.private_data = s;
375 b.in.callbacks.check_options = test_become_dc_check_options;
376 b.in.callbacks.prepare_db = test_become_dc_prepare_db;
377 b.in.callbacks.schema_chunk = test_become_dc_schema_chunk;
378 b.in.callbacks.config_chunk = test_become_dc_store_chunk;
379 b.in.callbacks.domain_chunk = test_become_dc_store_chunk;
381 status = libnet_BecomeDC(s->ctx, s, &b);
382 if (!NT_STATUS_IS_OK(status)) {
383 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
388 u.in.domain_dns_name = torture_join_dom_dns_name(s->tj);
389 u.in.domain_netbios_name = torture_join_dom_netbios_name(s->tj);
390 u.in.source_dsa_address = lp_parm_string(-1, "torture", "host");
391 u.in.dest_dsa_netbios_name = TORTURE_NETBIOS_NAME;
393 status = libnet_UnbecomeDC(s->ctx, s, &u);
394 if (!NT_STATUS_IS_OK(status)) {
395 printf("libnet_UnbecomeDC() failed - %s\n", nt_errstr(status));
400 torture_leave_domain(s->tj);