s4-torture: ran minimal_includes.pl over source4/torture
[samba.git] / source4 / torture / libnet / libnet_BecomeDC.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    libnet_BecomeDC() tests
5
6    Copyright (C) Stefan Metzmacher <metze@samba.org> 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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "torture/rpc/rpc.h"
25 #include "libnet/libnet.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "../lib/util/dlinklist.h"
28 #include "librpc/gen_ndr/ndr_drsuapi.h"
29 #include "librpc/gen_ndr/ndr_drsblobs.h"
30 #include "system/time.h"
31 #include "lib/ldb_wrap.h"
32 #include "auth/auth.h"
33 #include "param/param.h"
34 #include "param/provision.h"
35
36 struct test_become_dc_state {
37         struct libnet_context *ctx;
38         struct torture_context *tctx;
39         const char *netbios_name;
40         struct test_join *tj;
41         struct cli_credentials *machine_account;
42         struct dsdb_schema *self_made_schema;
43         const struct dsdb_schema *schema;
44
45         struct ldb_context *ldb;
46
47         struct {
48                 uint32_t object_count;
49                 struct drsuapi_DsReplicaObjectListItemEx *first_object;
50                 struct drsuapi_DsReplicaObjectListItemEx *last_object;
51         } schema_part;
52
53         const char *targetdir;
54
55         struct loadparm_context *lp_ctx;
56 };
57
58 static NTSTATUS test_become_dc_prepare_db(void *private_data,
59                                               const struct libnet_BecomeDC_PrepareDB *p)
60 {
61         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
62         struct provision_settings settings;
63         struct provision_result result;
64         NTSTATUS status;
65
66         settings.site_name = p->dest_dsa->site_name;
67         settings.root_dn_str = p->forest->root_dn_str;
68         settings.domain_dn_str = p->domain->dn_str;
69         settings.config_dn_str = p->forest->config_dn_str;
70         settings.schema_dn_str = p->forest->schema_dn_str;
71         settings.server_dn_str = torture_join_server_dn_str(s->tj);
72         settings.invocation_id = &p->dest_dsa->invocation_id;
73         settings.netbios_name = p->dest_dsa->netbios_name;
74         settings.host_ip = NULL;
75         settings.realm = torture_join_dom_dns_name(s->tj);
76         settings.domain = torture_join_dom_netbios_name(s->tj);
77         settings.ntds_dn_str = p->dest_dsa->ntds_dn_str;
78         settings.machine_password = cli_credentials_get_password(s->machine_account);
79         settings.targetdir = s->targetdir;
80
81         status = provision_bare(s, s->lp_ctx, &settings, &result);
82         
83         s->ldb = result.samdb;
84         s->lp_ctx = result.lp_ctx;
85         return NT_STATUS_OK;
86
87
88 }
89
90 static NTSTATUS test_become_dc_check_options(void *private_data,
91                                              const struct libnet_BecomeDC_CheckOptions *o)
92 {
93         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
94
95         DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
96                 s->netbios_name,
97                 o->domain->netbios_name, o->domain->dns_name));
98
99         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
100                 o->source_dsa->dns_name, o->source_dsa->site_name));
101
102         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
103                        "\tschema object_version[%u]\n"
104                        "\tdomain behavior_version[%u]\n"
105                        "\tdomain w2k3_update_revision[%u]\n", 
106                 o->forest->crossref_behavior_version,
107                 o->forest->schema_object_version,
108                 o->domain->behavior_version,
109                 o->domain->w2k3_update_revision));
110
111         return NT_STATUS_OK;
112 }
113
114 static NTSTATUS test_apply_schema(struct test_become_dc_state *s,
115                                   const struct libnet_BecomeDC_StoreChunk *c)
116 {
117         WERROR status;
118         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
119         uint32_t object_count;
120         struct drsuapi_DsReplicaObjectListItemEx *first_object;
121         struct drsuapi_DsReplicaObjectListItemEx *cur;
122         uint32_t linked_attributes_count;
123         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
124         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
125         struct dsdb_extended_replicated_objects *objs;
126         struct repsFromTo1 *s_dsa;
127         char *tmp_dns_name;
128         struct ldb_message *msg;
129         struct ldb_val prefixMap_val;
130         struct ldb_message_element *prefixMap_el;
131         struct ldb_val schemaInfo_val;
132         char *sam_ldb_path;
133         uint32_t i;
134         int ret;
135         bool ok;
136         uint64_t seq_num;
137
138         DEBUG(0,("Analyze and apply schema objects\n"));
139
140         s_dsa                   = talloc_zero(s, struct repsFromTo1);
141         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
142         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
143         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
144
145         switch (c->ctr_level) {
146         case 1:
147                 mapping_ctr                     = &c->ctr1->mapping_ctr;
148                 object_count                    = s->schema_part.object_count;
149                 first_object                    = s->schema_part.first_object;
150                 linked_attributes_count         = 0;
151                 linked_attributes               = NULL;
152                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
153                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
154                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
155                 uptodateness_vector             = NULL; /* TODO: map it */
156                 break;
157         case 6:
158                 mapping_ctr                     = &c->ctr6->mapping_ctr;
159                 object_count                    = s->schema_part.object_count;
160                 first_object                    = s->schema_part.first_object;
161                 linked_attributes_count         = 0; /* TODO: ! */
162                 linked_attributes               = NULL; /* TODO: ! */;
163                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
164                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
165                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
166                 uptodateness_vector             = c->ctr6->uptodateness_vector;
167                 break;
168         default:
169                 return NT_STATUS_INVALID_PARAMETER;
170         }
171
172         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
173                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
174                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
175         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
176
177         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
178         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
179         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
180         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
181         s_dsa->other_info->dns_name = tmp_dns_name;
182
183         for (cur = first_object; cur; cur = cur->next_object) {
184                 bool is_attr = false;
185                 bool is_class = false;
186
187                 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
188                         struct drsuapi_DsReplicaAttribute *a;
189                         uint32_t j;
190                         const char *oid = NULL;
191
192                         a = &cur->object.attribute_ctr.attributes[i];
193                         status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
194                         if (!W_ERROR_IS_OK(status)) {
195                                 return werror_to_ntstatus(status);
196                         }
197
198                         switch (a->attid) {
199                         case DRSUAPI_ATTRIBUTE_objectClass:
200                                 for (j=0; j < a->value_ctr.num_values; j++) {
201                                         uint32_t val = 0xFFFFFFFF;
202
203                                         if (a->value_ctr.values[i].blob
204                                             && a->value_ctr.values[i].blob->length == 4) {
205                                                 val = IVAL(a->value_ctr.values[i].blob->data,0);
206                                         }
207
208                                         if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
209                                                 is_attr = true;
210                                         }
211                                         if (val == DRSUAPI_OBJECTCLASS_classSchema) {
212                                                 is_class = true;
213                                         }
214                                 }
215
216                                 break;
217                         default:
218                                 break;
219                         }
220                 }
221
222                 if (is_attr) {
223                         struct dsdb_attribute *sa;
224
225                         sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
226                         NT_STATUS_HAVE_NO_MEMORY(sa);
227
228                         status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
229                         if (!W_ERROR_IS_OK(status)) {
230                                 return werror_to_ntstatus(status);
231                         }
232
233                         DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
234                 }
235
236                 if (is_class) {
237                         struct dsdb_class *sc;
238
239                         sc = talloc_zero(s->self_made_schema, struct dsdb_class);
240                         NT_STATUS_HAVE_NO_MEMORY(sc);
241
242                         status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
243                         if (!W_ERROR_IS_OK(status)) {
244                                 return werror_to_ntstatus(status);
245                         }
246
247                         DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
248                 }
249         }
250
251         /* attach the schema to the ldb */
252         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
253         if (ret != LDB_SUCCESS) {
254                 return NT_STATUS_FOOBAR;
255         }
256         /* we don't want to access the self made schema anymore */
257         s->self_made_schema = NULL;
258         s->schema = dsdb_get_schema(s->ldb);
259
260         status = dsdb_extended_replicated_objects_commit(s->ldb,
261                                                          c->partition->nc.dn,
262                                                          mapping_ctr,
263                                                          object_count,
264                                                          first_object,
265                                                          linked_attributes_count,
266                                                          linked_attributes,
267                                                          s_dsa,
268                                                          uptodateness_vector,
269                                                          c->gensec_skey,
270                                                          s, &objs, &seq_num);
271         if (!W_ERROR_IS_OK(status)) {
272                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
273                 return werror_to_ntstatus(status);
274         }
275
276         if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
277                 for (i=0; i < objs->num_objects; i++) {
278                         struct ldb_ldif ldif;
279                         fprintf(stdout, "#\n");
280                         ldif.changetype = LDB_CHANGETYPE_NONE;
281                         ldif.msg = objs->objects[i].msg;
282                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
283                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
284                 }
285         }
286
287         msg = ldb_msg_new(objs);
288         NT_STATUS_HAVE_NO_MEMORY(msg);
289         msg->dn = objs->partition_dn;
290
291         status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
292         if (!W_ERROR_IS_OK(status)) {
293                 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
294                 return werror_to_ntstatus(status);
295         }
296
297         /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
298         ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
299         if (ret != LDB_SUCCESS) {
300                 return NT_STATUS_FOOBAR;
301         }
302         prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
303
304         ret = ldb_modify(s->ldb, msg);
305         if (ret != LDB_SUCCESS) {
306                 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
307                 return NT_STATUS_FOOBAR;
308         }
309
310         talloc_free(s_dsa);
311         talloc_free(objs);
312
313         /* reopen the ldb */
314         talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
315         s->schema = NULL;
316
317         sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
318         DEBUG(0,("Reopen the SAM LDB with system credentials and a already stored schema: %s\n", sam_ldb_path));
319         s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->tctx->lp_ctx, sam_ldb_path,
320                                   system_session(s, s->tctx->lp_ctx),
321                                   NULL, 0, NULL);
322         if (!s->ldb) {
323                 DEBUG(0,("Failed to open '%s'\n",
324                         sam_ldb_path));
325                 return NT_STATUS_INTERNAL_DB_ERROR;
326         }
327
328         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
329         if (!ok) {
330                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
331                 return NT_STATUS_FOOBAR;
332         }
333         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
334         if (!ok) {
335                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
336                 return NT_STATUS_FOOBAR;
337         }
338
339         s->schema = dsdb_get_schema(s->ldb);
340         if (!s->schema) {
341                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
342                 return NT_STATUS_FOOBAR;
343         }
344
345         return NT_STATUS_OK;
346 }
347
348 static NTSTATUS test_become_dc_schema_chunk(void *private_data,
349                                             const struct libnet_BecomeDC_StoreChunk *c)
350 {
351         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
352         WERROR status;
353         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
354         uint32_t nc_object_count;
355         uint32_t object_count;
356         struct drsuapi_DsReplicaObjectListItemEx *first_object;
357         struct drsuapi_DsReplicaObjectListItemEx *cur;
358         uint32_t nc_linked_attributes_count;
359         uint32_t linked_attributes_count;
360
361         switch (c->ctr_level) {
362         case 1:
363                 mapping_ctr                     = &c->ctr1->mapping_ctr;
364                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
365                 object_count                    = c->ctr1->object_count;
366                 first_object                    = c->ctr1->first_object;
367                 nc_linked_attributes_count      = 0;
368                 linked_attributes_count         = 0;
369                 break;
370         case 6:
371                 mapping_ctr                     = &c->ctr6->mapping_ctr;
372                 nc_object_count                 = c->ctr6->nc_object_count;
373                 object_count                    = c->ctr6->object_count;
374                 first_object                    = c->ctr6->first_object;
375                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
376                 linked_attributes_count         = c->ctr6->linked_attributes_count;
377                 break;
378         default:
379                 return NT_STATUS_INVALID_PARAMETER;
380         }
381
382         if (nc_object_count) {
383                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
384                         c->partition->nc.dn, object_count, nc_object_count,
385                         linked_attributes_count, nc_linked_attributes_count));
386         } else {
387                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u\n",
388                 c->partition->nc.dn, object_count, linked_attributes_count));
389         }
390
391         if (!s->schema) {
392                 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
393
394                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
395
396                 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
397                 if (!W_ERROR_IS_OK(status)) {
398                         return werror_to_ntstatus(status);
399                 }
400
401                 s->schema = s->self_made_schema;
402         } else {
403                 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
404                 if (!W_ERROR_IS_OK(status)) {
405                         return werror_to_ntstatus(status);
406                 }
407         }
408
409         if (!s->schema_part.first_object) {
410                 s->schema_part.object_count = object_count;
411                 s->schema_part.first_object = talloc_steal(s, first_object);
412         } else {
413                 s->schema_part.object_count             += object_count;
414                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
415                                                                        first_object);
416         }
417         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
418         s->schema_part.last_object = cur;
419
420         if (!c->partition->more_data) {
421                 return test_apply_schema(s, c);
422         }
423
424         return NT_STATUS_OK;
425 }
426
427 static NTSTATUS test_become_dc_store_chunk(void *private_data,
428                                            const struct libnet_BecomeDC_StoreChunk *c)
429 {
430         struct test_become_dc_state *s = talloc_get_type(private_data, struct test_become_dc_state);
431         WERROR status;
432         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
433         uint32_t nc_object_count;
434         uint32_t object_count;
435         struct drsuapi_DsReplicaObjectListItemEx *first_object;
436         uint32_t nc_linked_attributes_count;
437         uint32_t linked_attributes_count;
438         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
439         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
440         struct dsdb_extended_replicated_objects *objs;
441         struct repsFromTo1 *s_dsa;
442         char *tmp_dns_name;
443         uint32_t i;
444         uint64_t seq_num;
445
446         s_dsa                   = talloc_zero(s, struct repsFromTo1);
447         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
448         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
449         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
450
451         switch (c->ctr_level) {
452         case 1:
453                 mapping_ctr                     = &c->ctr1->mapping_ctr;
454                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
455                 object_count                    = c->ctr1->object_count;
456                 first_object                    = c->ctr1->first_object;
457                 nc_linked_attributes_count      = 0;
458                 linked_attributes_count         = 0;
459                 linked_attributes               = NULL;
460                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
461                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
462                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
463                 uptodateness_vector             = NULL; /* TODO: map it */
464                 break;
465         case 6:
466                 mapping_ctr                     = &c->ctr6->mapping_ctr;
467                 nc_object_count                 = c->ctr6->nc_object_count;
468                 object_count                    = c->ctr6->object_count;
469                 first_object                    = c->ctr6->first_object;
470                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
471                 linked_attributes_count         = c->ctr6->linked_attributes_count;
472                 linked_attributes               = c->ctr6->linked_attributes;
473                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
474                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
475                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
476                 uptodateness_vector             = c->ctr6->uptodateness_vector;
477                 break;
478         default:
479                 return NT_STATUS_INVALID_PARAMETER;
480         }
481
482         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
483                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
484                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
485         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
486
487         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
488         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
489         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
490         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
491         s_dsa->other_info->dns_name = tmp_dns_name;
492
493         if (nc_object_count) {
494                 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
495                         c->partition->nc.dn, object_count, nc_object_count,
496                         linked_attributes_count, nc_linked_attributes_count));
497         } else {
498                 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u\n",
499                 c->partition->nc.dn, object_count, linked_attributes_count));
500         }
501
502         status = dsdb_extended_replicated_objects_commit(s->ldb,
503                                                          c->partition->nc.dn,
504                                                          mapping_ctr,
505                                                          object_count,
506                                                          first_object,
507                                                          linked_attributes_count,
508                                                          linked_attributes,
509                                                          s_dsa,
510                                                          uptodateness_vector,
511                                                          c->gensec_skey,
512                                                          s, &objs, &seq_num);
513         if (!W_ERROR_IS_OK(status)) {
514                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
515                 return werror_to_ntstatus(status);
516         }
517
518         if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
519                 for (i=0; i < objs->num_objects; i++) {
520                         struct ldb_ldif ldif;
521                         fprintf(stdout, "#\n");
522                         ldif.changetype = LDB_CHANGETYPE_NONE;
523                         ldif.msg = objs->objects[i].msg;
524                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
525                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
526                 }
527         }
528         talloc_free(s_dsa);
529         talloc_free(objs);
530
531         for (i=0; i < linked_attributes_count; i++) {
532                 const struct dsdb_attribute *sa;
533
534                 if (!linked_attributes[i].identifier) {
535                         return NT_STATUS_FOOBAR;                
536                 }
537
538                 if (!linked_attributes[i].value.blob) {
539                         return NT_STATUS_FOOBAR;                
540                 }
541
542                 sa = dsdb_attribute_by_attributeID_id(s->schema,
543                                                       linked_attributes[i].attid);
544                 if (!sa) {
545                         return NT_STATUS_FOOBAR;
546                 }
547
548                 if (lp_parm_bool(s->tctx->lp_ctx, NULL, "become dc", "dump objects", false)) {
549                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
550                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
551                         dump_data(0,
552                                 linked_attributes[i].value.blob->data,
553                                 linked_attributes[i].value.blob->length);
554                 }
555         }
556
557         return NT_STATUS_OK;
558 }
559
560 bool torture_net_become_dc(struct torture_context *torture)
561 {
562         bool ret = true;
563         NTSTATUS status;
564         struct libnet_BecomeDC b;
565         struct libnet_UnbecomeDC u;
566         struct test_become_dc_state *s;
567         struct ldb_message *msg;
568         int ldb_ret;
569         uint32_t i;
570         char *sam_ldb_path;
571
572         char *location = NULL;
573         torture_assert_ntstatus_ok(torture, torture_temp_dir(torture, "libnet_BecomeDC", &location), 
574                                    "torture_temp_dir should return NT_STATUS_OK" );
575
576         s = talloc_zero(torture, struct test_become_dc_state);
577         if (!s) return false;
578
579         s->tctx = torture;
580         s->lp_ctx = torture->lp_ctx;
581
582         s->netbios_name = lp_parm_string(torture->lp_ctx, NULL, "become dc", "smbtorture dc");
583         if (!s->netbios_name || !s->netbios_name[0]) {
584                 s->netbios_name = "smbtorturedc";
585         }
586
587         s->targetdir = location;
588
589         /* Join domain as a member server. */
590         s->tj = torture_join_domain(torture, s->netbios_name,
591                                  ACB_WSTRUST,
592                                  &s->machine_account);
593         if (!s->tj) {
594                 DEBUG(0, ("%s failed to join domain as workstation\n",
595                           s->netbios_name));
596                 return false;
597         }
598
599         s->ctx = libnet_context_init(torture->ev, torture->lp_ctx);
600         s->ctx->cred = cmdline_credentials;
601
602         s->ldb = ldb_init(s, torture->ev);
603
604         ZERO_STRUCT(b);
605         b.in.domain_dns_name            = torture_join_dom_dns_name(s->tj);
606         b.in.domain_netbios_name        = torture_join_dom_netbios_name(s->tj);
607         b.in.domain_sid                 = torture_join_sid(s->tj);
608         b.in.source_dsa_address         = torture_setting_string(torture, "host", NULL);
609         b.in.dest_dsa_netbios_name      = s->netbios_name;
610
611         b.in.callbacks.private_data     = s;
612         b.in.callbacks.check_options    = test_become_dc_check_options;
613         b.in.callbacks.prepare_db = test_become_dc_prepare_db;
614         b.in.callbacks.schema_chunk     = test_become_dc_schema_chunk;
615         b.in.callbacks.config_chunk     = test_become_dc_store_chunk;
616         b.in.callbacks.domain_chunk     = test_become_dc_store_chunk;
617
618         status = libnet_BecomeDC(s->ctx, s, &b);
619         if (!NT_STATUS_IS_OK(status)) {
620                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
621                 ret = false;
622                 goto cleanup;
623         }
624
625         msg = ldb_msg_new(s);
626         if (!msg) {
627                 printf("ldb_msg_new() failed\n");
628                 ret = false;
629                 goto cleanup;
630         }
631         msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
632         if (!msg->dn) {
633                 printf("ldb_msg_new(@ROOTDSE) failed\n");
634                 ret = false;
635                 goto cleanup;
636         }
637
638         ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
639         if (ldb_ret != LDB_SUCCESS) {
640                 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
641                 ret = false;
642                 goto cleanup;
643         }
644
645         for (i=0; i < msg->num_elements; i++) {
646                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
647         }
648
649         printf("mark ROOTDSE with isSynchronized=TRUE\n");
650         ldb_ret = ldb_modify(s->ldb, msg);
651         if (ldb_ret != LDB_SUCCESS) {
652                 printf("ldb_modify() failed: %d\n", ldb_ret);
653                 ret = false;
654                 goto cleanup;
655         }
656         
657         /* reopen the ldb */
658         talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
659         s->schema = NULL;
660
661         sam_ldb_path = talloc_asprintf(s, "%s/%s", s->targetdir, "private/sam.ldb");
662         DEBUG(0,("Reopen the SAM LDB with system credentials and all replicated data: %s\n", sam_ldb_path));
663         s->ldb = ldb_wrap_connect(s, s->tctx->ev, s->lp_ctx, sam_ldb_path,
664                                   system_session(s, s->lp_ctx),
665                                   NULL, 0, NULL);
666         if (!s->ldb) {
667                 DEBUG(0,("Failed to open '%s'\n",
668                         sam_ldb_path));
669                 ret = false;
670                 goto cleanup;
671         }
672
673         s->schema = dsdb_get_schema(s->ldb);
674         if (!s->schema) {
675                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
676                 ret = false;
677                 goto cleanup;
678         }
679
680         /* Make sure we get this from the command line */
681         if (lp_parm_bool(torture->lp_ctx, NULL, "become dc", "do not unjoin", false)) {
682                 talloc_free(s);
683                 return ret;
684         }
685
686 cleanup:
687         ZERO_STRUCT(u);
688         u.in.domain_dns_name            = torture_join_dom_dns_name(s->tj);
689         u.in.domain_netbios_name        = torture_join_dom_netbios_name(s->tj);
690         u.in.source_dsa_address         = torture_setting_string(torture, "host", NULL);
691         u.in.dest_dsa_netbios_name      = s->netbios_name;
692
693         status = libnet_UnbecomeDC(s->ctx, s, &u);
694         if (!NT_STATUS_IS_OK(status)) {
695                 printf("libnet_UnbecomeDC() failed - %s\n", nt_errstr(status));
696                 ret = false;
697         }
698
699         /* Leave domain. */                          
700         torture_leave_domain(torture, s->tj);
701
702         talloc_free(s);
703         return ret;
704 }