Link the new vampire code togeather.
[abartlet/samba.git/.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 };
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_name;
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, 
119            before our NTDS Settings entry is replicated */
120         ok = samdb_set_ntds_invocation_id(s->ldb, &p->dest_dsa->invocation_id);
121         if (!ok) {
122                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
123                 return NT_STATUS_FOOBAR;
124         }
125         s->lp_ctx = lp_ctx;
126
127         return NT_STATUS_OK;
128
129
130 }
131
132 static NTSTATUS vampire_check_options(void *private_data,
133                                              const struct libnet_BecomeDC_CheckOptions *o)
134 {
135         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
136
137         DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
138                 s->netbios_name,
139                 o->domain->netbios_name, o->domain->dns_name));
140
141         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
142                 o->source_dsa->dns_name, o->source_dsa->site_name));
143
144         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
145                        "\tschema object_version[%u]\n"
146                        "\tdomain behavior_version[%u]\n"
147                        "\tdomain w2k3_update_revision[%u]\n", 
148                 o->forest->crossref_behavior_version,
149                 o->forest->schema_object_version,
150                 o->domain->behavior_version,
151                 o->domain->w2k3_update_revision));
152
153         return NT_STATUS_OK;
154 }
155
156 static NTSTATUS vampire_apply_schema(struct vampire_state *s,
157                                   const struct libnet_BecomeDC_StoreChunk *c)
158 {
159         WERROR status;
160         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
161         uint32_t total_object_count;
162         uint32_t object_count;
163         struct drsuapi_DsReplicaObjectListItemEx *first_object;
164         struct drsuapi_DsReplicaObjectListItemEx *cur;
165         uint32_t linked_attributes_count;
166         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
167         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
168         struct dsdb_extended_replicated_objects *objs;
169         struct repsFromTo1 *s_dsa;
170         char *tmp_dns_name;
171         struct ldb_message *msg;
172         struct ldb_val prefixMap_val;
173         struct ldb_message_element *prefixMap_el;
174         struct ldb_val schemaInfo_val;
175         uint32_t i;
176         int ret;
177         bool ok;
178
179         DEBUG(0,("Analyze and apply schema objects\n"));
180
181         s_dsa                   = talloc_zero(s, struct repsFromTo1);
182         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
183         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
184         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
185
186         switch (c->ctr_level) {
187         case 1:
188                 mapping_ctr                     = &c->ctr1->mapping_ctr;
189                 total_object_count              = c->ctr1->total_object_count;
190                 object_count                    = s->schema_part.object_count;
191                 first_object                    = s->schema_part.first_object;
192                 linked_attributes_count         = 0;
193                 linked_attributes               = NULL;
194                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
195                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
196                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
197                 uptodateness_vector             = NULL; /* TODO: map it */
198                 break;
199         case 6:
200                 mapping_ctr                     = &c->ctr6->mapping_ctr;
201                 total_object_count              = c->ctr6->total_object_count;
202                 object_count                    = s->schema_part.object_count;
203                 first_object                    = s->schema_part.first_object;
204                 linked_attributes_count         = 0; /* TODO: ! */
205                 linked_attributes               = NULL; /* TODO: ! */;
206                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
207                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
208                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
209                 uptodateness_vector             = c->ctr6->uptodateness_vector;
210                 break;
211         default:
212                 return NT_STATUS_INVALID_PARAMETER;
213         }
214
215         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
216                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
217                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
218         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
219
220         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
221         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
222         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
223         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
224         s_dsa->other_info->dns_name = tmp_dns_name;
225
226         for (cur = first_object; cur; cur = cur->next_object) {
227                 bool is_attr = false;
228                 bool is_class = false;
229
230                 for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
231                         struct drsuapi_DsReplicaAttribute *a;
232                         uint32_t j;
233                         const char *oid = NULL;
234
235                         a = &cur->object.attribute_ctr.attributes[i];
236                         status = dsdb_map_int2oid(s->self_made_schema, a->attid, s, &oid);
237                         if (!W_ERROR_IS_OK(status)) {
238                                 return werror_to_ntstatus(status);
239                         }
240
241                         switch (a->attid) {
242                         case DRSUAPI_ATTRIBUTE_objectClass:
243                                 for (j=0; j < a->value_ctr.num_values; j++) {
244                                         uint32_t val = 0xFFFFFFFF;
245
246                                         if (a->value_ctr.values[i].blob
247                                             && a->value_ctr.values[i].blob->length == 4) {
248                                                 val = IVAL(a->value_ctr.values[i].blob->data,0);
249                                         }
250
251                                         if (val == DRSUAPI_OBJECTCLASS_attributeSchema) {
252                                                 is_attr = true;
253                                         }
254                                         if (val == DRSUAPI_OBJECTCLASS_classSchema) {
255                                                 is_class = true;
256                                         }
257                                 }
258
259                                 break;
260                         default:
261                                 break;
262                         }
263                 }
264
265                 if (is_attr) {
266                         struct dsdb_attribute *sa;
267
268                         sa = talloc_zero(s->self_made_schema, struct dsdb_attribute);
269                         NT_STATUS_HAVE_NO_MEMORY(sa);
270
271                         status = dsdb_attribute_from_drsuapi(s->self_made_schema, &cur->object, s, sa);
272                         if (!W_ERROR_IS_OK(status)) {
273                                 return werror_to_ntstatus(status);
274                         }
275
276                         DLIST_ADD_END(s->self_made_schema->attributes, sa, struct dsdb_attribute *);
277                 }
278
279                 if (is_class) {
280                         struct dsdb_class *sc;
281
282                         sc = talloc_zero(s->self_made_schema, struct dsdb_class);
283                         NT_STATUS_HAVE_NO_MEMORY(sc);
284
285                         status = dsdb_class_from_drsuapi(s->self_made_schema, &cur->object, s, sc);
286                         if (!W_ERROR_IS_OK(status)) {
287                                 return werror_to_ntstatus(status);
288                         }
289
290                         DLIST_ADD_END(s->self_made_schema->classes, sc, struct dsdb_class *);
291                 }
292         }
293
294         /* attach the schema to the ldb */
295         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
296         if (ret != LDB_SUCCESS) {
297                 return NT_STATUS_FOOBAR;
298         }
299         /* we don't want to access the self made schema anymore */
300         s->self_made_schema = NULL;
301         s->schema = dsdb_get_schema(s->ldb);
302
303         status = dsdb_extended_replicated_objects_commit(s->ldb,
304                                                          c->partition->nc.dn,
305                                                          mapping_ctr,
306                                                          object_count,
307                                                          first_object,
308                                                          linked_attributes_count,
309                                                          linked_attributes,
310                                                          s_dsa,
311                                                          uptodateness_vector,
312                                                          c->gensec_skey,
313                                                          s, &objs);
314         if (!W_ERROR_IS_OK(status)) {
315                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
316                 return werror_to_ntstatus(status);
317         }
318
319         if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
320                 for (i=0; i < objs->num_objects; i++) {
321                         struct ldb_ldif ldif;
322                         fprintf(stdout, "#\n");
323                         ldif.changetype = LDB_CHANGETYPE_NONE;
324                         ldif.msg = objs->objects[i].msg;
325                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
326                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
327                 }
328         }
329
330         msg = ldb_msg_new(objs);
331         NT_STATUS_HAVE_NO_MEMORY(msg);
332         msg->dn = objs->partition_dn;
333
334         status = dsdb_get_oid_mappings_ldb(s->schema, msg, &prefixMap_val, &schemaInfo_val);
335         if (!W_ERROR_IS_OK(status)) {
336                 DEBUG(0,("Failed dsdb_get_oid_mappings_ldb(%s)\n", win_errstr(status)));
337                 return werror_to_ntstatus(status);
338         }
339
340         /* we only add prefixMap here, because schemaInfo is a replicated attribute and already applied */
341         ret = ldb_msg_add_value(msg, "prefixMap", &prefixMap_val, &prefixMap_el);
342         if (ret != LDB_SUCCESS) {
343                 return NT_STATUS_FOOBAR;
344         }
345         prefixMap_el->flags = LDB_FLAG_MOD_REPLACE;
346
347         ret = ldb_modify(s->ldb, msg);
348         if (ret != LDB_SUCCESS) {
349                 DEBUG(0,("Failed to add prefixMap and schemaInfo %s\n", ldb_strerror(ret)));
350                 return NT_STATUS_FOOBAR;
351         }
352
353         talloc_free(s_dsa);
354         talloc_free(objs);
355
356         /* reopen the ldb */
357         talloc_free(s->ldb); /* this also free's the s->schema, because dsdb_set_schema() steals it */
358         s->schema = NULL;
359
360         DEBUG(0,("Reopen the SAM LDB with system credentials and a already stored schema\n"));
361         s->ldb = samdb_connect(s, s->lp_ctx, 
362                                system_session(s, s->lp_ctx));
363         if (!s->ldb) {
364                 DEBUG(0,("Failed to reopen sam.ldb\n"));
365                 return NT_STATUS_INTERNAL_DB_ERROR;
366         }
367
368         /* We must set these up to ensure the replMetaData is written correctly, before our NTDS Settings entry is replicated */
369         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
370         if (!ok) {
371                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
372                 return NT_STATUS_FOOBAR;
373         }
374         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
375         if (!ok) {
376                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
377                 return NT_STATUS_FOOBAR;
378         }
379
380         s->schema = dsdb_get_schema(s->ldb);
381         if (!s->schema) {
382                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
383                 return NT_STATUS_FOOBAR;
384         }
385
386         return NT_STATUS_OK;
387 }
388
389 static NTSTATUS vampire_schema_chunk(void *private_data,
390                                             const struct libnet_BecomeDC_StoreChunk *c)
391 {
392         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
393         WERROR status;
394         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
395         uint32_t total_object_count;
396         uint32_t object_count;
397         struct drsuapi_DsReplicaObjectListItemEx *first_object;
398         struct drsuapi_DsReplicaObjectListItemEx *cur;
399
400         switch (c->ctr_level) {
401         case 1:
402                 mapping_ctr             = &c->ctr1->mapping_ctr;
403                 total_object_count      = c->ctr1->total_object_count;
404                 object_count            = c->ctr1->object_count;
405                 first_object            = c->ctr1->first_object;
406                 break;
407         case 6:
408                 mapping_ctr             = &c->ctr6->mapping_ctr;
409                 total_object_count      = c->ctr6->total_object_count;
410                 object_count            = c->ctr6->object_count;
411                 first_object            = c->ctr6->first_object;
412                 break;
413         default:
414                 return NT_STATUS_INVALID_PARAMETER;
415         }
416
417         if (total_object_count) {
418                 DEBUG(0,("Schema-DN[%s] objects[%u/%u]\n",
419                         c->partition->nc.dn, object_count, total_object_count));
420         } else {
421                 DEBUG(0,("Schema-DN[%s] objects[%u]\n",
422                 c->partition->nc.dn, object_count));
423         }
424
425         if (!s->schema) {
426                 s->self_made_schema = dsdb_new_schema(s, lp_iconv_convenience(s->lp_ctx));
427
428                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
429
430                 status = dsdb_load_oid_mappings_drsuapi(s->self_made_schema, mapping_ctr);
431                 if (!W_ERROR_IS_OK(status)) {
432                         return werror_to_ntstatus(status);
433                 }
434
435                 s->schema = s->self_made_schema;
436         } else {
437                 status = dsdb_verify_oid_mappings_drsuapi(s->schema, mapping_ctr);
438                 if (!W_ERROR_IS_OK(status)) {
439                         return werror_to_ntstatus(status);
440                 }
441         }
442
443         if (!s->schema_part.first_object) {
444                 s->schema_part.object_count = object_count;
445                 s->schema_part.first_object = talloc_steal(s, first_object);
446         } else {
447                 s->schema_part.object_count             += object_count;
448                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
449                                                                        first_object);
450         }
451         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
452         s->schema_part.last_object = cur;
453
454         if (c->partition->highwatermark.tmp_highest_usn == c->partition->highwatermark.highest_usn) {
455                 return vampire_apply_schema(s, c);
456         }
457
458         return NT_STATUS_OK;
459 }
460
461 static NTSTATUS vampire_store_chunk(void *private_data,
462                                            const struct libnet_BecomeDC_StoreChunk *c)
463 {
464         struct vampire_state *s = talloc_get_type(private_data, struct vampire_state);
465         WERROR status;
466         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
467         uint32_t total_object_count;
468         uint32_t object_count;
469         struct drsuapi_DsReplicaObjectListItemEx *first_object;
470         uint32_t linked_attributes_count;
471         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
472         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
473         struct dsdb_extended_replicated_objects *objs;
474         struct repsFromTo1 *s_dsa;
475         char *tmp_dns_name;
476         uint32_t i;
477
478         s_dsa                   = talloc_zero(s, struct repsFromTo1);
479         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
480         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
481         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
482
483         switch (c->ctr_level) {
484         case 1:
485                 mapping_ctr                     = &c->ctr1->mapping_ctr;
486                 total_object_count              = c->ctr1->total_object_count;
487                 object_count                    = c->ctr1->object_count;
488                 first_object                    = c->ctr1->first_object;
489                 linked_attributes_count         = 0;
490                 linked_attributes               = NULL;
491                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
492                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
493                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
494                 uptodateness_vector             = NULL; /* TODO: map it */
495                 break;
496         case 6:
497                 mapping_ctr                     = &c->ctr6->mapping_ctr;
498                 total_object_count              = c->ctr6->total_object_count;
499                 object_count                    = c->ctr6->object_count;
500                 first_object                    = c->ctr6->first_object;
501                 linked_attributes_count         = c->ctr6->linked_attributes_count;
502                 linked_attributes               = c->ctr6->linked_attributes;
503                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
504                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
505                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
506                 uptodateness_vector             = c->ctr6->uptodateness_vector;
507                 break;
508         default:
509                 return NT_STATUS_INVALID_PARAMETER;
510         }
511
512         s_dsa->replica_flags            = DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE
513                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
514                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS;
515         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
516
517         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
518         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
519         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
520         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
521         s_dsa->other_info->dns_name = tmp_dns_name;
522
523         if (total_object_count) {
524                 DEBUG(0,("Partition[%s] objects[%u/%u]\n",
525                         c->partition->nc.dn, object_count, total_object_count));
526         } else {
527                 DEBUG(0,("Partition[%s] objects[%u]\n",
528                 c->partition->nc.dn, object_count));
529         }
530
531         status = dsdb_extended_replicated_objects_commit(s->ldb,
532                                                          c->partition->nc.dn,
533                                                          mapping_ctr,
534                                                          object_count,
535                                                          first_object,
536                                                          linked_attributes_count,
537                                                          linked_attributes,
538                                                          s_dsa,
539                                                          uptodateness_vector,
540                                                          c->gensec_skey,
541                                                          s, &objs);
542         if (!W_ERROR_IS_OK(status)) {
543                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
544                 return werror_to_ntstatus(status);
545         }
546
547         if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
548                 for (i=0; i < objs->num_objects; i++) {
549                         struct ldb_ldif ldif;
550                         fprintf(stdout, "#\n");
551                         ldif.changetype = LDB_CHANGETYPE_NONE;
552                         ldif.msg = objs->objects[i].msg;
553                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
554                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
555                 }
556         }
557         talloc_free(s_dsa);
558         talloc_free(objs);
559
560         for (i=0; i < linked_attributes_count; i++) {
561                 const struct dsdb_attribute *sa;
562
563                 if (!linked_attributes[i].identifier) {
564                         return NT_STATUS_FOOBAR;                
565                 }
566
567                 if (!linked_attributes[i].value.blob) {
568                         return NT_STATUS_FOOBAR;                
569                 }
570
571                 sa = dsdb_attribute_by_attributeID_id(s->schema,
572                                                       linked_attributes[i].attid);
573                 if (!sa) {
574                         return NT_STATUS_FOOBAR;
575                 }
576
577                 if (lp_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
578                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
579                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
580                         dump_data(0,
581                                 linked_attributes[i].value.blob->data,
582                                 linked_attributes[i].value.blob->length);
583                 }
584         }
585
586         return NT_STATUS_OK;
587 }
588
589 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 
590                         struct libnet_Vampire *r)
591 {
592         struct libnet_JoinDomain *join;
593         struct libnet_set_join_secrets *set_secrets;
594         struct libnet_BecomeDC b;
595         struct libnet_UnbecomeDC u;
596         struct vampire_state *s;
597         struct ldb_message *msg;
598         int ldb_ret;
599         uint32_t i;
600         NTSTATUS status;
601
602         const char *account_name;
603         const char *netbios_name;
604         
605         r->out.error_string = NULL;
606
607         s = talloc_zero(mem_ctx , struct vampire_state);
608         if (!s) {
609                 return NT_STATUS_NO_MEMORY;
610         }
611
612         join = talloc_zero(s, struct libnet_JoinDomain);
613         if (!join) {
614                 return NT_STATUS_NO_MEMORY;
615         }
616                 
617         if (r->in.netbios_name != NULL) {
618                 netbios_name = r->in.netbios_name;
619         } else {
620                 netbios_name = talloc_reference(join, lp_netbios_name(ctx->lp_ctx));
621                 if (!netbios_name) {
622                         r->out.error_string = NULL;
623                         talloc_free(s);
624                         return NT_STATUS_NO_MEMORY;
625                 }
626         }
627
628         account_name = talloc_asprintf(join, "%s$", netbios_name);
629         if (!account_name) {
630                 r->out.error_string = NULL;
631                 talloc_free(s);
632                 return NT_STATUS_NO_MEMORY;
633         }
634         
635         join->in.domain_name    = r->in.domain_name;
636         join->in.account_name   = account_name;
637         join->in.netbios_name   = netbios_name;
638         join->in.level          = LIBNET_JOINDOMAIN_AUTOMATIC;
639         join->in.acct_type      = ACB_WSTRUST;
640         join->in.recreate_account = false;
641         status = libnet_JoinDomain(ctx, join, join);
642         if (!NT_STATUS_IS_OK(status)) {
643                 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
644                 talloc_free(s);
645                 return status;
646         }
647         
648         s->join = join;
649
650         s->targetdir = r->in.targetdir;
651
652         ZERO_STRUCT(b);
653         b.in.domain_dns_name            = join->out.realm;
654         b.in.domain_netbios_name        = join->out.domain_name;
655         b.in.domain_sid                 = join->out.domain_sid;
656         b.in.source_dsa_address         = join->out.samr_binding->host;
657         b.in.dest_dsa_netbios_name      = netbios_name;
658
659         b.in.callbacks.private_data     = s;
660         b.in.callbacks.check_options    = vampire_check_options;
661         b.in.callbacks.prepare_db       = vampire_prepare_db;
662         b.in.callbacks.schema_chunk     = vampire_schema_chunk;
663         b.in.callbacks.config_chunk     = vampire_store_chunk;
664         b.in.callbacks.domain_chunk     = vampire_store_chunk;
665
666         status = libnet_BecomeDC(ctx, s, &b);
667         if (!NT_STATUS_IS_OK(status)) {
668                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
669                 talloc_free(s);
670                 return status;
671         }
672
673         msg = ldb_msg_new(s);
674         if (!msg) {
675                 printf("ldb_msg_new() failed\n");
676                 talloc_free(s);
677                 return NT_STATUS_NO_MEMORY;
678         }
679         msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
680         if (!msg->dn) {
681                 printf("ldb_msg_new(@ROOTDSE) failed\n");
682                 talloc_free(s);
683                 return NT_STATUS_NO_MEMORY;
684         }
685
686         ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
687         if (ldb_ret != LDB_SUCCESS) {
688                 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
689                 talloc_free(s);
690                 return NT_STATUS_NO_MEMORY;
691         }
692
693         for (i=0; i < msg->num_elements; i++) {
694                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
695         }
696
697         printf("mark ROOTDSE with isSynchronized=TRUE\n");
698         ldb_ret = ldb_modify(s->ldb, msg);
699         if (ldb_ret != LDB_SUCCESS) {
700                 printf("ldb_modify() failed: %d\n", ldb_ret);
701                 talloc_free(s);
702                 return NT_STATUS_INTERNAL_DB_ERROR;
703         }
704
705         set_secrets = talloc_zero(s, struct libnet_set_join_secrets);
706         if (!set_secrets) {
707                 return NT_STATUS_NO_MEMORY;
708         }
709                 
710         set_secrets->in.domain_name = join->out.domain_name;
711         set_secrets->in.realm = join->out.realm;
712         set_secrets->in.account_name = account_name;
713         set_secrets->in.netbios_name = netbios_name;
714         set_secrets->in.join_type = SEC_CHAN_BDC;
715         set_secrets->in.join_password = join->out.join_password;
716         set_secrets->in.kvno = join->out.kvno;
717         set_secrets->in.domain_sid = join->out.domain_sid;
718         
719         status = libnet_set_join_secrets(ctx, set_secrets, set_secrets);
720         if (!NT_STATUS_IS_OK(status)) {
721                 r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string);
722                 talloc_free(s);
723                 return status;
724         }
725
726         r->out.domain_name = talloc_steal(r, join->out.domain_name);
727         r->out.domain_sid = talloc_steal(r, join->out.domain_sid);
728         talloc_free(s);
729         
730         return NT_STATUS_OK;
731
732 }