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