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