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