r20572: - prepare a test_samdb.ldb in the NET-API-BECOME-DC torture test
[bbaumbach/samba-autobuild/.git] / source4 / torture / libnet / libnet_BecomeDC.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    libnet_BecomeDC() tests
5
6    Copyright (C) Stefan (metze) Metzmacher 2006
7    
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
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"
31 #include "lib/ldb/include/ldb.h"
32 #include "lib/ldb/include/ldb_errors.h"
33 #include "librpc/ndr/libndr.h"
34 #include "librpc/gen_ndr/ndr_drsuapi.h"
35 #include "librpc/gen_ndr/ndr_drsblobs.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
37 #include "system/time.h"
38
39 #include "lib/appweb/ejs/ejs.h"
40 #include "lib/appweb/ejs/ejsInternal.h"
41 #include "scripting/ejs/smbcalls.h"
42
43 static EjsId eid;
44 static int ejs_error;
45
46 static void test_ejs_exception(const char *reason)
47 {
48         Ejs *ep = ejsPtr(eid);
49         ejsSetErrorMsg(eid, "%s", reason);
50         fprintf(stderr, "%s", ep->error);
51         ejs_error = 127;
52 }
53
54 static int test_run_ejs(char *script)
55 {
56         EjsHandle handle = 0;
57         MprVar result;
58         char *emsg;
59         TALLOC_CTX *mem_ctx = talloc_new(NULL);
60         struct MprVar *return_var;
61
62         mprSetCtx(mem_ctx);
63
64         if (ejsOpen(NULL, NULL, NULL) != 0) {
65                 d_printf("ejsOpen(): unable to initialise EJS subsystem\n");
66                 ejs_error = 127;
67                 goto failed;
68         }
69
70         smb_setup_ejs_functions(test_ejs_exception);
71
72         if ((eid = ejsOpenEngine(handle, 0)) == (EjsId)-1) {
73                 d_printf("smbscript: ejsOpenEngine(): unable to initialise an EJS engine\n");
74                 ejs_error = 127;
75                 goto failed;
76         }
77
78         mprSetVar(ejsGetGlobalObject(eid), "ARGV", mprList("ARGV", NULL));
79
80         /* run the script */
81         if (ejsEvalScript(eid, script, &result, &emsg) == -1) {
82                 d_printf("smbscript: ejsEvalScript(): %s\n", emsg);
83                 if (ejs_error == 0) ejs_error = 127;
84                 goto failed;
85         }
86
87         return_var = ejsGetReturnValue(eid);
88         ejs_error = mprVarToNumber(return_var);
89
90 failed:
91         ejsClose();
92         talloc_free(mem_ctx);
93         return ejs_error;
94 }
95
96 #define TORTURE_NETBIOS_NAME "smbtorturedc"
97
98 struct test_become_dc_state {
99         struct libnet_context *ctx;
100         struct test_join *tj;
101         struct cli_credentials *machine_account;
102         struct dsdb_schema *schema;
103
104         struct ldb_context *ldb;
105
106         struct {
107                 struct drsuapi_DsReplicaObjectListItemEx *first_object;
108                 struct drsuapi_DsReplicaObjectListItemEx *last_object;
109         } schema_part;
110 };
111
112 static NTSTATUS test_become_dc_check_options(void *private_data,
113                                              const struct libnet_BecomeDC_CheckOptions *o)
114 {
115         DEBUG(0,("Become DC of Domain[%s]/[%s]\n",
116                 o->domain->netbios_name, o->domain->dns_name));
117
118         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
119                 o->source_dsa->dns_name, o->source_dsa->site_name));
120
121         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
122                        "\tschema object_version[%u]\n"
123                        "\tdomain behavior_version[%u]\n"
124                        "\tdomain w2k3_update_revision[%u]\n", 
125                 o->forest->crossref_behavior_version,
126                 o->forest->schema_object_version,
127                 o->domain->behavior_version,
128                 o->domain->w2k3_update_revision));
129
130         return NT_STATUS_OK;
131 }
132
133 static NTSTATUS test_become_dc_prepare_db(void *private_data,
134                                           const struct libnet_BecomeDC_PrepareDB *p)
135 {
136         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
137         char *ejs;
138         int ret;
139
140         DEBUG(0,("New Server[%s] in Site[%s]\n",
141                 p->dest_dsa->dns_name, p->dest_dsa->site_name));
142
143         DEBUG(0,("DSA Instance [%s]\n"
144                 "\tobjectGUID[%s]\n"
145                 "\tinvocationId[%s]\n",
146                 p->dest_dsa->ntds_dn_str,
147                 GUID_string(s, &p->dest_dsa->ntds_guid),
148                 GUID_string(s, &p->dest_dsa->invocation_id)));
149
150         DEBUG(0,("Schema Partition[%s]\n",
151                 p->forest->schema_dn_str));
152
153         DEBUG(0,("Config Partition[%s]\n",
154                 p->forest->config_dn_str));
155
156         DEBUG(0,("Domain Partition[%s]\n",
157                 p->domain->dn_str));
158
159         ejs = talloc_asprintf(s,
160                 "libinclude(\"base.js\");\n"
161                 "libinclude(\"provision.js\");\n"
162                 "\n"
163                 "function message() { print(vsprintf(arguments)); }\n"
164                 "\n"
165                 "var subobj = provision_guess();\n"
166                 "subobj.ROOTDN       = \"%s\";\n"
167                 "subobj.DOMAINDN     = \"%s\";\n"
168                 "subobj.DOMAINDN_LDB = \"test_domain.ldb\";\n"
169                 "subobj.CONFIGDN     = \"%s\";\n"
170                 "subobj.CONFIGDN_LDB = \"test_config.ldb\";\n"
171                 "subobj.SCHEMADN     = \"%s\";\n"
172                 "subobj.SCHEMADN_LDB = \"test_schema.ldb\";\n"
173                 "subobj.HOSTNAME     = \"%s\";\n"
174                 "subobj.DNSNAME      = \"%s\";\n"
175                 "subobj.DEFAULTSITE  = \"%s\";\n"
176                 "\n"
177                 "var paths = provision_default_paths(subobj);\n"
178                 "paths.samdb = \"test_samdb.ldb\";\n"
179                 "\n"
180                 "var system_session = system_session();\n"
181                 "\n"
182                 "var ok = provision_become_dc(subobj, message, paths, system_session);\n"
183                 "assert(ok);\n"
184                 "\n"
185                 "return 0;\n",
186                 p->forest->root_dn_str,
187                 p->domain->dn_str,
188                 p->forest->config_dn_str,
189                 p->forest->schema_dn_str,
190                 p->dest_dsa->netbios_name,
191                 p->dest_dsa->dns_name,
192                 p->dest_dsa->site_name);
193         NT_STATUS_HAVE_NO_MEMORY(ejs);
194
195         ret = test_run_ejs(ejs);
196         if (ret != 0) {
197                 DEBUG(0,("Failed to run ejs script: %d:\n%s",
198                         ret, ejs));
199                 talloc_free(ejs);
200                 return NT_STATUS_FOOBAR;
201         }
202
203         talloc_free(ejs);
204
205         return NT_STATUS_OK;
206 }
207
208 static WERROR test_object_to_ldb(struct test_become_dc_state *s,
209                                  const struct libnet_BecomeDC_StoreChunk *c,
210                                  struct drsuapi_DsReplicaObjectListItemEx *obj,
211                                  TALLOC_CTX *mem_ctx,
212                                  struct ldb_message **_msg)
213 {
214         NTSTATUS nt_status;
215         WERROR status;
216         uint32_t i;
217         struct ldb_message *msg;
218         struct replPropertyMetaDataBlob md;
219         struct ldb_val md_value;
220         struct drsuapi_DsReplicaObjMetaDataCtr mdc;
221         struct ldb_val guid_value;
222         NTTIME whenChanged = 0;
223         time_t whenChanged_t;
224         const char *whenChanged_s;
225         const char *rdn_name;
226         const struct ldb_val *rdn_value;
227         const struct dsdb_attribute *rdn_attr;
228         uint32_t rdn_attid;
229         struct drsuapi_DsReplicaAttribute *name_a;
230         struct drsuapi_DsReplicaMetaData *name_d;
231         struct replPropertyMetaData1 *rdn_m;
232         struct drsuapi_DsReplicaObjMetaData *rdn_mc;
233         int ret;
234
235         msg = ldb_msg_new(mem_ctx);
236         W_ERROR_HAVE_NO_MEMORY(msg);
237
238         msg->dn                 = ldb_dn_new(msg, s->ldb, obj->object.identifier->dn);
239         W_ERROR_HAVE_NO_MEMORY(msg->dn);
240
241         rdn_name        = ldb_dn_get_rdn_name(msg->dn);
242         rdn_attr        = dsdb_attribute_by_lDAPDisplayName(s->schema, rdn_name);
243         if (!rdn_attr) {
244                 return WERR_FOOBAR;
245         }
246         rdn_attid       = rdn_attr->attributeID_id;
247         rdn_value       = ldb_dn_get_rdn_val(msg->dn);
248
249         msg->num_elements       = obj->object.attribute_ctr.num_attributes;
250         msg->elements           = talloc_array(msg, struct ldb_message_element,
251                                                msg->num_elements);
252         W_ERROR_HAVE_NO_MEMORY(msg->elements);
253
254         for (i=0; i < msg->num_elements; i++) {
255                 status = dsdb_attribute_drsuapi_to_ldb(s->schema,
256                                                        &obj->object.attribute_ctr.attributes[i],
257                                                        msg->elements, &msg->elements[i]);
258                 W_ERROR_NOT_OK_RETURN(status);
259         }
260
261         if (obj->object.attribute_ctr.num_attributes != 0 && !obj->meta_data_ctr) {
262                 return WERR_FOOBAR;
263         }
264
265         if (obj->object.attribute_ctr.num_attributes != obj->meta_data_ctr->count) {
266                 return WERR_FOOBAR;
267         }
268
269         md.version              = 1;
270         md.reserved             = 0;
271         md.ctr.ctr1.count       = obj->meta_data_ctr->count;
272         md.ctr.ctr1.reserved    = 0;
273         md.ctr.ctr1.array       = talloc_array(mem_ctx,
274                                                struct replPropertyMetaData1,
275                                                md.ctr.ctr1.count + 1);
276         W_ERROR_HAVE_NO_MEMORY(md.ctr.ctr1.array);
277
278         mdc.count       = obj->meta_data_ctr->count;
279         mdc.reserved    = 0;
280         mdc.array       = talloc_array(mem_ctx,
281                                        struct drsuapi_DsReplicaObjMetaData,
282                                        mdc.count + 1);
283         W_ERROR_HAVE_NO_MEMORY(mdc.array);
284
285         for (i=0; i < obj->meta_data_ctr->count; i++) {
286                 struct drsuapi_DsReplicaAttribute *a;
287                 struct drsuapi_DsReplicaMetaData *d;
288                 struct replPropertyMetaData1 *m;
289                 struct drsuapi_DsReplicaObjMetaData *mc;
290
291                 a = &obj->object.attribute_ctr.attributes[i];
292                 d = &obj->meta_data_ctr->meta_data[i];
293                 m = &md.ctr.ctr1.array[i];
294                 mc = &mdc.array[i];
295
296                 m->attid                        = a->attid;
297                 m->version                      = d->version;
298                 m->orginating_time              = d->orginating_time;
299                 m->orginating_invocation_id     = d->orginating_invocation_id;
300                 m->orginating_usn               = d->orginating_usn;
301                 m->local_usn                    = 0;
302
303                 mc->attribute_name              = dsdb_lDAPDisplayName_by_id(s->schema, a->attid);
304                 mc->version                     = d->version;
305                 mc->originating_last_changed    = d->orginating_time;
306                 mc->originating_dsa_invocation_id= d->orginating_invocation_id;
307                 mc->originating_usn             = d->orginating_usn;
308                 mc->local_usn                   = 0;
309
310                 if (d->orginating_time > whenChanged) {
311                         whenChanged = d->orginating_time;
312                 }
313
314                 if (a->attid == DRSUAPI_ATTRIBUTE_name) {
315                         name_a = a;
316                         name_d = d;
317                         rdn_m = &md.ctr.ctr1.array[md.ctr.ctr1.count];
318                         rdn_mc = &mdc.array[mdc.count];
319                 }
320         }
321
322         if (!name_d) {
323                 return WERR_FOOBAR;
324         }
325
326         ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
327         if (ret != LDB_SUCCESS) {
328                 return WERR_FOOBAR;
329         }
330
331         nt_status = ndr_push_struct_blob(&guid_value, msg, &obj->object.identifier->guid,
332                                          (ndr_push_flags_fn_t)ndr_push_GUID);
333         if (!NT_STATUS_IS_OK(nt_status)) {
334                 return ntstatus_to_werror(nt_status);
335         }
336         ret = ldb_msg_add_value(msg, "objectGUID", &guid_value, NULL);
337         if (ret != LDB_SUCCESS) {
338                 return WERR_FOOBAR;
339         }
340
341         whenChanged_t = nt_time_to_unix(whenChanged);
342         whenChanged_s = ldb_timestring(msg, whenChanged_t);
343         W_ERROR_HAVE_NO_MEMORY(whenChanged_s);
344         ret = ldb_msg_add_string(msg, "whenChanged", whenChanged_s);
345         if (ret != LDB_SUCCESS) {
346                 return WERR_FOOBAR;
347         }
348
349         rdn_m->attid                            = rdn_attid;
350         rdn_m->version                          = name_d->version;
351         rdn_m->orginating_time                  = name_d->orginating_time;
352         rdn_m->orginating_invocation_id         = name_d->orginating_invocation_id;
353         rdn_m->orginating_usn                   = name_d->orginating_usn;
354         rdn_m->local_usn                        = 0;
355         md.ctr.ctr1.count++;
356
357         rdn_mc->attribute_name                  = rdn_attr->lDAPDisplayName;
358         rdn_mc->version                         = name_d->version;
359         rdn_mc->originating_last_changed        = name_d->orginating_time;
360         rdn_mc->originating_dsa_invocation_id   = name_d->orginating_invocation_id;
361         rdn_mc->originating_usn                 = name_d->orginating_usn;
362         rdn_mc->local_usn                       = 0;
363         mdc.count++;
364
365         nt_status = ndr_push_struct_blob(&md_value, msg, &md,
366                                          (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
367         if (!NT_STATUS_IS_OK(nt_status)) {
368                 return ntstatus_to_werror(nt_status);
369         }
370         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL);
371         if (ret != LDB_SUCCESS) {
372                 return WERR_FOOBAR;
373         }
374
375         if (lp_parm_bool(-1, "become dc", "dump objects", False)) {
376                 struct ldb_ldif ldif;
377                 fprintf(stdout, "#\n");
378                 ldif.changetype = LDB_CHANGETYPE_NONE;
379                 ldif.msg = msg;
380                 ldb_ldif_write_file(s->ldb, stdout, &ldif);
381                 NDR_PRINT_DEBUG(drsuapi_DsReplicaObjMetaDataCtr, &mdc);
382         }
383
384         *_msg = msg;
385         return WERR_OK;
386 }
387
388 static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
389                                   const struct libnet_BecomeDC_StoreChunk *c)
390 {
391         WERROR status;
392         struct drsuapi_DsReplicaObjectListItemEx *cur;
393
394         for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
395                 uint32_t i;
396                 bool is_attr = false;
397                 bool is_class = false;
398
399                 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
400                         struct drsuapi_DsReplicaAttribute *a;
401                         uint32_t j;
402                         const char *oid = NULL;
403
404                         a = &cur->object.attribute_ctr.attributes[i];
405                         status = dsdb_map_int2oid(s->schema, a->attid, s, &oid);
406                         if (!W_ERROR_IS_OK(status)) {
407                                 return werror_to_ntstatus(status);
408                         }
409
410                         switch (a->attid) {
411                         case DRSUAPI_ATTRIBUTE_objectClass:
412                                 for (j=0; j < a->value_ctr.num_values; j++) {
413                                         uint32_t val = 0xFFFFFFFF;
414
415                                         if (a->value_ctr.values[i].blob
416                                             && a->value_ctr.values[i].blob->length == 4) {
417                                                 val = IVAL(a->value_ctr.values[i].blob->data,0);
418                                         }
419
420                                         if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
421                                                 is_attr = true;
422                                         }
423                                         if (val == DRSUAPI_OBJECTCLASS_classSchema) {
424                                                 is_class = true;
425                                         }
426                                 }
427
428                                 break;
429                         default:
430                                 break;
431                         }
432                 }
433
434                 if (is_attr) {
435                         struct dsdb_attribute *sa;
436
437                         sa = talloc_zero(s->schema, struct dsdb_attribute);
438                         NT_STATUS_HAVE_NO_MEMORY(sa);
439
440                         status = dsdb_attribute_from_drsuapi(s->schema, &cur->object, s, sa);
441                         if (!W_ERROR_IS_OK(status)) {
442                                 return werror_to_ntstatus(status);
443                         }
444
445                         DLIST_ADD_END(s->schema->attributes, sa, struct dsdb_attribute *);
446                 }
447
448                 if (is_class) {
449                         struct dsdb_class *sc;
450
451                         sc = talloc_zero(s->schema, struct dsdb_class);
452                         NT_STATUS_HAVE_NO_MEMORY(sc);
453
454                         status = dsdb_class_from_drsuapi(s->schema, &cur->object, s, sc);
455                         if (!W_ERROR_IS_OK(status)) {
456                                 return werror_to_ntstatus(status);
457                         }
458
459                         DLIST_ADD_END(s->schema->classes, sc, struct dsdb_class *);
460                 }
461         }
462
463         for (cur = s->schema_part.first_object; cur; cur = cur->next_object) {
464                 struct ldb_message *msg;
465                 status = test_object_to_ldb(s, c, cur, s, &msg);
466                 if (!W_ERROR_IS_OK(status)) {
467                         return werror_to_ntstatus(status);
468                 }
469         }
470
471         return NT_STATUS_OK;
472 }
473
474 static NTSTATUS test_become_dc_schema_chunk(void *private_data,
475                                             const struct libnet_BecomeDC_StoreChunk *c)
476 {
477         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
478         WERROR status;
479         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
480         uint32_t total_object_count;
481         uint32_t object_count;
482         struct drsuapi_DsReplicaObjectListItemEx *first_object;
483         struct drsuapi_DsReplicaObjectListItemEx *cur;
484
485         switch (c->ctr_level) {
486         case 1:
487                 mapping_ctr             = &c->ctr1->mapping_ctr;
488                 total_object_count      = c->ctr1->total_object_count;
489                 object_count            = c->ctr1->object_count;
490                 first_object            = c->ctr1->first_object;
491                 break;
492         case 6:
493                 mapping_ctr             = &c->ctr6->mapping_ctr;
494                 total_object_count      = c->ctr6->total_object_count;
495                 object_count            = c->ctr6->object_count;
496                 first_object            = c->ctr6->first_object;
497                 break;
498         default:
499                 return NT_STATUS_INVALID_PARAMETER;
500         }
501
502         if (total_object_count) {
503                 DEBUG(0,("Schema-DN[%s] objects[%u/%u]\n",
504                         c->partition->nc.dn, object_count, total_object_count));
505         } else {
506                 DEBUG(0,("Schema-DN[%s] objects[%u]\n",
507                 c->partition->nc.dn, object_count));
508         }
509
510         if (!s->schema) {
511                 s->schema = talloc_zero(s, struct dsdb_schema);
512                 NT_STATUS_HAVE_NO_MEMORY(s->schema);
513
514                 status = dsdb_load_oid_mappings(s->schema, mapping_ctr);
515                 if (!W_ERROR_IS_OK(status)) {
516                         return werror_to_ntstatus(status);
517                 }
518         } else {
519                 status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
520                 if (!W_ERROR_IS_OK(status)) {
521                         return werror_to_ntstatus(status);
522                 }
523         }
524
525         if (!s->schema_part.first_object) {
526                 s->schema_part.first_object = talloc_steal(s, first_object);
527         } else {
528                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
529                                                                        first_object);
530         }
531         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
532         s->schema_part.last_object = cur;
533
534         if (c->partition->highwatermark.tmp_highest_usn == c->partition->highwatermark.highest_usn) {
535                 return test_apply_schema(s, c);
536         }
537
538         return NT_STATUS_OK;
539 }
540
541 static NTSTATUS test_become_dc_store_chunk(void *private_data,
542                                            const struct libnet_BecomeDC_StoreChunk *c)
543 {
544         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
545         WERROR status;
546         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
547         uint32_t total_object_count;
548         uint32_t object_count;
549         struct drsuapi_DsReplicaObjectListItemEx *first_object;
550         struct drsuapi_DsReplicaObjectListItemEx *cur;
551         uint32_t linked_attributes_count;
552         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
553         uint32_t i;
554
555         switch (c->ctr_level) {
556         case 1:
557                 mapping_ctr             = &c->ctr1->mapping_ctr;
558                 total_object_count      = c->ctr1->total_object_count;
559                 object_count            = c->ctr1->object_count;
560                 first_object            = c->ctr1->first_object;
561                 linked_attributes_count = 0;
562                 linked_attributes       = NULL;
563                 break;
564         case 6:
565                 mapping_ctr             = &c->ctr6->mapping_ctr;
566                 total_object_count      = c->ctr6->total_object_count;
567                 object_count            = c->ctr6->object_count;
568                 first_object            = c->ctr6->first_object;
569                 linked_attributes_count = c->ctr6->linked_attributes_count;
570                 linked_attributes       = c->ctr6->linked_attributes;
571                 break;
572         default:
573                 return NT_STATUS_INVALID_PARAMETER;
574         }
575
576         if (total_object_count) {
577                 DEBUG(0,("Partition[%s] objects[%u/%u]\n",
578                         c->partition->nc.dn, object_count, total_object_count));
579         } else {
580                 DEBUG(0,("Partition[%s] objects[%u]\n",
581                 c->partition->nc.dn, object_count));
582         }
583
584         status = dsdb_verify_oid_mappings(s->schema, mapping_ctr);
585         if (!W_ERROR_IS_OK(status)) {
586                 return werror_to_ntstatus(status);
587         }
588
589         for (cur = first_object; cur; cur = cur->next_object) {
590                 struct ldb_message *msg;
591                 status = test_object_to_ldb(s, c, cur, s, &msg);
592                 if (!W_ERROR_IS_OK(status)) {
593                         return werror_to_ntstatus(status);
594                 }
595         }
596
597         for (i=0; i < linked_attributes_count; i++) {
598                 const struct dsdb_attribute *sa;
599
600                 if (!linked_attributes[i].identifier) {
601                         return NT_STATUS_FOOBAR;                
602                 }
603
604                 if (!linked_attributes[i].value.blob) {
605                         return NT_STATUS_FOOBAR;                
606                 }
607
608                 sa = dsdb_attribute_by_attributeID_id(s->schema,
609                                                       linked_attributes[i].attid);
610                 if (!sa) {
611                         return NT_STATUS_FOOBAR;
612                 }
613
614                 if (lp_parm_bool(-1, "become dc", "dump objects", False)) {
615                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
616                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
617                         dump_data(0,
618                                 linked_attributes[i].value.blob->data,
619                                 linked_attributes[i].value.blob->length);
620                 }
621         }
622
623         return NT_STATUS_OK;
624 }
625
626 BOOL torture_net_become_dc(struct torture_context *torture)
627 {
628         BOOL ret = True;
629         NTSTATUS status;
630         struct libnet_BecomeDC b;
631         struct libnet_UnbecomeDC u;
632         struct test_become_dc_state *s;
633
634         s = talloc_zero(torture, struct test_become_dc_state);
635         if (!s) return False;
636
637         /* Join domain as a member server. */
638         s->tj = torture_join_domain(TORTURE_NETBIOS_NAME,
639                                  ACB_WSTRUST,
640                                  &s->machine_account);
641         if (!s->tj) {
642                 DEBUG(0, ("%s failed to join domain as workstation\n",
643                           TORTURE_NETBIOS_NAME));
644                 return False;
645         }
646
647         s->ctx = libnet_context_init(event_context_init(s));
648         s->ctx->cred = cmdline_credentials;
649
650         s->ldb = ldb_init(s);
651
652         ZERO_STRUCT(b);
653         b.in.domain_dns_name            = torture_join_dom_dns_name(s->tj);
654         b.in.domain_netbios_name        = torture_join_dom_netbios_name(s->tj);
655         b.in.domain_sid                 = torture_join_sid(s->tj);
656         b.in.source_dsa_address         = lp_parm_string(-1, "torture", "host");
657         b.in.dest_dsa_netbios_name      = TORTURE_NETBIOS_NAME;
658
659         b.in.callbacks.private_data     = s;
660         b.in.callbacks.check_options    = test_become_dc_check_options;
661         b.in.callbacks.prepare_db       = test_become_dc_prepare_db;
662         b.in.callbacks.schema_chunk     = test_become_dc_schema_chunk;
663         b.in.callbacks.config_chunk     = test_become_dc_store_chunk;
664         b.in.callbacks.domain_chunk     = test_become_dc_store_chunk;
665
666         status = libnet_BecomeDC(s->ctx, s, &b);
667         if (!NT_STATUS_IS_OK(status)) {
668                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
669                 ret = False;
670         }
671
672         ZERO_STRUCT(u);
673         u.in.domain_dns_name            = torture_join_dom_dns_name(s->tj);
674         u.in.domain_netbios_name        = torture_join_dom_netbios_name(s->tj);
675         u.in.source_dsa_address         = lp_parm_string(-1, "torture", "host");
676         u.in.dest_dsa_netbios_name      = TORTURE_NETBIOS_NAME;
677
678         status = libnet_UnbecomeDC(s->ctx, s, &u);
679         if (!NT_STATUS_IS_OK(status)) {
680                 printf("libnet_UnbecomeDC() failed - %s\n", nt_errstr(status));
681                 ret = False;
682         }
683
684         /* Leave domain. */                          
685         torture_leave_domain(s->tj);
686
687         talloc_free(s);
688         return ret;
689 }