Merge branch 'master' of /home/tridge/samba/git/combined
[kamenim/samba.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 #include "param/provision.h"
41
42 /* 
43 List of tasks vampire.py must perform:
44 - Domain Join
45  - but don't write the secrets.ldb
46  - results for this should be enough to handle the provision
47 - if vampire method is samsync 
48  - Provision using these results 
49   - do we still want to support this NT4 technology?
50 - Start samsync with libnet code
51  - provision in the callback 
52 - Write out the secrets database, using the code from libnet_Join
53
54 */
55 struct vampire_state {
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         struct tevent_context *event_ctx;
74         unsigned total_objects;
75         char *last_partition;
76 };
77
78 static NTSTATUS vampire_prepare_db(void *private_data,
79                                               const struct libnet_BecomeDC_PrepareDB *p)
80 {
81         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
82         struct provision_settings settings;
83         struct provision_result result;
84         NTSTATUS status;
85
86         ZERO_STRUCT(settings);
87         settings.site_name = p->dest_dsa->site_name;
88         settings.root_dn_str = p->forest->root_dn_str;
89         settings.domain_dn_str = p->domain->dn_str;
90         settings.config_dn_str = p->forest->config_dn_str;
91         settings.schema_dn_str = p->forest->schema_dn_str;
92         settings.netbios_name = p->dest_dsa->netbios_name;
93         settings.realm = s->join->out.realm;
94         settings.domain = s->join->out.domain_name;
95         settings.server_dn_str = p->dest_dsa->server_dn_str;
96         settings.machine_password = generate_random_str(s, 16);
97         settings.targetdir = s->targetdir;
98
99         status = provision_bare(s, s->lp_ctx, &settings, &result);
100
101         if (!NT_STATUS_IS_OK(status)) {
102                 return status;
103         }
104
105         s->ldb = result.samdb;
106         s->lp_ctx = result.lp_ctx;
107
108         /* wrap the entire vapire operation in a transaction.  This
109            isn't just cosmetic - we use this to ensure that linked
110            attribute back links are added at the end by relying on a
111            transaction commit hook in the linked attributes module. We
112            need to do this as the order of objects coming from the
113            server is not sufficiently deterministic to know that the
114            record that a backlink needs to be created in has itself
115            been created before the object containing the forward link
116            has come over the wire */
117         if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
118                 return NT_STATUS_FOOBAR;
119         }
120
121         return NT_STATUS_OK;
122
123
124 }
125
126 static NTSTATUS vampire_check_options(void *private_data,
127                                              const struct libnet_BecomeDC_CheckOptions *o)
128 {
129         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
130
131         DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
132                 s->netbios_name,
133                 o->domain->netbios_name, o->domain->dns_name));
134
135         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
136                 o->source_dsa->dns_name, o->source_dsa->site_name));
137
138         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
139                        "\tschema object_version[%u]\n"
140                        "\tdomain behavior_version[%u]\n"
141                        "\tdomain w2k3_update_revision[%u]\n", 
142                 o->forest->crossref_behavior_version,
143                 o->forest->schema_object_version,
144                 o->domain->behavior_version,
145                 o->domain->w2k3_update_revision));
146
147         return NT_STATUS_OK;
148 }
149
150 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
151                                   const struct libnet_BecomeDC_StoreChunk *c)
152 {
153         WERROR status;
154         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
155         uint32_t object_count;
156         struct drsuapi_DsReplicaObjectListItemEx *first_object;
157         struct drsuapi_DsReplicaObjectListItemEx *cur;
158         uint32_t linked_attributes_count;
159         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
160         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
161         struct dsdb_extended_replicated_objects *objs;
162         struct repsFromTo1 *s_dsa;
163         char *tmp_dns_name;
164         struct ldb_message *msg;
165         struct ldb_val prefixMap_val;
166         struct ldb_message_element *prefixMap_el;
167         struct ldb_val schemaInfo_val;
168         uint32_t i;
169         int ret;
170         bool ok;
171         uint64_t seq_num;
172
173         DEBUG(0,("Analyze and apply schema objects\n"));
174
175         s_dsa                   = talloc_zero(s, struct repsFromTo1);
176         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
177         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
178         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
179
180         switch (c->ctr_level) {
181         case 1:
182                 mapping_ctr                     = &c->ctr1->mapping_ctr;
183                 object_count                    = s->schema_part.object_count;
184                 first_object                    = s->schema_part.first_object;
185                 linked_attributes_count         = 0;
186                 linked_attributes               = NULL;
187                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
188                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
189                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
190                 uptodateness_vector             = NULL; /* TODO: map it */
191                 break;
192         case 6:
193                 mapping_ctr                     = &c->ctr6->mapping_ctr;
194                 object_count                    = s->schema_part.object_count;
195                 first_object                    = s->schema_part.first_object;
196                 linked_attributes_count         = c->ctr6->linked_attributes_count;
197                 linked_attributes               = c->ctr6->linked_attributes;
198                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
199                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
200                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
201                 uptodateness_vector             = c->ctr6->uptodateness_vector;
202                 break;
203         default:
204                 return NT_STATUS_INVALID_PARAMETER;
205         }
206
207         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
208                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
209                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
210         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
211
212         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
213         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
214         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
215         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
216         s_dsa->other_info->dns_name = tmp_dns_name;
217
218         for (cur = first_object; cur; cur = cur->next_object) {
219                 bool is_attr = false;
220                 bool is_class = false;
221
222                 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
223                         struct drsuapi_DsReplicaAttribute *a;
224                         uint32_t j;
225                         const char *oid = NULL;
226
227                         a = &cur->object.attribute_ctr.attributes[i];
228                         status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
229                         if (!W_ERROR_IS_OK(status)) {
230                                 return werror_to_ntstatus(status);
231                         }
232
233                         switch (a->attid) {
234                         case DRSUAPI_ATTRIBUTE_objectClass:
235                                 for (j=0; j < a->value_ctr.num_values; j++) {
236                                         uint32_t val = 0xFFFFFFFF;
237
238                                         if (a->value_ctr.values[j].blob
239                                             && a->value_ctr.values[j].blob->length == 4) {
240                                                 val = IVAL(a->value_ctr.values[j].blob->data,0);
241                                         }
242
243                                         if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
244                                                 is_attr = true;
245                                         }
246                                         if (val == DRSUAPI_OBJECTCLASS_classSchema) {
247                                                 is_class = true;
248                                         }
249                                 }
250
251                                 break;
252                         default:
253                                 break;
254                         }
255                 }
256
257                 if (is_attr) {
258                         struct dsdb_attribute *sa;
259
260                         sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
261                         NT_STATUS_HAVE_NO_MEMORY(sa);
262
263                         status = dsdb_attribute_from_drsuapi(s->ldb, s->self_made_schema, &cur->object, s, sa);
264                         if (!W_ERROR_IS_OK(status)) {
265                                 return werror_to_ntstatus(status);
266                         }
267
268                         DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
269                 }
270
271                 if (is_class) {
272                         struct dsdb_class *sc;
273
274                         sc = talloc_zero(s->self_made_schema, struct dsdb_class);
275                         NT_STATUS_HAVE_NO_MEMORY(sc);
276
277                         status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
278                         if (!W_ERROR_IS_OK(status)) {
279                                 return werror_to_ntstatus(status);
280                         }
281
282                         DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
283                 }
284         }
285
286         /* attach the schema to the ldb */
287         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
288         if (ret != LDB_SUCCESS) {
289                 return NT_STATUS_FOOBAR;
290         }
291         /* we don't want to access the self made schema anymore */
292         s->self_made_schema = NULL;
293         s->schema = dsdb_get_schema(s->ldb);
294
295         status = dsdb_extended_replicated_objects_commit(s->ldb,
296                                                          c->partition->nc.dn,
297                                                          mapping_ctr,
298                                                          object_count,
299                                                          first_object,
300                                                          linked_attributes_count,
301                                                          linked_attributes,
302                                                          s_dsa,
303                                                          uptodateness_vector,
304                                                          c->gensec_skey,
305                                                          s, &objs, &seq_num);
306         if (!W_ERROR_IS_OK(status)) {
307                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
308                 return werror_to_ntstatus(status);
309         }
310
311         if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
312                 for (i=0; i < objs->num_objects; i++) {
313                         struct ldb_ldif ldif;
314                         fprintf(stdout, "#\n");
315                         ldif.changetype = LDB_CHANGETYPE_NONE;
316                         ldif.msg = objs->objects[i].msg;
317                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
318                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
319                 }
320         }
321
322         msg = ldb_msg_new(objs);
323         NT_STATUS_HAVE_NO_MEMORY(msg);
324         msg->dn = objs->partition_dn;
325
326         status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
327         if (!W_ERROR_IS_OK(status)) {
328                 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
329                 return werror_to_ntstatus(status);
330         }
331
332         /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
333         ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
334         if (ret != LDB_SUCCESS) {
335                 return NT_STATUS_FOOBAR;
336         }
337         prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
338
339         ret = ldb_modify(s->ldb, msg);
340         if (ret != LDB_SUCCESS) {
341                 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
342                 return NT_STATUS_FOOBAR;
343         }
344
345         talloc_free(s_dsa);
346         talloc_free(objs);
347
348         /* We must set these up to ensure the replMetaData is written
349          * correctly, before our NTDS Settings entry is replicated */
350         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
351         if (!ok) {
352                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
353                 return NT_STATUS_FOOBAR;
354         }
355         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
356         if (!ok) {
357                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
358                 return NT_STATUS_FOOBAR;
359         }
360
361         s->schema = dsdb_get_schema(s->ldb);
362         if (!s->schema) {
363                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
364                 return NT_STATUS_FOOBAR;
365         }
366
367         return NT_STATUS_OK;
368 }
369
370 static NTSTATUS vampire_schema_chunk(void *private_data,
371                                             const struct libnet_BecomeDC_StoreChunk *c)
372 {
373         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
374         WERROR status;
375         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
376         uint32_t nc_object_count;
377         uint32_t object_count;
378         struct drsuapi_DsReplicaObjectListItemEx *first_object;
379         struct drsuapi_DsReplicaObjectListItemEx *cur;
380         uint32_t nc_linked_attributes_count;
381         uint32_t linked_attributes_count;
382         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
383
384         switch (c->ctr_level) {
385         case 1:
386                 mapping_ctr                     = &c->ctr1->mapping_ctr;
387                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
388                 object_count                    = c->ctr1->object_count;
389                 first_object                    = c->ctr1->first_object;
390                 nc_linked_attributes_count      = 0;
391                 linked_attributes_count         = 0;
392                 linked_attributes               = NULL;
393                 break;
394         case 6:
395                 mapping_ctr                     = &c->ctr6->mapping_ctr;
396                 nc_object_count                 = c->ctr6->nc_object_count;
397                 object_count                    = c->ctr6->object_count;
398                 first_object                    = c->ctr6->first_object;
399                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
400                 linked_attributes_count         = c->ctr6->linked_attributes_count;
401                 linked_attributes               = c->ctr6->linked_attributes;
402                 break;
403         default:
404                 return NT_STATUS_INVALID_PARAMETER;
405         }
406
407         if (nc_object_count) {
408                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
409                         c->partition->nc.dn, object_count, nc_object_count,
410                         linked_attributes_count, nc_linked_attributes_count));
411         } else {
412                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u\n",
413                 c->partition->nc.dn, object_count, linked_attributes_count));
414         }
415
416         if (!s->schema) {
417                 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
418
419                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
420
421                 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
422                 if (!W_ERROR_IS_OK(status)) {
423                         return werror_to_ntstatus(status);
424                 }
425
426                 s->schema = s->self_made_schema;
427         } else {
428                 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
429                 if (!W_ERROR_IS_OK(status)) {
430                         return werror_to_ntstatus(status);
431                 }
432         }
433
434         if (!s->schema_part.first_object) {
435                 s->schema_part.object_count = object_count;
436                 s->schema_part.first_object = talloc_steal(s, first_object);
437         } else {
438                 s->schema_part.object_count             += object_count;
439                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
440                                                                        first_object);
441         }
442         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
443         s->schema_part.last_object = cur;
444
445         if (!c->partition->more_data) {
446                 return vampire_apply_schema(s, c);
447         }
448
449         return NT_STATUS_OK;
450 }
451
452 static NTSTATUS vampire_store_chunk(void *private_data,
453                                            const struct libnet_BecomeDC_StoreChunk *c)
454 {
455         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
456         WERROR status;
457         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
458         uint32_t nc_object_count;
459         uint32_t object_count;
460         struct drsuapi_DsReplicaObjectListItemEx *first_object;
461         uint32_t nc_linked_attributes_count;
462         uint32_t linked_attributes_count;
463         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
464         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
465         struct dsdb_extended_replicated_objects *objs;
466         struct repsFromTo1 *s_dsa;
467         char *tmp_dns_name;
468         uint32_t i;
469         uint64_t seq_num;
470
471         s_dsa                   = talloc_zero(s, struct repsFromTo1);
472         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
473         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
474         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
475
476         switch (c->ctr_level) {
477         case 1:
478                 mapping_ctr                     = &c->ctr1->mapping_ctr;
479                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
480                 object_count                    = c->ctr1->object_count;
481                 first_object                    = c->ctr1->first_object;
482                 nc_linked_attributes_count      = 0;
483                 linked_attributes_count         = 0;
484                 linked_attributes               = NULL;
485                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
486                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
487                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
488                 uptodateness_vector             = NULL; /* TODO: map it */
489                 break;
490         case 6:
491                 mapping_ctr                     = &c->ctr6->mapping_ctr;
492                 nc_object_count                 = c->ctr6->nc_object_count;
493                 object_count                    = c->ctr6->object_count;
494                 first_object                    = c->ctr6->first_object;
495                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
496                 linked_attributes_count         = c->ctr6->linked_attributes_count;
497                 linked_attributes               = c->ctr6->linked_attributes;
498                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
499                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
500                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
501                 uptodateness_vector             = c->ctr6->uptodateness_vector;
502                 break;
503         default:
504                 return NT_STATUS_INVALID_PARAMETER;
505         }
506
507         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
508                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
509                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
510         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
511
512         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
513         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
514         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
515         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
516         s_dsa->other_info->dns_name = tmp_dns_name;
517
518         /* we want to show a count per partition */
519         if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
520                 s->total_objects = 0;
521                 talloc_free(s->last_partition);
522                 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
523         }
524         s->total_objects += object_count;
525
526         if (nc_object_count) {
527                 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
528                         c->partition->nc.dn, s->total_objects, nc_object_count,
529                         linked_attributes_count, nc_linked_attributes_count));
530         } else {
531                 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u\n",
532                 c->partition->nc.dn, s->total_objects, linked_attributes_count));
533         }
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, &seq_num);
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_set_join_secrets *set_secrets;
599         struct libnet_BecomeDC b;
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         s->lp_ctx = ctx->lp_ctx;
617         s->event_ctx = ctx->event_ctx;
618
619         join = talloc_zero(s, struct libnet_JoinDomain);
620         if (!join) {
621                 return NT_STATUS_NO_MEMORY;
622         }
623                 
624         if (r->in.netbios_name != NULL) {
625                 netbios_name = r->in.netbios_name;
626         } else {
627                 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
628                 if (!netbios_name) {
629                         r->out.error_string = NULL;
630                         talloc_free(s);
631                         return NT_STATUS_NO_MEMORY;
632                 }
633         }
634
635         account_name = talloc_asprintf(join, "%s$", netbios_name);
636         if (!account_name) {
637                 r->out.error_string = NULL;
638                 talloc_free(s);
639                 return NT_STATUS_NO_MEMORY;
640         }
641         
642         join->in.domain_name    = r->in.domain_name;
643         join->in.account_name   = account_name;
644         join->in.netbios_name   = netbios_name;
645         join->in.level          = LIBNET_JOINDOMAIN_AUTOMATIC;
646         join->in.acct_type      = ACB_WSTRUST;
647         join->in.recreate_account = false;
648         status = libnet_JoinDomain(ctx, join, join);
649         if (!NT_STATUS_IS_OK(status)) {
650                 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
651                 talloc_free(s);
652                 return status;
653         }
654         
655         s->join = join;
656
657         s->targetdir = r->in.targetdir;
658
659         ZERO_STRUCT(b);
660         b.in.domain_dns_name            = join->out.realm;
661         b.in.domain_netbios_name        = join->out.domain_name;
662         b.in.domain_sid                 = join->out.domain_sid;
663         b.in.source_dsa_address         = join->out.samr_binding->host;
664         b.in.dest_dsa_netbios_name      = netbios_name;
665
666         b.in.callbacks.private_data     = s;
667         b.in.callbacks.check_options    = vampire_check_options;
668         b.in.callbacks.prepare_db       = vampire_prepare_db;
669         b.in.callbacks.schema_chunk     = vampire_schema_chunk;
670         b.in.callbacks.config_chunk     = vampire_store_chunk;
671         b.in.callbacks.domain_chunk     = vampire_store_chunk;
672
673         status = libnet_BecomeDC(ctx, s, &b);
674         if (!NT_STATUS_IS_OK(status)) {
675                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
676                 talloc_free(s);
677                 return status;
678         }
679
680         msg = ldb_msg_new(s);
681         if (!msg) {
682                 printf("ldb_msg_new() failed\n");
683                 talloc_free(s);
684                 return NT_STATUS_NO_MEMORY;
685         }
686         msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
687         if (!msg->dn) {
688                 printf("ldb_msg_new(@ROOTDSE) failed\n");
689                 talloc_free(s);
690                 return NT_STATUS_NO_MEMORY;
691         }
692
693         ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
694         if (ldb_ret != LDB_SUCCESS) {
695                 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
696                 talloc_free(s);
697                 return NT_STATUS_NO_MEMORY;
698         }
699
700         for (i=0; i < msg->num_elements; i++) {
701                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
702         }
703
704         printf("mark ROOTDSE with isSynchronized=TRUE\n");
705         ldb_ret = ldb_modify(s->ldb, msg);
706         if (ldb_ret != LDB_SUCCESS) {
707                 printf("ldb_modify() failed: %d\n", ldb_ret);
708                 talloc_free(s);
709                 return NT_STATUS_INTERNAL_DB_ERROR;
710         }
711
712         /* commit the transaction - this commits all the changes in
713            the ldb from the whole vampire.  Note that this commit
714            triggers the writing of the linked attribute backlinks.
715         */
716         if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
717                 printf("Failed to commit vampire transaction\n");
718                 return NT_STATUS_INTERNAL_DB_ERROR;
719         }
720
721         set_secrets = talloc_zero(s, struct libnet_set_join_secrets);
722         if (!set_secrets) {
723                 return NT_STATUS_NO_MEMORY;
724         }
725                 
726         set_secrets->in.domain_name = join->out.domain_name;
727         set_secrets->in.realm = join->out.realm;
728         set_secrets->in.account_name = account_name;
729         set_secrets->in.netbios_name = netbios_name;
730         set_secrets->in.join_type = SEC_CHAN_BDC;
731         set_secrets->in.join_password = join->out.join_password;
732         set_secrets->in.kvno = join->out.kvno;
733         set_secrets->in.domain_sid = join->out.domain_sid;
734         
735         status = libnet_set_join_secrets(ctx, set_secrets, set_secrets);
736         if (!NT_STATUS_IS_OK(status)) {
737                 r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string);
738                 talloc_free(s);
739                 return status;
740         }
741
742         r->out.domain_name = talloc_steal(r, join->out.domain_name);
743         r->out.domain_sid = talloc_steal(r, join->out.domain_sid);
744         talloc_free(s);
745         
746         return NT_STATUS_OK;
747
748 }