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