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