repl: Give an error if we get a secret when not expecting one
[obnox/samba/samba-obnox.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         WERROR status;
223         struct dsdb_schema_prefixmap *pfm_remote;
224         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
225         struct dsdb_schema *provision_schema;
226         uint32_t object_count = 0;
227         struct drsuapi_DsReplicaObjectListItemEx *first_object;
228         uint32_t linked_attributes_count;
229         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
230         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
231         struct dsdb_extended_replicated_objects *schema_objs;
232         struct repsFromTo1 *s_dsa;
233         char *tmp_dns_name;
234         struct ldb_context *schema_ldb;
235         struct ldb_message *msg;
236         struct ldb_message_element *prefixMap_el;
237         uint32_t i;
238         int ret;
239         bool ok;
240         uint64_t seq_num;
241         uint32_t cycle_before_switching;
242
243         DEBUG(0,("Analyze and apply schema objects\n"));
244
245         s_dsa                   = talloc_zero(s, struct repsFromTo1);
246         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
247         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
248         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
249
250         switch (c->ctr_level) {
251         case 1:
252                 mapping_ctr                     = &c->ctr1->mapping_ctr;
253                 object_count                    = s->schema_part.object_count;
254                 first_object                    = s->schema_part.first_object;
255                 linked_attributes_count         = 0;
256                 linked_attributes               = NULL;
257                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
258                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
259                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
260                 uptodateness_vector             = NULL; /* TODO: map it */
261                 break;
262         case 6:
263                 mapping_ctr                     = &c->ctr6->mapping_ctr;
264                 object_count                    = s->schema_part.object_count;
265                 first_object                    = s->schema_part.first_object;
266                 linked_attributes_count         = c->ctr6->linked_attributes_count;
267                 linked_attributes               = c->ctr6->linked_attributes;
268                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
269                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
270                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
271                 uptodateness_vector             = c->ctr6->uptodateness_vector;
272                 break;
273         default:
274                 return NT_STATUS_INVALID_PARAMETER;
275         }
276         /* We must set these up to ensure the replMetaData is written
277          * correctly, before our NTDS Settings entry is replicated */
278         ok = samdb_set_ntds_invocation_id(s->ldb, &c->dest_dsa->invocation_id);
279         if (!ok) {
280                 DEBUG(0,("Failed to set cached ntds invocationId\n"));
281                 return NT_STATUS_FOOBAR;
282         }
283         ok = samdb_set_ntds_objectGUID(s->ldb, &c->dest_dsa->ntds_guid);
284         if (!ok) {
285                 DEBUG(0,("Failed to set cached ntds objectGUID\n"));
286                 return NT_STATUS_FOOBAR;
287         }
288
289         status = dsdb_schema_pfm_from_drsuapi_pfm(mapping_ctr, true,
290                                                   s, &pfm_remote, NULL);
291         if (!W_ERROR_IS_OK(status)) {
292                 DEBUG(0,(__location__ ": Failed to decode remote prefixMap: %s",
293                          win_errstr(status)));
294                 return werror_to_ntstatus(status);
295         }
296
297         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
298                                         | DRSUAPI_DRS_INIT_SYNC
299                                         | DRSUAPI_DRS_PER_SYNC;
300         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
301
302         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
303         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
304         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
305         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
306         s_dsa->other_info->dns_name = tmp_dns_name;
307
308         if (s->self_made_schema == NULL) {
309                 DEBUG(0,("libnet_vampire_cb_apply_schema: called with out self_made_schema\n"));
310                 return NT_STATUS_INTERNAL_ERROR;
311         }
312
313         schema_ldb = provision_get_schema(s, s->lp_ctx,
314                                           c->forest->schema_dn_str,
315                                           &s->prefixmap_blob);
316         if (!schema_ldb) {
317                 DEBUG(0,("Failed to re-load from local provision using remote prefixMap. "
318                          "Will continue with local prefixMap\n"));
319                 provision_schema = dsdb_get_schema(s->ldb, s);
320         } else {
321                 provision_schema = dsdb_get_schema(schema_ldb, s);
322                 ret = dsdb_reference_schema(s->ldb, provision_schema, false);
323                 if (ret != LDB_SUCCESS) {
324                         DEBUG(0,("Failed to attach schema from local provision using remote prefixMap."));
325                         return NT_STATUS_UNSUCCESSFUL;
326                 }
327                 talloc_free(schema_ldb);
328         }
329
330         cycle_before_switching = lpcfg_parm_long(s->lp_ctx, NULL,
331                                                  "become dc",
332                                                  "schema convert retrial", 1);
333
334         status = dsdb_repl_resolve_working_schema(s->ldb, s,
335                                                   pfm_remote,
336                                                   cycle_before_switching,
337                                                   provision_schema,
338                                                   s->self_made_schema,
339                                                   object_count,
340                                                   first_object);
341         if (!W_ERROR_IS_OK(status)) {
342                 DEBUG(0, ("%s: dsdb_repl_resolve_working_schema() failed: %s",
343                           __location__, win_errstr(status)));
344                 return werror_to_ntstatus(status);
345         }
346
347         /* free temp objects for 1st conversion phase */
348         talloc_unlink(s, provision_schema);
349
350         /*
351          * attach the schema we just brought over DRS to the ldb,
352          * so we can use it in dsdb_convert_object_ex below
353          */
354         ret = dsdb_set_schema(s->ldb, s->self_made_schema);
355         if (ret != LDB_SUCCESS) {
356                 DEBUG(0,("Failed to attach working 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_made_schema;
362         s->self_made_schema = NULL;
363
364         /* Now convert the schema elements again, using the schema we finalised, ready to actually import */
365         status = dsdb_replicated_objects_convert(s->ldb,
366                                                  s->schema,
367                                                  c->partition->nc.dn,
368                                                  mapping_ctr,
369                                                  object_count,
370                                                  first_object,
371                                                  linked_attributes_count,
372                                                  linked_attributes,
373                                                  s_dsa,
374                                                  uptodateness_vector,
375                                                  c->gensec_skey,
376                                                  0,
377                                                  s, &schema_objs);
378         if (!W_ERROR_IS_OK(status)) {
379                 DEBUG(0,("Failed to convert objects when trying to import over DRS (2nd pass, to store remote schema): %s\n", win_errstr(status)));
380                 return werror_to_ntstatus(status);
381         }
382
383         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
384                 for (i=0; i < schema_objs->num_objects; i++) {
385                         struct ldb_ldif ldif;
386                         fprintf(stdout, "#\n");
387                         ldif.changetype = LDB_CHANGETYPE_NONE;
388                         ldif.msg = schema_objs->objects[i].msg;
389                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
390                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, schema_objs->objects[i].meta_data);
391                 }
392         }
393
394         status = dsdb_replicated_objects_commit(s->ldb, NULL, schema_objs, &seq_num);
395         if (!W_ERROR_IS_OK(status)) {
396                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
397                 return werror_to_ntstatus(status);
398         }
399
400         msg = ldb_msg_new(schema_objs);
401         NT_STATUS_HAVE_NO_MEMORY(msg);
402         msg->dn = schema_objs->partition_dn;
403
404         /* We must ensure a prefixMap has been written.  Unlike other
405          * attributes (including schemaInfo), it is not replicated in
406          * the normal replication stream.  We can use the one from
407          * s->prefixmap_blob because we operate with one, unchanging
408          * prefixMap for this entire operation.  */
409         ret = ldb_msg_add_value(msg, "prefixMap", &s->prefixmap_blob, &prefixMap_el);
410         if (ret != LDB_SUCCESS) {
411                 return NT_STATUS_FOOBAR;
412         }
413         /* We want to know if a prefixMap was written already, as it
414          * would mean that the above comment was not true, and we have
415          * somehow updated the prefixMap during this transaction */
416         prefixMap_el->flags = LDB_FLAG_MOD_ADD;
417
418         ret = dsdb_modify(s->ldb, msg, DSDB_FLAG_AS_SYSTEM);
419         if (ret != LDB_SUCCESS) {
420                 DEBUG(0,("Failed to add prefixMap: %s\n", ldb_errstring(s->ldb)));
421                 return NT_STATUS_FOOBAR;
422         }
423
424         talloc_free(s_dsa);
425         talloc_free(schema_objs);
426
427         s->schema = dsdb_get_schema(s->ldb, s);
428         if (!s->schema) {
429                 DEBUG(0,("Failed to get loaded dsdb_schema\n"));
430                 return NT_STATUS_FOOBAR;
431         }
432
433         return NT_STATUS_OK;
434 }
435
436 NTSTATUS libnet_vampire_cb_schema_chunk(void *private_data,
437                                         const struct libnet_BecomeDC_StoreChunk *c)
438 {
439         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
440         WERROR status;
441         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
442         uint32_t nc_object_count;
443         uint32_t nc_total_received = 0;
444         uint32_t object_count;
445         struct drsuapi_DsReplicaObjectListItemEx *first_object;
446         struct drsuapi_DsReplicaObjectListItemEx *cur;
447         uint32_t nc_linked_attributes_count;
448         uint32_t linked_attributes_count;
449
450         switch (c->ctr_level) {
451         case 1:
452                 mapping_ctr                     = &c->ctr1->mapping_ctr;
453                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
454                 object_count                    = c->ctr1->object_count;
455                 first_object                    = c->ctr1->first_object;
456                 nc_linked_attributes_count      = 0;
457                 linked_attributes_count         = 0;
458                 break;
459         case 6:
460                 mapping_ctr                     = &c->ctr6->mapping_ctr;
461                 nc_object_count                 = c->ctr6->nc_object_count;
462                 object_count                    = c->ctr6->object_count;
463                 first_object                    = c->ctr6->first_object;
464                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
465                 linked_attributes_count         = c->ctr6->linked_attributes_count;
466                 break;
467         default:
468                 return NT_STATUS_INVALID_PARAMETER;
469         }
470
471         if (!s->schema_part.first_object) {
472                 nc_total_received = object_count;
473         } else {
474                 nc_total_received = s->schema_part.object_count + object_count;
475         }
476         if (nc_object_count) {
477                 DEBUG(0,("Schema-DN[%s] objects[%u/%u] linked_values[%u/%u]\n",
478                         c->partition->nc.dn, nc_total_received, nc_object_count,
479                         linked_attributes_count, nc_linked_attributes_count));
480         } else {
481                 DEBUG(0,("Schema-DN[%s] objects[%u] linked_values[%u]\n",
482                 c->partition->nc.dn, nc_total_received, linked_attributes_count));
483         }
484
485         if (!s->self_made_schema) {
486                 WERROR werr;
487                 struct drsuapi_DsReplicaOIDMapping_Ctr mapping_ctr_without_schema_info;
488                 /* Put the DRS prefixmap aside for the schema we are
489                  * about to load in the provision, and into the one we
490                  * are making with the help of DRS */
491
492                 mapping_ctr_without_schema_info = *mapping_ctr;
493
494                 /* This strips off the 0xFF schema info from the end,
495                  * because we don't want it in the blob */
496                 if (mapping_ctr_without_schema_info.num_mappings > 0) {
497                         mapping_ctr_without_schema_info.num_mappings--;
498                 }
499                 werr = dsdb_get_drsuapi_prefixmap_as_blob(&mapping_ctr_without_schema_info, s, &s->prefixmap_blob);
500                 if (!W_ERROR_IS_OK(werr)) {
501                         return werror_to_ntstatus(werr);
502                 }
503
504                 /* Set up two manually-constructed schema - the local
505                  * schema from the provision will be used to build
506                  * one, which will then in turn be used to build the
507                  * other. */
508                 s->self_made_schema = dsdb_new_schema(s);
509                 NT_STATUS_HAVE_NO_MEMORY(s->self_made_schema);
510
511                 status = dsdb_load_prefixmap_from_drsuapi(s->self_made_schema, mapping_ctr);
512                 if (!W_ERROR_IS_OK(status)) {
513                         return werror_to_ntstatus(status);
514                 }
515         } else {
516                 status = dsdb_schema_pfm_contains_drsuapi_pfm(s->self_made_schema->prefixmap, mapping_ctr);
517                 if (!W_ERROR_IS_OK(status)) {
518                         return werror_to_ntstatus(status);
519                 }
520         }
521
522         if (!s->schema_part.first_object) {
523                 s->schema_part.object_count = object_count;
524                 s->schema_part.first_object = talloc_steal(s, first_object);
525         } else {
526                 s->schema_part.object_count             += object_count;
527                 s->schema_part.last_object->next_object = talloc_steal(s->schema_part.last_object,
528                                                                        first_object);
529         }
530         for (cur = first_object; cur->next_object; cur = cur->next_object) {}
531         s->schema_part.last_object = cur;
532
533         if (!c->partition->more_data) {
534                 return libnet_vampire_cb_apply_schema(s, c);
535         }
536
537         return NT_STATUS_OK;
538 }
539
540 NTSTATUS libnet_vampire_cb_store_chunk(void *private_data,
541                              const struct libnet_BecomeDC_StoreChunk *c)
542 {
543         struct libnet_vampire_cb_state *s = talloc_get_type(private_data, struct libnet_vampire_cb_state);
544         WERROR status;
545         struct dsdb_schema *schema;
546         const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
547         uint32_t nc_object_count;
548         uint32_t object_count;
549         struct drsuapi_DsReplicaObjectListItemEx *first_object;
550         uint32_t nc_linked_attributes_count;
551         uint32_t linked_attributes_count;
552         struct drsuapi_DsReplicaLinkedAttribute *linked_attributes;
553         const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector;
554         struct dsdb_extended_replicated_objects *objs;
555         uint32_t req_replica_flags;
556         uint32_t dsdb_repl_flags = 0;
557         struct repsFromTo1 *s_dsa;
558         char *tmp_dns_name;
559         uint32_t i;
560         uint64_t seq_num;
561         bool is_exop = false;
562
563         s_dsa                   = talloc_zero(s, struct repsFromTo1);
564         NT_STATUS_HAVE_NO_MEMORY(s_dsa);
565         s_dsa->other_info       = talloc(s_dsa, struct repsFromTo1OtherInfo);
566         NT_STATUS_HAVE_NO_MEMORY(s_dsa->other_info);
567
568         switch (c->ctr_level) {
569         case 1:
570                 mapping_ctr                     = &c->ctr1->mapping_ctr;
571                 nc_object_count                 = c->ctr1->extended_ret; /* maybe w2k send this unexpected? */
572                 object_count                    = c->ctr1->object_count;
573                 first_object                    = c->ctr1->first_object;
574                 nc_linked_attributes_count      = 0;
575                 linked_attributes_count         = 0;
576                 linked_attributes               = NULL;
577                 s_dsa->highwatermark            = c->ctr1->new_highwatermark;
578                 s_dsa->source_dsa_obj_guid      = c->ctr1->source_dsa_guid;
579                 s_dsa->source_dsa_invocation_id = c->ctr1->source_dsa_invocation_id;
580                 uptodateness_vector             = NULL; /* TODO: map it */
581                 break;
582         case 6:
583                 mapping_ctr                     = &c->ctr6->mapping_ctr;
584                 nc_object_count                 = c->ctr6->nc_object_count;
585                 object_count                    = c->ctr6->object_count;
586                 first_object                    = c->ctr6->first_object;
587                 nc_linked_attributes_count      = c->ctr6->nc_linked_attributes_count;
588                 linked_attributes_count         = c->ctr6->linked_attributes_count;
589                 linked_attributes               = c->ctr6->linked_attributes;
590                 s_dsa->highwatermark            = c->ctr6->new_highwatermark;
591                 s_dsa->source_dsa_obj_guid      = c->ctr6->source_dsa_guid;
592                 s_dsa->source_dsa_invocation_id = c->ctr6->source_dsa_invocation_id;
593                 uptodateness_vector             = c->ctr6->uptodateness_vector;
594                 break;
595         default:
596                 return NT_STATUS_INVALID_PARAMETER;
597         }
598
599         switch (c->req_level) {
600         case 0:
601                 /* none */
602                 req_replica_flags = 0;
603                 break;
604         case 5:
605                 if (c->req5->extended_op != DRSUAPI_EXOP_NONE) {
606                         is_exop = true;
607                 }
608                 req_replica_flags = c->req5->replica_flags;
609                 break;
610         case 8:
611                 if (c->req8->extended_op != DRSUAPI_EXOP_NONE) {
612                         is_exop = true;
613                 }
614                 req_replica_flags = c->req8->replica_flags;
615                 break;
616         case 10:
617                 if (c->req10->extended_op != DRSUAPI_EXOP_NONE) {
618                         is_exop = true;
619                 }
620                 req_replica_flags = c->req10->replica_flags;
621                 break;
622         default:
623                 return NT_STATUS_INVALID_PARAMETER;
624         }
625
626         if (req_replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
627                 /*
628                  * If we only replicate the critical objects
629                  * we should not remember what we already
630                  * got, as it is incomplete.
631                  */
632                 ZERO_STRUCT(s_dsa->highwatermark);
633                 uptodateness_vector = NULL;
634         }
635
636         /* TODO: avoid hardcoded flags */
637         s_dsa->replica_flags            = DRSUAPI_DRS_WRIT_REP
638                                         | DRSUAPI_DRS_INIT_SYNC
639                                         | DRSUAPI_DRS_PER_SYNC;
640         memset(s_dsa->schedule, 0x11, sizeof(s_dsa->schedule));
641
642         tmp_dns_name    = GUID_string(s_dsa->other_info, &s_dsa->source_dsa_obj_guid);
643         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
644         tmp_dns_name    = talloc_asprintf_append_buffer(tmp_dns_name, "._msdcs.%s", c->forest->dns_name);
645         NT_STATUS_HAVE_NO_MEMORY(tmp_dns_name);
646         s_dsa->other_info->dns_name = tmp_dns_name;
647
648         /* we want to show a count per partition */
649         if (!s->last_partition || strcmp(s->last_partition, c->partition->nc.dn) != 0) {
650                 s->total_objects = 0;
651                 talloc_free(s->last_partition);
652                 s->last_partition = talloc_strdup(s, c->partition->nc.dn);
653         }
654         s->total_objects += object_count;
655
656         if (is_exop) {
657                 if (nc_object_count) {
658                         DEBUG(0,("Exop on[%s] objects[%u/%u] linked_values[%u/%u]\n",
659                                 c->partition->nc.dn, s->total_objects, nc_object_count,
660                                 linked_attributes_count, nc_linked_attributes_count));
661                 } else {
662                         DEBUG(0,("Exop on[%s] objects[%u] linked_values[%u]\n",
663                         c->partition->nc.dn, s->total_objects, linked_attributes_count));
664                 }
665         } else {
666                 if (nc_object_count) {
667                         DEBUG(0,("Partition[%s] objects[%u/%u] linked_values[%u/%u]\n",
668                                 c->partition->nc.dn, s->total_objects, nc_object_count,
669                                 linked_attributes_count, nc_linked_attributes_count));
670                 } else {
671                         DEBUG(0,("Partition[%s] objects[%u] linked_values[%u]\n",
672                         c->partition->nc.dn, s->total_objects, linked_attributes_count));
673                 }
674         }
675
676
677         schema = dsdb_get_schema(s->ldb, NULL);
678         if (!schema) {
679                 DEBUG(0,(__location__ ": Schema is not loaded yet!\n"));
680                 return NT_STATUS_INTERNAL_ERROR;
681         }
682
683         if (req_replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
684                 dsdb_repl_flags |= DSDB_REPL_FLAG_EXPECT_NO_SECRETS;
685         }
686
687         status = dsdb_replicated_objects_convert(s->ldb,
688                                                  schema,
689                                                  c->partition->nc.dn,
690                                                  mapping_ctr,
691                                                  object_count,
692                                                  first_object,
693                                                  linked_attributes_count,
694                                                  linked_attributes,
695                                                  s_dsa,
696                                                  uptodateness_vector,
697                                                  c->gensec_skey,
698                                                  dsdb_repl_flags,
699                                                  s, &objs);
700         if (!W_ERROR_IS_OK(status)) {
701                 DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
702                 return werror_to_ntstatus(status);
703         }
704
705         if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
706                 for (i=0; i < objs->num_objects; i++) {
707                         struct ldb_ldif ldif;
708                         fprintf(stdout, "#\n");
709                         ldif.changetype = LDB_CHANGETYPE_NONE;
710                         ldif.msg = objs->objects[i].msg;
711                         ldb_ldif_write_file(s->ldb, stdout, &ldif);
712                         NDR_PRINT_DEBUG(replPropertyMetaDataBlob, objs->objects[i].meta_data);
713                 }
714         }
715         status = dsdb_replicated_objects_commit(s->ldb, NULL, objs, &seq_num);
716         if (!W_ERROR_IS_OK(status)) {
717                 DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
718                 return werror_to_ntstatus(status);
719         }
720
721         talloc_free(s_dsa);
722         talloc_free(objs);
723
724         for (i=0; i < linked_attributes_count; i++) {
725                 const struct dsdb_attribute *sa;
726
727                 if (!linked_attributes[i].identifier) {
728                         DEBUG(0, ("No linked attribute identifier\n"));
729                         return NT_STATUS_FOOBAR;
730                 }
731
732                 if (!linked_attributes[i].value.blob) {
733                         DEBUG(0, ("No linked attribute value\n"));
734                         return NT_STATUS_FOOBAR;
735                 }
736
737                 sa = dsdb_attribute_by_attributeID_id(s->schema,
738                                                       linked_attributes[i].attid);
739                 if (!sa) {
740                         DEBUG(0, ("Unable to find attribute via attribute id %d\n", linked_attributes[i].attid));
741                         return NT_STATUS_FOOBAR;
742                 }
743
744                 if (lpcfg_parm_bool(s->lp_ctx, NULL, "become dc", "dump objects", false)) {
745                         DEBUG(0,("# %s\n", sa->lDAPDisplayName));
746                         NDR_PRINT_DEBUG(drsuapi_DsReplicaLinkedAttribute, &linked_attributes[i]);
747                         dump_data(0,
748                                 linked_attributes[i].value.blob->data,
749                                 linked_attributes[i].value.blob->length);
750                 }
751         }
752
753         return NT_STATUS_OK;
754 }
755