s4-repl: Allow dsdb_replicated_objects_commit() to use different schema while committ...
[kai/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 "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/security.h"
43 #include "dsdb/common/util.h"
44
45 /* 
46 List of tasks vampire.py must perform:
47 - Domain Join
48  - but don't write the secrets.ldb
49  - results for this should be enough to handle the provision
50 - if vampire method is samsync 
51  - Provision using these results 
52   - do we still want to support this NT4 technology?
53 - Start samsync with libnet code
54  - provision in the callback 
55 - Write out the secrets database, using the code from libnet_Join
56
57 */
58 struct libnet_vampire_cb_state {
59         const char *netbios_name;
60         const char *domain_name;
61         const char *realm;
62         struct cli_credentials *machine_account;
63
64         /* Schema loaded from local LDIF files */
65         struct dsdb_schema *provision_schema;
66
67         /* 1st pass, with some OIDs/attribute names/class names not
68          * converted, because we may not know them yet */
69         struct dsdb_schema *self_made_schema;
70
71         /* prefixMap in LDB format, from the remote DRS server */
72         DATA_BLOB prefixmap_blob;
73         const struct dsdb_schema *schema;
74
75         struct ldb_context *ldb;
76
77         struct {
78                 uint32_t object_count;
79                 struct drsuapi_DsReplicaObjectListItemEx *first_object;
80                 struct drsuapi_DsReplicaObjectListItemEx *last_object;
81         } schema_part;
82
83         const char *targetdir;
84
85         struct loadparm_context *lp_ctx;
86         struct tevent_context *event_ctx;
87         unsigned total_objects;
88         char *last_partition;
89         const char *server_dn_str;
90 };
91
92 /* initialise a state structure ready for replication of chunks */
93 void *libnet_vampire_replicate_init(TALLOC_CTX *mem_ctx,
94                                     struct ldb_context *samdb,
95                                     struct loadparm_context *lp_ctx)
96 {
97         struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
98         if (!s) {
99                 return NULL;
100         }
101
102         s->ldb              = samdb;
103         s->lp_ctx           = lp_ctx;
104         s->provision_schema = dsdb_get_schema(s->ldb, s);
105         s->schema           = s->provision_schema;
106         s->netbios_name     = lpcfg_netbios_name(lp_ctx);
107         s->domain_name      = lpcfg_workgroup(lp_ctx);
108         s->realm            = lpcfg_realm(lp_ctx);
109
110         return s;
111 }
112
113 /* Caller is expected to keep supplied pointers around for the lifetime of the structure */
114 void *libnet_vampire_cb_state_init(TALLOC_CTX *mem_ctx,
115                                    struct loadparm_context *lp_ctx, struct tevent_context *event_ctx,
116                                    const char *netbios_name, const char *domain_name, const char *realm,
117                                    const char *targetdir)
118 {
119         struct libnet_vampire_cb_state *s = talloc_zero(mem_ctx, struct libnet_vampire_cb_state);
120         if (!s) {
121                 return NULL;
122         }
123
124         s->lp_ctx = lp_ctx;
125         s->event_ctx = event_ctx;
126         s->netbios_name = netbios_name;
127         s->domain_name = domain_name;
128         s->realm = realm;
129         s->targetdir = targetdir;
130         return s;
131 }
132
133 struct ldb_context *libnet_vampire_cb_ldb(struct libnet_vampire_cb_state *state)
134 {
135         state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
136         return state->ldb;
137 }
138
139 struct loadparm_context *libnet_vampire_cb_lp_ctx(struct libnet_vampire_cb_state *state)
140 {
141         state = talloc_get_type_abort(state, struct libnet_vampire_cb_state);
142         return state->lp_ctx;
143 }
144
145 NTSTATUS libnet_vampire_cb_prepare_db(void *private_data,
146                                       const struct libnet_BecomeDC_PrepareDB *p)
147 {
148         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
149         struct provision_settings settings;
150         struct provision_result result;
151         NTSTATUS status;
152
153         ZERO_STRUCT(settings);
154         settings.site_name = p->dest_dsa->site_name;
155         settings.root_dn_str = p->forest->root_dn_str;
156         settings.domain_dn_str = p->domain->dn_str;
157         settings.config_dn_str = p->forest->config_dn_str;
158         settings.schema_dn_str = p->forest->schema_dn_str;
159         settings.netbios_name = p->dest_dsa->netbios_name;
160         settings.realm = s->realm;
161         settings.domain = s->domain_name;
162         settings.server_dn_str = p->dest_dsa->server_dn_str;
163         settings.machine_password = generate_random_password(s, 16, 255);
164         settings.targetdir = s->targetdir;
165
166         status = provision_bare(s, s->lp_ctx, &settings, &result);
167
168         if (!NT_STATUS_IS_OK(status)) {
169                 return status;
170         }
171
172         s->ldb = talloc_steal(s, result.samdb);
173         s->lp_ctx = talloc_reparent(talloc_parent(result.lp_ctx), s, result.lp_ctx);
174         s->provision_schema = dsdb_get_schema(s->ldb, s);
175         s->server_dn_str = talloc_steal(s, p->dest_dsa->server_dn_str);
176
177         /* wrap the entire vapire operation in a transaction.  This
178            isn't just cosmetic - we use this to ensure that linked
179            attribute back links are added at the end by relying on a
180            transaction commit hook in the linked attributes module. We
181            need to do this as the order of objects coming from the
182            server is not sufficiently deterministic to know that the
183            record that a backlink needs to be created in has itself
184            been created before the object containing the forward link
185            has come over the wire */
186         if (ldb_transaction_start(s->ldb) != LDB_SUCCESS) {
187                 return NT_STATUS_FOOBAR;
188         }
189
190         return NT_STATUS_OK;
191
192
193 }
194
195 NTSTATUS libnet_vampire_cb_check_options(void *private_data,
196                                          const struct libnet_BecomeDC_CheckOptions *o)
197 {
198         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
199
200         DEBUG(0,("Become DC [%s] of Domain[%s]/[%s]\n",
201                 s->netbios_name,
202                 o->domain->netbios_name, o->domain->dns_name));
203
204         DEBUG(0,("Promotion Partner is Server[%s] from Site[%s]\n",
205                 o->source_dsa->dns_name, o->source_dsa->site_name));
206
207         DEBUG(0,("Options:crossRef behavior_version[%u]\n"
208                        "\tschema object_version[%u]\n"
209                        "\tdomain behavior_version[%u]\n"
210                        "\tdomain w2k3_update_revision[%u]\n", 
211                 o->forest->crossref_behavior_version,
212                 o->forest->schema_object_version,
213                 o->domain->behavior_version,
214                 o->domain->w2k3_update_revision));
215
216         return NT_STATUS_OK;
217 }
218
219 static NTSTATUS libnet_vampire_cb_apply_schema(struct libnet_vampire_cb_state *s,
220                                                const struct libnet_BecomeDC_StoreChunk *c)
221 {
222         struct schema_list {
223                 struct schema_list *next, *prev;
224                 const struct drsuapi_DsReplicaObjectListItemEx *obj;
225         };
226
227         WERROR status;
228         struct dsdb_schema_prefixmap *pfm_remote;
229         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
230         struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item;
231         struct dsdb_schema *working_schema;
232         struct dsdb_schema *provision_schema;
233         uint32_t object_count = 0;
234         struct drsuapi_DsReplicaObjectListItemEx *first_object;
235         const struct drsuapi_DsReplicaObjectListItemEx *cur;
236         uint32_t linked_attributes_count;
237         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
238         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
239         struct dsdb_extended_replicated_objects *schema_objs;
240         struct repsFromTo1 *s_dsa;
241         char *tmp_dns_name;
242         struct ldb_context *schema_ldb;
243         struct ldb_message *msg;
244         struct ldb_message_element *prefixMap_el;
245         uint32_t i;
246         int ret, pass_no;
247         bool ok;
248         uint64_t seq_num;
249
250         DEBUG(0,("Analyze and apply schema objects\n"));
251
252         s_dsa                   = talloc_zero(s, struct repsFromTo1);
253         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
254         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
255         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
256
257         switch (c->ctr_level) {
258         case 1:
259                 mapping_ctr                     = &c->ctr1->mapping_ctr;
260                 object_count                    = s->schema_part.object_count;
261                 first_object                    = s->schema_part.first_object;
262                 linked_attributes_count         = 0;
263                 linked_attributes               = NULL;
264                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
265                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
266                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
267                 uptodateness_vector             = NULL; /* TODO: map it */
268                 break;
269         case 6:
270                 mapping_ctr                     = &c->ctr6->mapping_ctr;
271                 object_count                    = s->schema_part.object_count;
272                 first_object                    = s->schema_part.first_object;
273                 linked_attributes_count         = c->ctr6->linked_attributes_count;
274                 linked_attributes               = c->ctr6->linked_attributes;
275                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
276                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
277                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
278                 uptodateness_vector             = c->ctr6->uptodateness_vector;
279                 break;
280         default:
281                 return NT_STATUS_INVALID_PARAMETER;
282         }
283
284         status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
285                                                   s, &pfm_remote, NULL);
286         if (!W_ERROR_IS_OK(status)) {
287                 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
288                          win_errstr(status)));
289                 return werror_to_ntstatus(status);
290         }
291
292         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
293                                         | DRSUAPI_DRS_INIT_SYNC
294                                         | DRSUAPI_DRS_PER_SYNC;
295         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
296
297         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
298         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
299         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
300         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
301         s_dsa->other_info->dns_name = tmp_dns_name;
302
303         schema_ldb = provision_get_schema(s, s->lp_ctx, &s->prefixmap_blob);
304         if (!schema_ldb) {
305                 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
306                          "Will continue with local prefixMap\n"));
307                 provision_schema = dsdb_get_schema(s->ldb, s);
308         } else {
309                 provision_schema = dsdb_get_schema(schema_ldb, s);
310                 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
311                 if (ret != LDB_SUCCESS) {
312                         DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
313                         return NT_STATUS_UNSUCCESSFUL;
314                 }
315                 talloc_free(schema_ldb);
316         }
317
318         /* create a list of objects yet to be converted */
319         for (cur = first_object; cur; cur = cur->next_object) {
320                 schema_list_item = talloc(s, struct schema_list);
321                 schema_list_item->obj = cur;
322                 DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
323         }
324
325         /* resolve objects until all are resolved and in local schema */
326         pass_no = 1;
327         working_schema = provision_schema;
328
329         while (schema_list) {
330                 uint32_t converted_obj_count = 0;
331                 uint32_t failed_obj_count = 0;
332                 TALLOC_CTX *tmp_ctx = talloc_new(s);
333                 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
334
335                 for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) {
336                         struct dsdb_extended_replicated_object object;
337
338                         cur = schema_list_item->obj;
339
340                         /* Save the next item, now we have saved out
341                          * the current one, so we can DLIST_REMOVE it
342                          * safely */
343                         schema_list_next_item = schema_list_item->next;
344
345                         /*
346                          * Convert the objects into LDB messages using the
347                          * schema we have so far. It's ok if we fail to convert
348                          * an object. We should convert more objects on next pass.
349                          */
350                         status = dsdb_convert_object_ex(s->ldb, working_schema, pfm_remote,
351                                                         cur, c->gensec_skey,
352                                                         tmp_ctx, &object);
353                         if (!W_ERROR_IS_OK(status)) {
354                                 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
355                                          cur->object.identifier->dn));
356
357                                 failed_obj_count++;
358                         } else {
359                                 /*
360                                  * Convert the schema from ldb_message format
361                                  * (OIDs as OID strings) into schema, using
362                                  * the remote prefixMap
363                                  */
364                                 status = dsdb_schema_set_el_from_ldb_msg(s->ldb,
365                                                                          s->self_made_schema,
366                                                                          object.msg);
367                                 if (!W_ERROR_IS_OK(status)) {
368                                         DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
369                                                  ldb_dn_get_linearized(object.msg->dn),
370                                                  win_errstr(status)));
371                                         failed_obj_count++;
372                                 } else {
373                                         DLIST_REMOVE(schema_list, schema_list_item);
374                                         converted_obj_count++;
375                                 }
376                         }
377                 }
378                 talloc_free(tmp_ctx);
379
380                 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
381                          pass_no, failed_obj_count, converted_obj_count, object_count));
382                 pass_no++;
383
384                 /* check if we converted any objects in this pass */
385                 if (converted_obj_count == 0) {
386                         DEBUG(0,("Can't continue Schema load: didn't manage to convert any objects: all %d remaining of %d objects failed to convert\n", failed_obj_count, object_count));
387                         return NT_STATUS_INTERNAL_ERROR;
388                 }
389
390                 if (schema_list) {
391                         /* prepare for another cycle */
392                         working_schema = s->self_made_schema;
393
394                         ret = dsdb_setup_sorted_accessors(s->ldb, working_schema);
395                         if (LDB_SUCCESS != ret) {
396                                 DEBUG(0,("Failed to create schema-cache indexes!\n"));
397                                 return NT_STATUS_INTERNAL_ERROR;
398                         }
399                 }
400         };
401
402         /* free temp objects for 1st conversion phase */
403         talloc_unlink(s, provision_schema);
404         TALLOC_FREE(schema_list);
405
406         /*
407          * attach the schema we just brought over DRS to the ldb,
408          * so we can use it in dsdb_convert_object_ex below
409          */
410         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
411         if (ret != LDB_SUCCESS) {
412                 DEBUG(0,("Failed to attach working schema from DRS.\n"));
413                 return NT_STATUS_FOOBAR;
414         }
415
416         /* we don't want to access the self made schema anymore */
417         s->schema = s->self_made_schema;
418         s->self_made_schema = NULL;
419
420         /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
421         status = dsdb_replicated_objects_convert(s->ldb,
422                                                  s->schema,
423                                                  c->partition->nc.dn,
424                                                  mapping_ctr,
425                                                  object_count,
426                                                  first_object,
427                                                  linked_attributes_count,
428                                                  linked_attributes,
429                                                  s_dsa,
430                                                  uptodateness_vector,
431                                                  c->gensec_skey,
432                                                  s, &schema_objs);
433         if (!W_ERROR_IS_OK(status)) {
434                 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
435                 return werror_to_ntstatus(status);
436         }
437
438         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
439                 for (i=0; i < schema_objs->num_objects; i++) {
440                         struct ldb_ldif ldif;
441                         fprintf(stdout, "#\n");
442                         ldif.changetype = LDB_CHANGETYPE_NONE;
443                         ldif.msg = schema_objs->objects[i].msg;
444                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
445                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
446                 }
447         }
448
449         status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
450         if (!W_ERROR_IS_OK(status)) {
451                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
452                 return werror_to_ntstatus(status);
453         }
454
455         msg = ldb_msg_new(schema_objs);
456         NT_STATUS_HAVE_NO_MEMORY(msg);
457         msg->dn = schema_objs->partition_dn;
458
459         /* We must ensure a prefixMap has been written.  Unlike other
460          * attributes (including schemaInfo), it is not replicated in
461          * the normal replication stream.  We can use the one from
462          * s->prefixmap_blob because we operate with one, unchanging
463          * prefixMap for this entire operation.  */
464         ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
465         if (ret != LDB_SUCCESS) {
466                 return NT_STATUS_FOOBAR;
467         }
468         /* We want to know if a prefixMap was written already, as it
469          * would mean that the above comment was not true, and we have
470          * somehow updated the prefixMap during this transaction */
471         prefixMap_el->flags = LDB_FLAG_MOD_ADD;
472
473         ret = ldb_modify(s->ldb, msg);
474         if (ret != LDB_SUCCESS) {
475                 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
476                 return NT_STATUS_FOOBAR;
477         }
478
479         talloc_free(s_dsa);
480         talloc_free(schema_objs);
481
482         /* We must set these up to ensure the replMetaData is written
483          * correctly, before our NTDS Settings entry is replicated */
484         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
485         if (!ok) {
486                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
487                 return NT_STATUS_FOOBAR;
488         }
489         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
490         if (!ok) {
491                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
492                 return NT_STATUS_FOOBAR;
493         }
494
495         s->schema = dsdb_get_schema(s->ldb, s);
496         if (!s->schema) {
497                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
498                 return NT_STATUS_FOOBAR;
499         }
500
501         return NT_STATUS_OK;
502 }
503
504 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
505                                         const struct libnet_BecomeDC_StoreChunk *c)
506 {
507         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
508         WERROR status;
509         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
510         uint32_t nc_object_count;
511         uint32_t object_count;
512         struct drsuapi_DsReplicaObjectListItemEx *first_object;
513         struct drsuapi_DsReplicaObjectListItemEx *cur;
514         uint32_t nc_linked_attributes_count;
515         uint32_t linked_attributes_count;
516         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
517
518         switch (c->ctr_level) {
519         case 1:
520                 mapping_ctr                     = &c->ctr1->mapping_ctr;
521                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
522                 object_count                    = c->ctr1->object_count;
523                 first_object                    = c->ctr1->first_object;
524                 nc_linked_attributes_count      = 0;
525                 linked_attributes_count         = 0;
526                 linked_attributes               = NULL;
527                 break;
528         case 6:
529                 mapping_ctr                     = &c->ctr6->mapping_ctr;
530                 nc_object_count                 = c->ctr6->nc_object_count;
531                 object_count                    = c->ctr6->object_count;
532                 first_object                    = c->ctr6->first_object;
533                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
534                 linked_attributes_count         = c->ctr6->linked_attributes_count;
535                 linked_attributes               = c->ctr6->linked_attributes;
536                 break;
537         default:
538                 return NT_STATUS_INVALID_PARAMETER;
539         }
540
541         if (nc_object_count) {
542                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
543                         c->partition->nc.dn, object_count, nc_object_count,
544                         linked_attributes_count, nc_linked_attributes_count));
545         } else {
546                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
547                 c->partition->nc.dn, object_count, linked_attributes_count));
548         }
549
550         if (!s->self_made_schema) {
551                 WERROR werr;
552                 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
553                 /* Put the DRS prefixmap aside for the schema we are
554                  * about to load in the provision, and into the one we
555                  * are making with the help of DRS */
556
557                 mapping_ctr_without_schema_info = *mapping_ctr;
558
559                 /* This strips off the 0xFF schema info from the end,
560                  * because we don't want it in the blob */
561                 if (mapping_ctr_without_schema_info.num_mappings > 0) {
562                         mapping_ctr_without_schema_info.num_mappings--;
563                 }
564                 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
565                 if (!W_ERROR_IS_OK(werr)) {
566                         return werror_to_ntstatus(werr);
567                 }
568
569                 /* Set up two manually-constructed schema - the local
570                  * schema from the provision will be used to build
571                  * one, which will then in turn be used to build the
572                  * other. */
573                 s->self_made_schema = dsdb_new_schema(s);
574                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
575
576                 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
577                 if (!W_ERROR_IS_OK(status)) {
578                         return werror_to_ntstatus(status);
579                 }
580         } else {
581                 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
582                 if (!W_ERROR_IS_OK(status)) {
583                         return werror_to_ntstatus(status);
584                 }
585         }
586
587         if (!s->schema_part.first_object) {
588                 s->schema_part.object_count = object_count;
589                 s->schema_part.first_object = talloc_steal(s, first_object);
590         } else {
591                 s->schema_part.object_count             += object_count;
592                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
593                                                                        first_object);
594         }
595         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
596         s->schema_part.last_object = cur;
597
598         if (!c->partition->more_data) {
599                 return libnet_vampire_cb_apply_schema(s, c);
600         }
601
602         return NT_STATUS_OK;
603 }
604
605 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
606                              const struct libnet_BecomeDC_StoreChunk *c)
607 {
608         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
609         WERROR status;
610         struct dsdb_schema *schema;
611         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
612         uint32_t nc_object_count;
613         uint32_t object_count;
614         struct drsuapi_DsReplicaObjectListItemEx *first_object;
615         uint32_t nc_linked_attributes_count;
616         uint32_t linked_attributes_count;
617         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
618         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
619         struct dsdb_extended_replicated_objects *objs;
620         struct repsFromTo1 *s_dsa;
621         char *tmp_dns_name;
622         uint32_t i;
623         uint64_t seq_num;
624
625         s_dsa                   = talloc_zero(s, struct repsFromTo1);
626         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
627         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
628         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
629
630         switch (c->ctr_level) {
631         case 1:
632                 mapping_ctr                     = &c->ctr1->mapping_ctr;
633                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
634                 object_count                    = c->ctr1->object_count;
635                 first_object                    = c->ctr1->first_object;
636                 nc_linked_attributes_count      = 0;
637                 linked_attributes_count         = 0;
638                 linked_attributes               = NULL;
639                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
640                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
641                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
642                 uptodateness_vector             = NULL; /* TODO: map it */
643                 break;
644         case 6:
645                 mapping_ctr                     = &c->ctr6->mapping_ctr;
646                 nc_object_count                 = c->ctr6->nc_object_count;
647                 object_count                    = c->ctr6->object_count;
648                 first_object                    = c->ctr6->first_object;
649                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
650                 linked_attributes_count         = c->ctr6->linked_attributes_count;
651                 linked_attributes               = c->ctr6->linked_attributes;
652                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
653                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
654                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
655                 uptodateness_vector             = c->ctr6->uptodateness_vector;
656                 break;
657         default:
658                 return NT_STATUS_INVALID_PARAMETER;
659         }
660
661         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
662                                         | DRSUAPI_DRS_INIT_SYNC
663                                         | DRSUAPI_DRS_PER_SYNC;
664         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
665
666         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
667         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
668         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
669         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
670         s_dsa->other_info->dns_name = tmp_dns_name;
671
672         /* we want to show a count per partition */
673         if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
674                 s->total_objects = 0;
675                 talloc_free(s->last_partition);
676                 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
677         }
678         s->total_objects += object_count;
679
680         if (nc_object_count) {
681                 DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
682                         c->partition->nc.dn, s->total_objects, nc_object_count,
683                         linked_attributes_count, nc_linked_attributes_count));
684         } else {
685                 DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
686                 c->partition->nc.dn, s->total_objects, linked_attributes_count));
687         }
688
689
690         schema = dsdb_get_schema(s->ldb, NULL);
691         if (!schema) {
692                 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
693                 return NT_STATUS_INTERNAL_ERROR;
694         }
695
696         status = dsdb_replicated_objects_convert(s->ldb,
697                                                  schema,
698                                                  c->partition->nc.dn,
699                                                  mapping_ctr,
700                                                  object_count,
701                                                  first_object,
702                                                  linked_attributes_count,
703                                                  linked_attributes,
704                                                  s_dsa,
705                                                  uptodateness_vector,
706                                                  c->gensec_skey,
707                                                  s, &objs);
708         if (!W_ERROR_IS_OK(status)) {
709                 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
710                 return werror_to_ntstatus(status);
711         }
712
713         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
714                 for (i=0; i < objs->num_objects; i++) {
715                         struct ldb_ldif ldif;
716                         fprintf(stdout, "#\n");
717                         ldif.changetype = LDB_CHANGETYPE_NONE;
718                         ldif.msg = objs->objects[i].msg;
719                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
720                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
721                 }
722         }
723         status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
724         if (!W_ERROR_IS_OK(status)) {
725                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
726                 return werror_to_ntstatus(status);
727         }
728
729         talloc_free(s_dsa);
730         talloc_free(objs);
731
732         for (i=0; i < linked_attributes_count; i++) {
733                 const struct dsdb_attribute *sa;
734
735                 if (!linked_attributes[i].identifier) {
736                         return NT_STATUS_FOOBAR;                
737                 }
738
739                 if (!linked_attributes[i].value.blob) {
740                         return NT_STATUS_FOOBAR;                
741                 }
742
743                 sa = dsdb_attribute_by_attributeID_id(s->schema,
744                                                       linked_attributes[i].attid);
745                 if (!sa) {
746                         return NT_STATUS_FOOBAR;
747                 }
748
749                 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
750                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
751                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
752                         dump_data(0,
753                                 linked_attributes[i].value.blob->data,
754                                 linked_attributes[i].value.blob->length);
755                 }
756         }
757
758         return NT_STATUS_OK;
759 }
760
761 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
762                                               struct ldb_context *ldb,
763                                               const char *server_dn_str,
764                                               const char *netbios_name,
765                                               const char *realm)
766 {
767         int ret;
768         struct ldb_message *msg;
769         struct ldb_message_element *el;
770         struct ldb_dn *server_dn;
771         const char *dNSHostName = strlower_talloc(mem_ctx,
772                                                   talloc_asprintf(mem_ctx,
773                                                                   "%s.%s",
774                                                                   netbios_name,
775                                                                   realm));
776         msg = ldb_msg_new(mem_ctx);
777         if (msg == NULL) {
778                 return NT_STATUS_NO_MEMORY;
779         }
780
781         server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
782         if (!server_dn) {
783                 return NT_STATUS_INTERNAL_ERROR;
784         }
785
786         msg->dn = server_dn;
787         ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
788         if (ret != LDB_SUCCESS) {
789                 return NT_STATUS_INTERNAL_ERROR;
790         }
791
792         ret = ldb_msg_add_steal_string(msg,
793                                        "dNSHostName",
794                                        talloc_asprintf(el->values, "%s", dNSHostName));
795         if (ret != LDB_SUCCESS) {
796                 return NT_STATUS_INTERNAL_ERROR;
797         }
798
799         ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
800         if (ret != LDB_SUCCESS) {
801                 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
802                          ldb_errstring(ldb)));
803                 return NT_STATUS_INTERNAL_ERROR;
804         }
805
806         return NT_STATUS_OK;
807 }
808
809
810 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 
811                         struct libnet_Vampire *r)
812 {
813         struct libnet_JoinDomain *join;
814         struct libnet_Replicate rep;
815         NTSTATUS status;
816
817         const char *account_name;
818         const char *netbios_name;
819         
820         r->out.error_string = NULL;
821
822         join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
823         if (!join) {
824                 return NT_STATUS_NO_MEMORY;
825         }
826                 
827         if (r->in.netbios_name != NULL) {
828                 netbios_name = r->in.netbios_name;
829         } else {
830                 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
831                 if (!netbios_name) {
832                         talloc_free(join);
833                         r->out.error_string = NULL;
834                         return NT_STATUS_NO_MEMORY;
835                 }
836         }
837
838         account_name = talloc_asprintf(join, "%s$", netbios_name);
839         if (!account_name) {
840                 talloc_free(join);
841                 r->out.error_string = NULL;
842                 return NT_STATUS_NO_MEMORY;
843         }
844         
845         /* Re-use the domain we are joining as the domain for the user
846          * to be authenticated with, unless they specified
847          * otherwise */
848         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
849
850         join->in.domain_name    = r->in.domain_name;
851         join->in.account_name   = account_name;
852         join->in.netbios_name   = netbios_name;
853         join->in.level          = LIBNET_JOINDOMAIN_AUTOMATIC;
854         join->in.acct_type      = ACB_WSTRUST;
855         join->in.recreate_account = false;
856         status = libnet_JoinDomain(ctx, join, join);
857         if (!NT_STATUS_IS_OK(status)) {
858                 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
859                 talloc_free(join);
860                 return status;
861         }
862
863         rep.in.domain_name   = join->out.domain_name;
864         rep.in.netbios_name  = netbios_name;
865         rep.in.targetdir     = r->in.targetdir;
866         rep.in.domain_sid    = join->out.domain_sid;
867         rep.in.realm         = join->out.realm;
868         rep.in.server        = join->out.samr_binding->host;
869         rep.in.join_password = join->out.join_password;
870         rep.in.kvno          = join->out.kvno;
871
872         status = libnet_Replicate(ctx, mem_ctx, &rep);
873
874         r->out.domain_sid   = join->out.domain_sid;
875         r->out.domain_name  = join->out.domain_name;
876         r->out.error_string = rep.out.error_string;
877
878         return status;
879 }
880
881
882
883 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
884                           struct libnet_Replicate *r)
885 {
886         struct provision_store_self_join_settings *set_secrets;
887         struct libnet_BecomeDC b;
888         struct libnet_vampire_cb_state *s;
889         struct ldb_message *msg;
890         const char *error_string;
891         int ldb_ret;
892         uint32_t i;
893         NTSTATUS status;
894         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
895         const char *account_name;
896         const char *netbios_name;
897
898         r->out.error_string = NULL;
899
900         netbios_name = r->in.netbios_name;
901         account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
902         if (!account_name) {
903                 talloc_free(tmp_ctx);
904                 r->out.error_string = NULL;
905                 return NT_STATUS_NO_MEMORY;
906         }
907         
908         /* Re-use the domain we are joining as the domain for the user
909          * to be authenticated with, unless they specified
910          * otherwise */
911         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
912
913         s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
914                                          netbios_name, r->in.domain_name, r->in.realm,
915                                          r->in.targetdir);
916         if (!s) {
917                 return NT_STATUS_NO_MEMORY;
918         }
919         talloc_steal(s, tmp_ctx);
920
921         ZERO_STRUCT(b);
922
923         /* Be more robust:
924          * We now know the domain and realm for sure - if they didn't
925          * put one on the command line, use this for the rest of the
926          * join */
927         cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
928         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
929
930         /* Now set these values into the smb.conf - we probably had
931          * empty or useless defaults here from whatever smb.conf we
932          * started with */
933         lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
934         lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
935
936         b.in.domain_dns_name            = r->in.realm;
937         b.in.domain_netbios_name        = r->in.domain_name;
938         b.in.domain_sid                 = r->in.domain_sid;
939         b.in.source_dsa_address         = r->in.server;
940         b.in.dest_dsa_netbios_name      = netbios_name;
941
942         b.in.callbacks.private_data     = s;
943         b.in.callbacks.check_options    = libnet_vampire_cb_check_options;
944         b.in.callbacks.prepare_db       = libnet_vampire_cb_prepare_db;
945         b.in.callbacks.schema_chunk     = libnet_vampire_cb_schema_chunk;
946         b.in.callbacks.config_chunk     = libnet_vampire_cb_store_chunk;
947         b.in.callbacks.domain_chunk     = libnet_vampire_cb_store_chunk;
948
949         b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
950
951         status = libnet_BecomeDC(ctx, s, &b);
952         if (!NT_STATUS_IS_OK(status)) {
953                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
954                 talloc_free(s);
955                 return status;
956         }
957
958         msg = ldb_msg_new(s);
959         if (!msg) {
960                 printf("ldb_msg_new() failed\n");
961                 talloc_free(s);
962                 return NT_STATUS_NO_MEMORY;
963         }
964         msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
965         if (!msg->dn) {
966                 printf("ldb_msg_new(@ROOTDSE) failed\n");
967                 talloc_free(s);
968                 return NT_STATUS_NO_MEMORY;
969         }
970
971         ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
972         if (ldb_ret != LDB_SUCCESS) {
973                 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
974                 talloc_free(s);
975                 return NT_STATUS_NO_MEMORY;
976         }
977
978         for (i=0; i < msg->num_elements; i++) {
979                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
980         }
981
982         printf("mark ROOTDSE with isSynchronized=TRUE\n");
983         ldb_ret = ldb_modify(s->ldb, msg);
984         if (ldb_ret != LDB_SUCCESS) {
985                 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
986                 talloc_free(s);
987                 return NT_STATUS_INTERNAL_DB_ERROR;
988         }
989         /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
990          * the attribute appears on the original DC after replication
991          */
992         status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
993         if (!NT_STATUS_IS_OK(status)) {
994                 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
995                 talloc_free(s);
996                 return status;
997         }
998         /* prepare the transaction - this prepares to commit all the changes in
999            the ldb from the whole vampire.  Note that this 
1000            triggers the writing of the linked attribute backlinks.
1001         */
1002         if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
1003                 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
1004                 return NT_STATUS_INTERNAL_DB_ERROR;
1005         }
1006
1007         set_secrets = talloc(s, struct provision_store_self_join_settings);
1008         if (!set_secrets) {
1009                 r->out.error_string = NULL;
1010                 talloc_free(s);
1011                 return NT_STATUS_NO_MEMORY;
1012         }
1013         
1014         ZERO_STRUCTP(set_secrets);
1015         set_secrets->domain_name = r->in.domain_name;
1016         set_secrets->realm = r->in.realm;
1017         set_secrets->netbios_name = netbios_name;
1018         set_secrets->secure_channel_type = SEC_CHAN_BDC;
1019         set_secrets->machine_password = r->in.join_password;
1020         set_secrets->key_version_number = r->in.kvno;
1021         set_secrets->domain_sid = r->in.domain_sid;
1022         
1023         status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
1024         if (!NT_STATUS_IS_OK(status)) {
1025                 r->out.error_string = talloc_steal(mem_ctx, error_string);
1026                 talloc_free(s);
1027                 return status;
1028         }
1029
1030         /* commit the transaction now we know the secrets were written
1031          * out properly
1032         */
1033         if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
1034                 printf("Failed to commit vampire transaction\n");
1035                 return NT_STATUS_INTERNAL_DB_ERROR;
1036         }
1037
1038         talloc_free(s);
1039
1040         return NT_STATUS_OK;
1041 }