libnet-vampire: reports Exops as they rather than sync on some partitions
[metze/samba/wip.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 <ldb.h>
31 #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         settings.use_ntvfs = true;
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         uint32_t ignore_attids[] = {
250                         DRSUAPI_ATTID_auxiliaryClass,
251                         DRSUAPI_ATTID_mayContain,
252                         DRSUAPI_ATTID_mustContain,
253                         DRSUAPI_ATTID_possSuperiors,
254                         DRSUAPI_ATTID_systemPossSuperiors,
255                         DRSUAPI_ATTID_INVALID
256         };
257
258         DEBUG(0,("Analyze and apply schema objects\n"));
259
260         s_dsa                   = talloc_zero(s, struct repsFromTo1);
261         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
262         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
263         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
264
265         switch (c->ctr_level) {
266         case 1:
267                 mapping_ctr                     = &c->ctr1->mapping_ctr;
268                 object_count                    = s->schema_part.object_count;
269                 first_object                    = s->schema_part.first_object;
270                 linked_attributes_count         = 0;
271                 linked_attributes               = NULL;
272                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
273                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
274                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
275                 uptodateness_vector             = NULL; /* TODO: map it */
276                 break;
277         case 6:
278                 mapping_ctr                     = &c->ctr6->mapping_ctr;
279                 object_count                    = s->schema_part.object_count;
280                 first_object                    = s->schema_part.first_object;
281                 linked_attributes_count         = c->ctr6->linked_attributes_count;
282                 linked_attributes               = c->ctr6->linked_attributes;
283                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
284                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
285                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
286                 uptodateness_vector             = c->ctr6->uptodateness_vector;
287                 break;
288         default:
289                 return NT_STATUS_INVALID_PARAMETER;
290         }
291         /* We must set these up to ensure the replMetaData is written
292          * correctly, before our NTDS Settings entry is replicated */
293         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
294         if (!ok) {
295                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
296                 return NT_STATUS_FOOBAR;
297         }
298         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
299         if (!ok) {
300                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
301                 return NT_STATUS_FOOBAR;
302         }
303
304
305         status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
306                                                   s, &pfm_remote, NULL);
307         if (!W_ERROR_IS_OK(status)) {
308                 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
309                          win_errstr(status)));
310                 return werror_to_ntstatus(status);
311         }
312
313         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
314                                         | DRSUAPI_DRS_INIT_SYNC
315                                         | DRSUAPI_DRS_PER_SYNC;
316         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
317
318         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
319         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
320         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
321         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
322         s_dsa->other_info->dns_name = tmp_dns_name;
323
324         schema_ldb = provision_get_schema(s, s->lp_ctx,
325                                           c->forest->schema_dn_str,
326                                           &s->prefixmap_blob);
327         if (!schema_ldb) {
328                 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
329                          "Will continue with local prefixMap\n"));
330                 provision_schema = dsdb_get_schema(s->ldb, s);
331         } else {
332                 provision_schema = dsdb_get_schema(schema_ldb, s);
333                 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
334                 if (ret != LDB_SUCCESS) {
335                         DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
336                         return NT_STATUS_UNSUCCESSFUL;
337                 }
338                 talloc_free(schema_ldb);
339         }
340
341         /* create a list of objects yet to be converted */
342         for (cur = first_object; cur; cur = cur->next_object) {
343                 schema_list_item = talloc(s, struct schema_list);
344                 schema_list_item->obj = cur;
345                 DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
346         }
347
348         /* resolve objects until all are resolved and in local schema */
349         pass_no = 1;
350         working_schema = provision_schema;
351
352         while (schema_list) {
353                 uint32_t converted_obj_count = 0;
354                 uint32_t failed_obj_count = 0;
355                 TALLOC_CTX *tmp_ctx = talloc_new(s);
356                 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
357
358                 for (schema_list_item = schema_list; schema_list_item; schema_list_item=schema_list_next_item) {
359                         struct dsdb_extended_replicated_object object;
360
361                         cur = schema_list_item->obj;
362
363                         /* Save the next item, now we have saved out
364                          * the current one, so we can DLIST_REMOVE it
365                          * safely */
366                         schema_list_next_item = schema_list_item->next;
367
368                         /*
369                          * Convert the objects into LDB messages using the
370                          * schema we have so far. It's ok if we fail to convert
371                          * an object. We should convert more objects on next pass.
372                          */
373                         status = dsdb_convert_object_ex(s->ldb, working_schema, pfm_remote,
374                                                         cur, c->gensec_skey,
375                                                         ignore_attids,
376                                                         0,
377                                                         tmp_ctx, &object);
378                         if (!W_ERROR_IS_OK(status)) {
379                                 DEBUG(1,("Warning: Failed to convert schema object %s into ldb msg\n",
380                                          cur->object.identifier->dn));
381
382                                 failed_obj_count++;
383                         } else {
384                                 /*
385                                  * Convert the schema from ldb_message format
386                                  * (OIDs as OID strings) into schema, using
387                                  * the remote prefixMap
388                                  */
389                                 status = dsdb_schema_set_el_from_ldb_msg(s->ldb,
390                                                                          s->self_made_schema,
391                                                                          object.msg);
392                                 if (!W_ERROR_IS_OK(status)) {
393                                         DEBUG(1,("Warning: failed to convert object %s into a schema element: %s\n",
394                                                  ldb_dn_get_linearized(object.msg->dn),
395                                                  win_errstr(status)));
396                                         failed_obj_count++;
397                                 } else {
398                                         DLIST_REMOVE(schema_list, schema_list_item);
399                                         converted_obj_count++;
400                                 }
401                         }
402                 }
403                 talloc_free(tmp_ctx);
404
405                 DEBUG(4,("Schema load pass %d: %d/%d of %d objects left to be converted.\n",
406                          pass_no, failed_obj_count, converted_obj_count, object_count));
407                 pass_no++;
408
409                 /* check if we converted any objects in this pass */
410                 if (converted_obj_count == 0) {
411                         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));
412                         return NT_STATUS_INTERNAL_ERROR;
413                 }
414
415                 if (schema_list) {
416                         /* prepare for another cycle */
417                         working_schema = s->self_made_schema;
418
419                         ret = dsdb_setup_sorted_accessors(s->ldb, working_schema);
420                         if (LDB_SUCCESS != ret) {
421                                 DEBUG(0,("Failed to create schema-cache indexes!\n"));
422                                 return NT_STATUS_INTERNAL_ERROR;
423                         }
424                 }
425         };
426
427         /* free temp objects for 1st conversion phase */
428         talloc_unlink(s, provision_schema);
429         TALLOC_FREE(schema_list);
430
431         /*
432          * attach the schema we just brought over DRS to the ldb,
433          * so we can use it in dsdb_convert_object_ex below
434          */
435         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
436         if (ret != LDB_SUCCESS) {
437                 DEBUG(0,("Failed to attach working schema from DRS.\n"));
438                 return NT_STATUS_FOOBAR;
439         }
440
441         /* we don't want to access the self made schema anymore */
442         s->schema = s->self_made_schema;
443         s->self_made_schema = NULL;
444
445         /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
446         status = dsdb_replicated_objects_convert(s->ldb,
447                                                  s->schema,
448                                                  c->partition->nc.dn,
449                                                  mapping_ctr,
450                                                  object_count,
451                                                  first_object,
452                                                  linked_attributes_count,
453                                                  linked_attributes,
454                                                  s_dsa,
455                                                  uptodateness_vector,
456                                                  c->gensec_skey,
457                                                  0,
458                                                  s, &schema_objs);
459         if (!W_ERROR_IS_OK(status)) {
460                 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
461                 return werror_to_ntstatus(status);
462         }
463
464         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
465                 for (i=0; i < schema_objs->num_objects; i++) {
466                         struct ldb_ldif ldif;
467                         fprintf(stdout, "#\n");
468                         ldif.changetype = LDB_CHANGETYPE_NONE;
469                         ldif.msg = schema_objs->objects[i].msg;
470                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
471                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
472                 }
473         }
474
475         status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
476         if (!W_ERROR_IS_OK(status)) {
477                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
478                 return werror_to_ntstatus(status);
479         }
480
481         msg = ldb_msg_new(schema_objs);
482         NT_STATUS_HAVE_NO_MEMORY(msg);
483         msg->dn = schema_objs->partition_dn;
484
485         /* We must ensure a prefixMap has been written.  Unlike other
486          * attributes (including schemaInfo), it is not replicated in
487          * the normal replication stream.  We can use the one from
488          * s->prefixmap_blob because we operate with one, unchanging
489          * prefixMap for this entire operation.  */
490         ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
491         if (ret != LDB_SUCCESS) {
492                 return NT_STATUS_FOOBAR;
493         }
494         /* We want to know if a prefixMap was written already, as it
495          * would mean that the above comment was not true, and we have
496          * somehow updated the prefixMap during this transaction */
497         prefixMap_el->flags = LDB_FLAG_MOD_ADD;
498
499         ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
500         if (ret != LDB_SUCCESS) {
501                 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
502                 return NT_STATUS_FOOBAR;
503         }
504
505         talloc_free(s_dsa);
506         talloc_free(schema_objs);
507
508         s->schema = dsdb_get_schema(s->ldb, s);
509         if (!s->schema) {
510                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
511                 return NT_STATUS_FOOBAR;
512         }
513
514         return NT_STATUS_OK;
515 }
516
517 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
518                                         const struct libnet_BecomeDC_StoreChunk *c)
519 {
520         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
521         WERROR status;
522         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
523         uint32_t nc_object_count;
524         uint32_t nc_total_received = 0;
525         uint32_t object_count;
526         struct drsuapi_DsReplicaObjectListItemEx *first_object;
527         struct drsuapi_DsReplicaObjectListItemEx *cur;
528         uint32_t nc_linked_attributes_count;
529         uint32_t linked_attributes_count;
530
531         switch (c->ctr_level) {
532         case 1:
533                 mapping_ctr                     = &c->ctr1->mapping_ctr;
534                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
535                 object_count                    = c->ctr1->object_count;
536                 first_object                    = c->ctr1->first_object;
537                 nc_linked_attributes_count      = 0;
538                 linked_attributes_count         = 0;
539                 break;
540         case 6:
541                 mapping_ctr                     = &c->ctr6->mapping_ctr;
542                 nc_object_count                 = c->ctr6->nc_object_count;
543                 object_count                    = c->ctr6->object_count;
544                 first_object                    = c->ctr6->first_object;
545                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
546                 linked_attributes_count         = c->ctr6->linked_attributes_count;
547                 break;
548         default:
549                 return NT_STATUS_INVALID_PARAMETER;
550         }
551
552         if (!s->schema_part.first_object) {
553                 nc_total_received = object_count;
554         } else {
555                 nc_total_received = s->schema_part.object_count + object_count;
556         }
557         if (nc_object_count) {
558                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
559                         c->partition->nc.dn, nc_total_received, nc_object_count,
560                         linked_attributes_count, nc_linked_attributes_count));
561         } else {
562                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
563                 c->partition->nc.dn, nc_total_received, linked_attributes_count));
564         }
565
566         if (!s->self_made_schema) {
567                 WERROR werr;
568                 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
569                 /* Put the DRS prefixmap aside for the schema we are
570                  * about to load in the provision, and into the one we
571                  * are making with the help of DRS */
572
573                 mapping_ctr_without_schema_info = *mapping_ctr;
574
575                 /* This strips off the 0xFF schema info from the end,
576                  * because we don't want it in the blob */
577                 if (mapping_ctr_without_schema_info.num_mappings > 0) {
578                         mapping_ctr_without_schema_info.num_mappings--;
579                 }
580                 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
581                 if (!W_ERROR_IS_OK(werr)) {
582                         return werror_to_ntstatus(werr);
583                 }
584
585                 /* Set up two manually-constructed schema - the local
586                  * schema from the provision will be used to build
587                  * one, which will then in turn be used to build the
588                  * other. */
589                 s->self_made_schema = dsdb_new_schema(s);
590                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
591
592                 s->self_made_schema->base_dn = ldb_dn_new(s->self_made_schema,
593                                                 s->ldb,
594                                                 c->forest->schema_dn_str);
595                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema->base_dn);
596
597                 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
598                 if (!W_ERROR_IS_OK(status)) {
599                         return werror_to_ntstatus(status);
600                 }
601         } else {
602                 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
603                 if (!W_ERROR_IS_OK(status)) {
604                         return werror_to_ntstatus(status);
605                 }
606         }
607
608         if (!s->schema_part.first_object) {
609                 s->schema_part.object_count = object_count;
610                 s->schema_part.first_object = talloc_steal(s, first_object);
611         } else {
612                 s->schema_part.object_count             += object_count;
613                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
614                                                                        first_object);
615         }
616         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
617         s->schema_part.last_object = cur;
618
619         if (!c->partition->more_data) {
620                 return libnet_vampire_cb_apply_schema(s, c);
621         }
622
623         return NT_STATUS_OK;
624 }
625
626 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
627                              const struct libnet_BecomeDC_StoreChunk *c)
628 {
629         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
630         WERROR status;
631         struct dsdb_schema *schema;
632         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
633         uint32_t nc_object_count;
634         uint32_t object_count;
635         struct drsuapi_DsReplicaObjectListItemEx *first_object;
636         uint32_t nc_linked_attributes_count;
637         uint32_t linked_attributes_count;
638         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
639         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
640         struct dsdb_extended_replicated_objects *objs;
641         uint32_t req_replica_flags;
642         struct repsFromTo1 *s_dsa;
643         char *tmp_dns_name;
644         uint32_t i;
645         uint64_t seq_num;
646         bool is_exop = false;
647
648         s_dsa                   = talloc_zero(s, struct repsFromTo1);
649         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
650         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
651         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
652
653         switch (c->ctr_level) {
654         case 1:
655                 mapping_ctr                     = &c->ctr1->mapping_ctr;
656                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
657                 object_count                    = c->ctr1->object_count;
658                 first_object                    = c->ctr1->first_object;
659                 nc_linked_attributes_count      = 0;
660                 linked_attributes_count         = 0;
661                 linked_attributes               = NULL;
662                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
663                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
664                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
665                 uptodateness_vector             = NULL; /* TODO: map it */
666                 break;
667         case 6:
668                 mapping_ctr                     = &c->ctr6->mapping_ctr;
669                 nc_object_count                 = c->ctr6->nc_object_count;
670                 object_count                    = c->ctr6->object_count;
671                 first_object                    = c->ctr6->first_object;
672                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
673                 linked_attributes_count         = c->ctr6->linked_attributes_count;
674                 linked_attributes               = c->ctr6->linked_attributes;
675                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
676                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
677                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
678                 uptodateness_vector             = c->ctr6->uptodateness_vector;
679                 break;
680         default:
681                 return NT_STATUS_INVALID_PARAMETER;
682         }
683
684         switch (c->req_level) {
685         case 0:
686                 /* none */
687                 req_replica_flags = 0;
688                 break;
689         case 5:
690                 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
691                         is_exop = true;
692                 }
693                 req_replica_flags = c->req5->replica_flags;
694                 break;
695         case 8:
696                 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
697                         is_exop = true;
698                 }
699                 req_replica_flags = c->req8->replica_flags;
700                 break;
701         case 10:
702                 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
703                         is_exop = true;
704                 }
705                 req_replica_flags = c->req10->replica_flags;
706                 break;
707         default:
708                 return NT_STATUS_INVALID_PARAMETER;
709         }
710
711         if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
712                 /*
713                  * If we only replicate the critical objects
714                  * we should not remember what we already
715                  * got, as it is incomplete.
716                  */
717                 ZERO_STRUCT(s_dsa->highwatermark);
718                 uptodateness_vector = NULL;
719         }
720
721         /* TODO: avoid hardcoded flags */
722         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
723                                         | DRSUAPI_DRS_INIT_SYNC
724                                         | DRSUAPI_DRS_PER_SYNC;
725         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
726
727         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
728         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
729         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
730         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
731         s_dsa->other_info->dns_name = tmp_dns_name;
732
733         /* we want to show a count per partition */
734         if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
735                 s->total_objects = 0;
736                 talloc_free(s->last_partition);
737                 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
738         }
739         s->total_objects += object_count;
740
741         if (is_exop) {
742                 if (nc_object_count) {
743                         DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
744                                 c->partition->nc.dn, s->total_objects, nc_object_count,
745                                 linked_attributes_count, nc_linked_attributes_count));
746                 } else {
747                         DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
748                         c->partition->nc.dn, s->total_objects, linked_attributes_count));
749                 }
750         } else {
751                 if (nc_object_count) {
752                         DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
753                                 c->partition->nc.dn, s->total_objects, nc_object_count,
754                                 linked_attributes_count, nc_linked_attributes_count));
755                 } else {
756                         DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
757                         c->partition->nc.dn, s->total_objects, linked_attributes_count));
758                 }
759         }
760
761
762         schema = dsdb_get_schema(s->ldb, NULL);
763         if (!schema) {
764                 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
765                 return NT_STATUS_INTERNAL_ERROR;
766         }
767
768         status = dsdb_replicated_objects_convert(s->ldb,
769                                                  schema,
770                                                  c->partition->nc.dn,
771                                                  mapping_ctr,
772                                                  object_count,
773                                                  first_object,
774                                                  linked_attributes_count,
775                                                  linked_attributes,
776                                                  s_dsa,
777                                                  uptodateness_vector,
778                                                  c->gensec_skey,
779                                                  0,
780                                                  s, &objs);
781         if (!W_ERROR_IS_OK(status)) {
782                 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
783                 return werror_to_ntstatus(status);
784         }
785
786         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
787                 for (i=0; i < objs->num_objects; i++) {
788                         struct ldb_ldif ldif;
789                         fprintf(stdout, "#\n");
790                         ldif.changetype = LDB_CHANGETYPE_NONE;
791                         ldif.msg = objs->objects[i].msg;
792                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
793                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
794                 }
795         }
796         status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
797         if (!W_ERROR_IS_OK(status)) {
798                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
799                 return werror_to_ntstatus(status);
800         }
801
802         talloc_free(s_dsa);
803         talloc_free(objs);
804
805         for (i=0; i < linked_attributes_count; i++) {
806                 const struct dsdb_attribute *sa;
807
808                 if (!linked_attributes[i].identifier) {
809                         DEBUG(0, ("No linked attribute identifier\n"));
810                         return NT_STATUS_FOOBAR;
811                 }
812
813                 if (!linked_attributes[i].value.blob) {
814                         DEBUG(0, ("No linked attribute value\n"));
815                         return NT_STATUS_FOOBAR;
816                 }
817
818                 sa = dsdb_attribute_by_attributeID_id(s->schema,
819                                                       linked_attributes[i].attid);
820                 if (!sa) {
821                         DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
822                         return NT_STATUS_FOOBAR;
823                 }
824
825                 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
826                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
827                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
828                         dump_data(0,
829                                 linked_attributes[i].value.blob->data,
830                                 linked_attributes[i].value.blob->length);
831                 }
832         }
833
834         return NT_STATUS_OK;
835 }
836
837 static NTSTATUS update_dnshostname_for_server(TALLOC_CTX *mem_ctx,
838                                               struct ldb_context *ldb,
839                                               const char *server_dn_str,
840                                               const char *netbios_name,
841                                               const char *realm)
842 {
843         int ret;
844         struct ldb_message *msg;
845         struct ldb_message_element *el;
846         struct ldb_dn *server_dn;
847         const char *dNSHostName = strlower_talloc(mem_ctx,
848                                                   talloc_asprintf(mem_ctx,
849                                                                   "%s.%s",
850                                                                   netbios_name,
851                                                                   realm));
852         msg = ldb_msg_new(mem_ctx);
853         if (msg == NULL) {
854                 return NT_STATUS_NO_MEMORY;
855         }
856
857         server_dn = ldb_dn_new(mem_ctx, ldb, server_dn_str);
858         if (!server_dn) {
859                 return NT_STATUS_INTERNAL_ERROR;
860         }
861
862         msg->dn = server_dn;
863         ret = ldb_msg_add_empty(msg, "dNSHostName", LDB_FLAG_MOD_ADD, &el);
864         if (ret != LDB_SUCCESS) {
865                 return NT_STATUS_INTERNAL_ERROR;
866         }
867
868         ret = ldb_msg_add_steal_string(msg,
869                                        "dNSHostName",
870                                        talloc_asprintf(el->values, "%s", dNSHostName));
871         if (ret != LDB_SUCCESS) {
872                 return NT_STATUS_INTERNAL_ERROR;
873         }
874
875         ret = dsdb_modify(ldb, msg, DSDB_MODIFY_PERMISSIVE);
876         if (ret != LDB_SUCCESS) {
877                 DEBUG(0,(__location__ ": Failed to add dnsHostName to the Server object: %s\n",
878                          ldb_errstring(ldb)));
879                 return NT_STATUS_INTERNAL_ERROR;
880         }
881
882         return NT_STATUS_OK;
883 }
884
885
886 NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 
887                         struct libnet_Vampire *r)
888 {
889         struct libnet_JoinDomain *join;
890         struct libnet_Replicate rep;
891         NTSTATUS status;
892
893         const char *account_name;
894         const char *netbios_name;
895         
896         r->out.error_string = NULL;
897
898         join = talloc_zero(mem_ctx, struct libnet_JoinDomain);
899         if (!join) {
900                 return NT_STATUS_NO_MEMORY;
901         }
902                 
903         if (r->in.netbios_name != NULL) {
904                 netbios_name = r->in.netbios_name;
905         } else {
906                 netbios_name = talloc_reference(join, lpcfg_netbios_name(ctx->lp_ctx));
907                 if (!netbios_name) {
908                         talloc_free(join);
909                         r->out.error_string = NULL;
910                         return NT_STATUS_NO_MEMORY;
911                 }
912         }
913
914         account_name = talloc_asprintf(join, "%s$", netbios_name);
915         if (!account_name) {
916                 talloc_free(join);
917                 r->out.error_string = NULL;
918                 return NT_STATUS_NO_MEMORY;
919         }
920         
921         /* Re-use the domain we are joining as the domain for the user
922          * to be authenticated with, unless they specified
923          * otherwise */
924         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
925
926         join->in.domain_name    = r->in.domain_name;
927         join->in.account_name   = account_name;
928         join->in.netbios_name   = netbios_name;
929         join->in.level          = LIBNET_JOINDOMAIN_AUTOMATIC;
930         join->in.acct_type      = ACB_WSTRUST;
931         join->in.recreate_account = false;
932         status = libnet_JoinDomain(ctx, join, join);
933         if (!NT_STATUS_IS_OK(status)) {
934                 r->out.error_string = talloc_steal(mem_ctx, join->out.error_string);
935                 talloc_free(join);
936                 return status;
937         }
938
939         rep.in.domain_name   = join->out.domain_name;
940         rep.in.netbios_name  = netbios_name;
941         rep.in.targetdir     = r->in.targetdir;
942         rep.in.domain_sid    = join->out.domain_sid;
943         rep.in.realm         = join->out.realm;
944         rep.in.server        = join->out.samr_binding->host;
945         rep.in.join_password = join->out.join_password;
946         rep.in.kvno          = join->out.kvno;
947
948         status = libnet_Replicate(ctx, mem_ctx, &rep);
949
950         r->out.domain_sid   = join->out.domain_sid;
951         r->out.domain_name  = join->out.domain_name;
952         r->out.error_string = rep.out.error_string;
953
954         return status;
955 }
956
957
958
959 NTSTATUS libnet_Replicate(struct libnet_context *ctx, TALLOC_CTX *mem_ctx,
960                           struct libnet_Replicate *r)
961 {
962         struct provision_store_self_join_settings *set_secrets;
963         struct libnet_BecomeDC b;
964         struct libnet_vampire_cb_state *s;
965         struct ldb_message *msg;
966         const char *error_string;
967         int ldb_ret;
968         uint32_t i;
969         NTSTATUS status;
970         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
971         const char *account_name;
972         const char *netbios_name;
973
974         r->out.error_string = NULL;
975
976         netbios_name = r->in.netbios_name;
977         account_name = talloc_asprintf(tmp_ctx, "%s$", netbios_name);
978         if (!account_name) {
979                 talloc_free(tmp_ctx);
980                 r->out.error_string = NULL;
981                 return NT_STATUS_NO_MEMORY;
982         }
983         
984         /* Re-use the domain we are joining as the domain for the user
985          * to be authenticated with, unless they specified
986          * otherwise */
987         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
988
989         s = libnet_vampire_cb_state_init(mem_ctx, ctx->lp_ctx, ctx->event_ctx,
990                                          netbios_name, r->in.domain_name, r->in.realm,
991                                          r->in.targetdir);
992         if (!s) {
993                 return NT_STATUS_NO_MEMORY;
994         }
995         talloc_steal(s, tmp_ctx);
996
997         ZERO_STRUCT(b);
998
999         /* Be more robust:
1000          * We now know the domain and realm for sure - if they didn't
1001          * put one on the command line, use this for the rest of the
1002          * join */
1003         cli_credentials_set_realm(ctx->cred, r->in.realm, CRED_GUESS_ENV);
1004         cli_credentials_set_domain(ctx->cred, r->in.domain_name, CRED_GUESS_ENV);
1005
1006         /* Now set these values into the smb.conf - we probably had
1007          * empty or useless defaults here from whatever smb.conf we
1008          * started with */
1009         lpcfg_set_cmdline(s->lp_ctx, "realm", r->in.realm);
1010         lpcfg_set_cmdline(s->lp_ctx, "workgroup", r->in.domain_name);
1011
1012         b.in.domain_dns_name            = r->in.realm;
1013         b.in.domain_netbios_name        = r->in.domain_name;
1014         b.in.domain_sid                 = r->in.domain_sid;
1015         b.in.source_dsa_address         = r->in.server;
1016         b.in.dest_dsa_netbios_name      = netbios_name;
1017
1018         b.in.callbacks.private_data     = s;
1019         b.in.callbacks.check_options    = libnet_vampire_cb_check_options;
1020         b.in.callbacks.prepare_db       = libnet_vampire_cb_prepare_db;
1021         b.in.callbacks.schema_chunk     = libnet_vampire_cb_schema_chunk;
1022         b.in.callbacks.config_chunk     = libnet_vampire_cb_store_chunk;
1023         b.in.callbacks.domain_chunk     = libnet_vampire_cb_store_chunk;
1024
1025         b.in.rodc_join = lpcfg_parm_bool(s->lp_ctx, NULL, "repl", "RODC", false);
1026
1027         status = libnet_BecomeDC(ctx, s, &b);
1028         if (!NT_STATUS_IS_OK(status)) {
1029                 printf("libnet_BecomeDC() failed - %s\n", nt_errstr(status));
1030                 talloc_free(s);
1031                 return status;
1032         }
1033
1034         msg = ldb_msg_new(s);
1035         if (!msg) {
1036                 printf("ldb_msg_new() failed\n");
1037                 talloc_free(s);
1038                 return NT_STATUS_NO_MEMORY;
1039         }
1040         msg->dn = ldb_dn_new(msg, s->ldb, "@ROOTDSE");
1041         if (!msg->dn) {
1042                 printf("ldb_msg_new(@ROOTDSE) failed\n");
1043                 talloc_free(s);
1044                 return NT_STATUS_NO_MEMORY;
1045         }
1046
1047         ldb_ret = ldb_msg_add_string(msg, "isSynchronized", "TRUE");
1048         if (ldb_ret != LDB_SUCCESS) {
1049                 printf("ldb_msg_add_string(msg, isSynchronized, TRUE) failed: %d\n", ldb_ret);
1050                 talloc_free(s);
1051                 return NT_STATUS_NO_MEMORY;
1052         }
1053
1054         for (i=0; i < msg->num_elements; i++) {
1055                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1056         }
1057
1058         printf("mark ROOTDSE with isSynchronized=TRUE\n");
1059         ldb_ret = ldb_modify(s->ldb, msg);
1060         if (ldb_ret != LDB_SUCCESS) {
1061                 printf("ldb_modify() failed: %d : %s\n", ldb_ret, ldb_errstring(s->ldb));
1062                 talloc_free(s);
1063                 return NT_STATUS_INTERNAL_DB_ERROR;
1064         }
1065         /* during dcpromo the 2nd computer adds dNSHostName attribute to his Server object
1066          * the attribute appears on the original DC after replication
1067          */
1068         status = update_dnshostname_for_server(s, s->ldb, s->server_dn_str, s->netbios_name, s->realm);
1069         if (!NT_STATUS_IS_OK(status)) {
1070                 printf("Failed to update dNSHostName on Server object - %s\n", nt_errstr(status));
1071                 talloc_free(s);
1072                 return status;
1073         }
1074         /* prepare the transaction - this prepares to commit all the changes in
1075            the ldb from the whole vampire.  Note that this 
1076            triggers the writing of the linked attribute backlinks.
1077         */
1078         if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) {
1079                 printf("Failed to prepare_commit vampire transaction: %s\n", ldb_errstring(s->ldb));
1080                 return NT_STATUS_INTERNAL_DB_ERROR;
1081         }
1082
1083         set_secrets = talloc(s, struct provision_store_self_join_settings);
1084         if (!set_secrets) {
1085                 r->out.error_string = NULL;
1086                 talloc_free(s);
1087                 return NT_STATUS_NO_MEMORY;
1088         }
1089         
1090         ZERO_STRUCTP(set_secrets);
1091         set_secrets->domain_name = r->in.domain_name;
1092         set_secrets->realm = r->in.realm;
1093         set_secrets->netbios_name = netbios_name;
1094         set_secrets->secure_channel_type = SEC_CHAN_BDC;
1095         set_secrets->machine_password = r->in.join_password;
1096         set_secrets->key_version_number = r->in.kvno;
1097         set_secrets->domain_sid = r->in.domain_sid;
1098         
1099         status = provision_store_self_join(ctx, s->lp_ctx, ctx->event_ctx, set_secrets, &error_string);
1100         if (!NT_STATUS_IS_OK(status)) {
1101                 r->out.error_string = talloc_steal(mem_ctx, error_string);
1102                 talloc_free(s);
1103                 return status;
1104         }
1105
1106         /* commit the transaction now we know the secrets were written
1107          * out properly
1108         */
1109         if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) {
1110                 printf("Failed to commit vampire transaction\n");
1111                 return NT_STATUS_INTERNAL_DB_ERROR;
1112         }
1113
1114         talloc_free(s);
1115
1116         return NT_STATUS_OK;
1117 }