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