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