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