3c7b8b1646555f39b426aa363e1c959027e9ab77
[samba.git] / source4 / dsdb / samdb / ldb_modules / repl_meta_data.c
1 /*
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004-2008
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2013
6    Copyright (C) Andrew Tridgell 2005-2009
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
8    Copyright (C) Matthieu Patou <mat@samba.org> 2010-2011
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  *  Name: ldb
26  *
27  *  Component: ldb repl_meta_data module
28  *
29  *  Description: - add a unique objectGUID onto every new record,
30  *               - handle whenCreated, whenChanged timestamps
31  *               - handle uSNCreated, uSNChanged numbers
32  *               - handle replPropertyMetaData attribute
33  *
34  *  Author: Simo Sorce
35  *  Author: Stefan Metzmacher
36  */
37
38 #include "includes.h"
39 #include "ldb_module.h"
40 #include "dsdb/samdb/samdb.h"
41 #include "dsdb/common/proto.h"
42 #include "dsdb/common/util.h"
43 #include "../libds/common/flags.h"
44 #include "librpc/gen_ndr/irpc.h"
45 #include "librpc/gen_ndr/ndr_misc.h"
46 #include "librpc/gen_ndr/ndr_drsuapi.h"
47 #include "librpc/gen_ndr/ndr_drsblobs.h"
48 #include "param/param.h"
49 #include "libcli/security/security.h"
50 #include "lib/util/dlinklist.h"
51 #include "dsdb/samdb/ldb_modules/util.h"
52 #include "lib/util/tsort.h"
53
54 #undef DBGC_CLASS
55 #define DBGC_CLASS            DBGC_DRS_REPL
56
57 /* the RMD_VERSION for linked attributes starts from 1 */
58 #define RMD_VERSION_INITIAL   1
59
60 /*
61  * It's 29/12/9999 at 23:59:59 UTC as specified in MS-ADTS 7.1.1.4.2
62  * Deleted Objects Container
63  */
64 static const NTTIME DELETED_OBJECT_CONTAINER_CHANGE_TIME = 2650466015990000000ULL;
65
66 struct replmd_private {
67         TALLOC_CTX *la_ctx;
68         struct la_group *la_list;
69         struct nc_entry {
70                 struct nc_entry *prev, *next;
71                 struct ldb_dn *dn;
72                 uint64_t mod_usn;
73                 uint64_t mod_usn_urgent;
74         } *ncs;
75         struct ldb_dn *schema_dn;
76         bool originating_updates;
77         bool sorted_links;
78         uint32_t total_links;
79         uint32_t num_processed;
80 };
81
82 /*
83  * groups link attributes together by source-object and attribute-ID,
84  * to improve processing efficiency (i.e. for 'member' attribute, which
85  * could have 100s or 1000s of links).
86  * Note this grouping is best effort - the same source object could still
87  * correspond to several la_groups (a lot depends on the order DRS sends
88  * the links in). The groups currently don't span replication chunks (which
89  * caps the size to ~1500 links by default).
90  */
91 struct la_group {
92         struct la_group *next, *prev;
93         struct la_entry *la_entries;
94 };
95
96 struct la_entry {
97         struct la_entry *next, *prev;
98         struct drsuapi_DsReplicaLinkedAttribute *la;
99         uint32_t dsdb_repl_flags;
100 };
101
102 struct replmd_replicated_request {
103         struct ldb_module *module;
104         struct ldb_request *req;
105
106         const struct dsdb_schema *schema;
107         struct GUID our_invocation_id;
108
109         /* the controls we pass down */
110         struct ldb_control **controls;
111
112         /*
113          * Backlinks for the replmd_add() case (we want to create
114          * backlinks after creating the user, but before the end of
115          * the ADD request) 
116          */
117         struct la_backlink *la_backlinks;
118
119         /* details for the mode where we apply a bunch of inbound replication meessages */
120         bool apply_mode;
121         uint32_t index_current;
122         struct dsdb_extended_replicated_objects *objs;
123
124         struct ldb_message *search_msg;
125         struct GUID local_parent_guid;
126
127         uint64_t seq_num;
128         bool is_urgent;
129
130         bool isDeleted;
131
132         bool fix_link_sid;
133 };
134
135 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
136 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete);
137 static int replmd_check_upgrade_links(struct ldb_context *ldb,
138                                       struct parsed_dn *dns, uint32_t count,
139                                       struct ldb_message_element *el,
140                                       const char *ldap_oid);
141 static int replmd_verify_linked_attribute(struct replmd_replicated_request *ar,
142                                           struct la_entry *la);
143 static int replmd_set_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
144                              struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
145                              uint64_t usn, uint64_t local_usn, NTTIME nttime,
146                              uint32_t version, bool deleted);
147
148 static int replmd_make_deleted_child_dn(TALLOC_CTX *tmp_ctx,
149                                         struct ldb_context *ldb,
150                                         struct ldb_dn *dn,
151                                         const char *rdn_name,
152                                         const struct ldb_val *rdn_value,
153                                         struct GUID guid);
154
155 enum urgent_situation {
156         REPL_URGENT_ON_CREATE = 1,
157         REPL_URGENT_ON_UPDATE = 2,
158         REPL_URGENT_ON_DELETE = 4
159 };
160
161 enum deletion_state {
162         OBJECT_NOT_DELETED=1,
163         OBJECT_DELETED=2,
164         OBJECT_RECYCLED=3,
165         OBJECT_TOMBSTONE=4,
166         OBJECT_REMOVED=5
167 };
168
169 static void replmd_deletion_state(struct ldb_module *module,
170                                   const struct ldb_message *msg,
171                                   enum deletion_state *current_state,
172                                   enum deletion_state *next_state)
173 {
174         int ret;
175         bool enabled = false;
176
177         if (msg == NULL) {
178                 *current_state = OBJECT_REMOVED;
179                 if (next_state != NULL) {
180                         *next_state = OBJECT_REMOVED;
181                 }
182                 return;
183         }
184
185         ret = dsdb_recyclebin_enabled(module, &enabled);
186         if (ret != LDB_SUCCESS) {
187                 enabled = false;
188         }
189
190         if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
191                 if (!enabled) {
192                         *current_state = OBJECT_TOMBSTONE;
193                         if (next_state != NULL) {
194                                 *next_state = OBJECT_REMOVED;
195                         }
196                         return;
197                 }
198
199                 if (ldb_msg_check_string_attribute(msg, "isRecycled", "TRUE")) {
200                         *current_state = OBJECT_RECYCLED;
201                         if (next_state != NULL) {
202                                 *next_state = OBJECT_REMOVED;
203                         }
204                         return;
205                 }
206
207                 *current_state = OBJECT_DELETED;
208                 if (next_state != NULL) {
209                         *next_state = OBJECT_RECYCLED;
210                 }
211                 return;
212         }
213
214         *current_state = OBJECT_NOT_DELETED;
215         if (next_state == NULL) {
216                 return;
217         }
218
219         if (enabled) {
220                 *next_state = OBJECT_DELETED;
221         } else {
222                 *next_state = OBJECT_TOMBSTONE;
223         }
224 }
225
226 static const struct {
227         const char *update_name;
228         enum urgent_situation repl_situation;
229 } urgent_objects[] = {
230                 {"nTDSDSA", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE)},
231                 {"crossRef", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE)},
232                 {"attributeSchema", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
233                 {"classSchema", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
234                 {"secret", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
235                 {"rIDManager", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
236                 {NULL, 0}
237 };
238
239 /* Attributes looked for when updating or deleting, to check for a urgent replication needed */
240 static const char *urgent_attrs[] = {
241                 "lockoutTime",
242                 "pwdLastSet",
243                 "userAccountControl",
244                 NULL
245 };
246
247
248 static bool replmd_check_urgent_objectclass(const struct ldb_message_element *objectclass_el,
249                                         enum urgent_situation situation)
250 {
251         unsigned int i, j;
252         for (i=0; urgent_objects[i].update_name; i++) {
253
254                 if ((situation & urgent_objects[i].repl_situation) == 0) {
255                         continue;
256                 }
257
258                 for (j=0; j<objectclass_el->num_values; j++) {
259                         const struct ldb_val *v = &objectclass_el->values[j];
260                         if (ldb_attr_cmp((const char *)v->data, urgent_objects[i].update_name) == 0) {
261                                 return true;
262                         }
263                 }
264         }
265         return false;
266 }
267
268 static bool replmd_check_urgent_attribute(const struct ldb_message_element *el)
269 {
270         if (ldb_attr_in_list(urgent_attrs, el->name)) {
271                 return true;
272         }
273         return false;
274 }
275
276 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar);
277
278 /*
279   initialise the module
280   allocate the private structure and build the list
281   of partition DNs for use by replmd_notify()
282  */
283 static int replmd_init(struct ldb_module *module)
284 {
285         struct replmd_private *replmd_private;
286         struct ldb_context *ldb = ldb_module_get_ctx(module);
287         static const char *samba_dsdb_attrs[] = { SAMBA_COMPATIBLE_FEATURES_ATTR, NULL };
288         struct ldb_dn *samba_dsdb_dn;
289         struct ldb_result *res;
290         int ret;
291         TALLOC_CTX *frame = talloc_stackframe();
292         replmd_private = talloc_zero(module, struct replmd_private);
293         if (replmd_private == NULL) {
294                 ldb_oom(ldb);
295                 TALLOC_FREE(frame);
296                 return LDB_ERR_OPERATIONS_ERROR;
297         }
298         ldb_module_set_private(module, replmd_private);
299
300         replmd_private->schema_dn = ldb_get_schema_basedn(ldb);
301
302         samba_dsdb_dn = ldb_dn_new(frame, ldb, "@SAMBA_DSDB");
303         if (!samba_dsdb_dn) {
304                 TALLOC_FREE(frame);
305                 return ldb_oom(ldb);
306         }
307
308         ret = dsdb_module_search_dn(module, frame, &res, samba_dsdb_dn,
309                                     samba_dsdb_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
310         if (ret == LDB_SUCCESS) {
311                 replmd_private->sorted_links
312                         = ldb_msg_check_string_attribute(res->msgs[0],
313                                                          SAMBA_COMPATIBLE_FEATURES_ATTR,
314                                                          SAMBA_SORTED_LINKS_FEATURE);
315         }
316         TALLOC_FREE(frame);
317
318         return ldb_next_init(module);
319 }
320
321 /*
322   cleanup our per-transaction contexts
323  */
324 static void replmd_txn_cleanup(struct replmd_private *replmd_private)
325 {
326         talloc_free(replmd_private->la_ctx);
327         replmd_private->la_list = NULL;
328         replmd_private->la_ctx = NULL;
329
330 }
331
332
333 struct la_backlink {
334         struct la_backlink *next, *prev;
335         const char *attr_name;
336         struct ldb_dn *forward_dn;
337         struct GUID target_guid;
338         bool active;
339 };
340
341 /*
342   a ldb_modify request operating on modules below the
343   current module
344  */
345 static int linked_attr_modify(struct ldb_module *module,
346                               const struct ldb_message *message,
347                               struct ldb_request *parent)
348 {
349         struct ldb_request *mod_req;
350         int ret;
351         struct ldb_context *ldb = ldb_module_get_ctx(module);
352         TALLOC_CTX *tmp_ctx = talloc_new(module);
353         struct ldb_result *res;
354
355         res = talloc_zero(tmp_ctx, struct ldb_result);
356         if (!res) {
357                 talloc_free(tmp_ctx);
358                 return ldb_oom(ldb_module_get_ctx(module));
359         }
360
361         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
362                                 message,
363                                 NULL,
364                                 res,
365                                 ldb_modify_default_callback,
366                                 parent);
367         LDB_REQ_SET_LOCATION(mod_req);
368         if (ret != LDB_SUCCESS) {
369                 talloc_free(tmp_ctx);
370                 return ret;
371         }
372
373         ret = ldb_request_add_control(mod_req, DSDB_CONTROL_REPLICATED_UPDATE_OID,
374                                       false, NULL);
375         if (ret != LDB_SUCCESS) {
376                 return ret;
377         }
378
379         /* Run the new request */
380         ret = ldb_next_request(module, mod_req);
381
382         if (ret == LDB_SUCCESS) {
383                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
384         }
385
386         talloc_free(tmp_ctx);
387         return ret;
388 }
389
390 /*
391   process a backlinks we accumulated during a transaction, adding and
392   deleting the backlinks from the target objects
393  */
394 static int replmd_process_backlink(struct ldb_module *module, struct la_backlink *bl, struct ldb_request *parent)
395 {
396         struct ldb_dn *target_dn, *source_dn;
397         int ret;
398         struct ldb_context *ldb = ldb_module_get_ctx(module);
399         struct ldb_message *msg;
400         TALLOC_CTX *frame = talloc_stackframe();
401         char *dn_string;
402
403         /*
404           - find DN of target
405           - find DN of source
406           - construct ldb_message
407               - either an add or a delete
408          */
409         ret = dsdb_module_dn_by_guid(module, frame, &bl->target_guid, &target_dn, parent);
410         if (ret != LDB_SUCCESS) {
411                 struct GUID_txt_buf guid_str;
412                 DBG_WARNING("Failed to find target DN for linked attribute with GUID %s\n",
413                             GUID_buf_string(&bl->target_guid, &guid_str));
414                 DBG_WARNING("Please run 'samba-tool dbcheck' to resolve any missing backlinks.\n");
415                 talloc_free(frame);
416                 return LDB_SUCCESS;
417         }
418
419         msg = ldb_msg_new(frame);
420         if (msg == NULL) {
421                 ldb_module_oom(module);
422                 talloc_free(frame);
423                 return LDB_ERR_OPERATIONS_ERROR;
424         }
425
426         source_dn = ldb_dn_copy(frame, bl->forward_dn);
427         if (!source_dn) {
428                 ldb_module_oom(module);
429                 talloc_free(frame);
430                 return LDB_ERR_OPERATIONS_ERROR;
431         } else {
432                 /* Filter down to the attributes we want in the backlink */
433                 const char *accept[] = { "GUID", "SID", NULL };
434                 ldb_dn_extended_filter(source_dn, accept);
435         }
436
437         /* construct a ldb_message for adding/deleting the backlink */
438         msg->dn = target_dn;
439         dn_string = ldb_dn_get_extended_linearized(frame, bl->forward_dn, 1);
440         if (!dn_string) {
441                 ldb_module_oom(module);
442                 talloc_free(frame);
443                 return LDB_ERR_OPERATIONS_ERROR;
444         }
445         ret = ldb_msg_add_steal_string(msg, bl->attr_name, dn_string);
446         if (ret != LDB_SUCCESS) {
447                 talloc_free(frame);
448                 return ret;
449         }
450         msg->elements[0].flags = bl->active?LDB_FLAG_MOD_ADD:LDB_FLAG_MOD_DELETE;
451
452         /* a backlink should never be single valued. Unfortunately the
453            exchange schema has a attribute
454            msExchBridgeheadedLocalConnectorsDNBL which is single
455            valued and a backlink. We need to cope with that by
456            ignoring the single value flag */
457         msg->elements[0].flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
458
459         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
460         if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && !bl->active) {
461                 /* we allow LDB_ERR_NO_SUCH_ATTRIBUTE as success to
462                    cope with possible corruption where the backlink has
463                    already been removed */
464                 DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n",
465                          ldb_dn_get_linearized(target_dn),
466                          ldb_dn_get_linearized(source_dn),
467                          ldb_errstring(ldb)));
468                 ret = LDB_SUCCESS;
469         } else if (ret != LDB_SUCCESS) {
470                 ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s",
471                                        bl->active?"add":"remove",
472                                        ldb_dn_get_linearized(source_dn),
473                                        ldb_dn_get_linearized(target_dn),
474                                        ldb_errstring(ldb));
475                 talloc_free(frame);
476                 return ret;
477         }
478         talloc_free(frame);
479         return ret;
480 }
481
482 /*
483   add a backlink to the list of backlinks to add/delete in the prepare
484   commit
485
486   forward_dn is stolen onto the defereed context
487  */
488 static int replmd_defer_add_backlink(struct ldb_module *module,
489                                      struct replmd_private *replmd_private,
490                                      const struct dsdb_schema *schema,
491                                      struct replmd_replicated_request *ac,
492                                      struct ldb_dn *forward_dn,
493                                      struct GUID *target_guid, bool active,
494                                      const struct dsdb_attribute *schema_attr,
495                                      struct ldb_request *parent)
496 {
497         const struct dsdb_attribute *target_attr;
498         struct la_backlink *bl;
499         
500         bl = talloc(ac, struct la_backlink);
501         if (bl == NULL) {
502                 ldb_module_oom(module);
503                 return LDB_ERR_OPERATIONS_ERROR;
504         }
505
506         target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1);
507         if (!target_attr) {
508                 /*
509                  * windows 2003 has a broken schema where the
510                  * definition of msDS-IsDomainFor is missing (which is
511                  * supposed to be the backlink of the
512                  * msDS-HasDomainNCs attribute
513                  */
514                 return LDB_SUCCESS;
515         }
516
517         bl->attr_name = target_attr->lDAPDisplayName;
518         bl->forward_dn = talloc_steal(bl, forward_dn);
519         bl->target_guid = *target_guid;
520         bl->active = active;
521
522         DLIST_ADD(ac->la_backlinks, bl);
523
524         return LDB_SUCCESS;
525 }
526
527 /*
528   add a backlink to the list of backlinks to add/delete in the prepare
529   commit
530  */
531 static int replmd_add_backlink(struct ldb_module *module,
532                                struct replmd_private *replmd_private,
533                                const struct dsdb_schema *schema,
534                                struct ldb_dn *forward_dn,
535                                struct GUID *target_guid, bool active,
536                                const struct dsdb_attribute *schema_attr,
537                                struct ldb_request *parent)
538 {
539         const struct dsdb_attribute *target_attr;
540         struct la_backlink bl;
541         int ret;
542         
543         target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1);
544         if (!target_attr) {
545                 /*
546                  * windows 2003 has a broken schema where the
547                  * definition of msDS-IsDomainFor is missing (which is
548                  * supposed to be the backlink of the
549                  * msDS-HasDomainNCs attribute
550                  */
551                 return LDB_SUCCESS;
552         }
553
554         bl.attr_name = target_attr->lDAPDisplayName;
555         bl.forward_dn = forward_dn;
556         bl.target_guid = *target_guid;
557         bl.active = active;
558
559         ret = replmd_process_backlink(module, &bl, parent);
560         return ret;
561 }
562
563
564 /*
565  * Callback for most write operations in this module:
566  *
567  * notify the repl task that a object has changed. The notifies are
568  * gathered up in the replmd_private structure then written to the
569  * @REPLCHANGED object in each partition during the prepare_commit
570  */
571 static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares)
572 {
573         int ret;
574         struct replmd_replicated_request *ac =
575                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
576         struct replmd_private *replmd_private =
577                 talloc_get_type_abort(ldb_module_get_private(ac->module), struct replmd_private);
578         struct nc_entry *modified_partition;
579         struct ldb_control *partition_ctrl;
580         const struct dsdb_control_current_partition *partition;
581
582         struct ldb_control **controls;
583
584         partition_ctrl = ldb_reply_get_control(ares, DSDB_CONTROL_CURRENT_PARTITION_OID);
585
586         controls = ares->controls;
587         if (ldb_request_get_control(ac->req,
588                                     DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
589                 /*
590                  * Remove the current partition control from what we pass up
591                  * the chain if it hasn't been requested manually.
592                  */
593                 controls = ldb_controls_except_specified(ares->controls, ares,
594                                                          partition_ctrl);
595         }
596
597         if (ares->error != LDB_SUCCESS) {
598                 struct GUID_txt_buf guid_txt;
599                 struct ldb_message *msg = NULL;
600                 char *s = NULL;
601
602                 if (ac->apply_mode == false) {
603                         DBG_NOTICE("Originating update failure. Error is: %s\n",
604                                    ldb_strerror(ares->error));
605                         return ldb_module_done(ac->req, controls,
606                                                ares->response, ares->error);
607                 }
608
609                 msg = ac->objs->objects[ac->index_current].msg;
610                 /*
611                  * Set at DBG_NOTICE as once these start to happe, they
612                  * will happen a lot until resolved, due to repeated
613                  * replication.  The caller will probably print the
614                  * ldb error string anyway.
615                  */
616                 DBG_NOTICE("DRS replication apply failure for %s. Error is: %s\n",
617                            ldb_dn_get_linearized(msg->dn),
618                            ldb_strerror(ares->error));
619
620                 s = ldb_ldif_message_redacted_string(ldb_module_get_ctx(ac->module),
621                                                      ac,
622                                                      LDB_CHANGETYPE_ADD,
623                                                      msg);
624
625                 DBG_INFO("Failing DRS %s replication message was %s:\n%s\n",
626                          ac->search_msg == NULL ? "ADD" : "MODIFY",
627                          GUID_buf_string(&ac->objs->objects[ac->index_current].object_guid,
628                                          &guid_txt),
629                          s);
630                 talloc_free(s);
631                 return ldb_module_done(ac->req, controls,
632                                        ares->response, ares->error);
633         }
634
635         if (ares->type != LDB_REPLY_DONE) {
636                 ldb_set_errstring(ldb_module_get_ctx(ac->module), "Invalid reply type for notify\n!");
637                 return ldb_module_done(ac->req, NULL,
638                                        NULL, LDB_ERR_OPERATIONS_ERROR);
639         }
640
641         if (ac->apply_mode == false) {
642                 struct la_backlink *bl;
643                 /*
644                  * process our backlink list after an replmd_add(),
645                  * creating and deleting backlinks as necessary (this
646                  * code is sync).  The other cases are handled inline
647                  * with the modify.
648                  */
649                 for (bl=ac->la_backlinks; bl; bl=bl->next) {
650                         ret = replmd_process_backlink(ac->module, bl, ac->req);
651                         if (ret != LDB_SUCCESS) {
652                                 return ldb_module_done(ac->req, NULL,
653                                                        NULL, ret);
654                         }
655                 }
656         }
657         
658         if (!partition_ctrl) {
659                 ldb_set_errstring(ldb_module_get_ctx(ac->module),"No partition control on reply");
660                 return ldb_module_done(ac->req, NULL,
661                                        NULL, LDB_ERR_OPERATIONS_ERROR);
662         }
663
664         partition = talloc_get_type_abort(partition_ctrl->data,
665                                     struct dsdb_control_current_partition);
666
667         if (ac->seq_num > 0) {
668                 for (modified_partition = replmd_private->ncs; modified_partition;
669                      modified_partition = modified_partition->next) {
670                         if (ldb_dn_compare(modified_partition->dn, partition->dn) == 0) {
671                                 break;
672                         }
673                 }
674
675                 if (modified_partition == NULL) {
676                         modified_partition = talloc_zero(replmd_private, struct nc_entry);
677                         if (!modified_partition) {
678                                 ldb_oom(ldb_module_get_ctx(ac->module));
679                                 return ldb_module_done(ac->req, NULL,
680                                                        NULL, LDB_ERR_OPERATIONS_ERROR);
681                         }
682                         modified_partition->dn = ldb_dn_copy(modified_partition, partition->dn);
683                         if (!modified_partition->dn) {
684                                 ldb_oom(ldb_module_get_ctx(ac->module));
685                                 return ldb_module_done(ac->req, NULL,
686                                                        NULL, LDB_ERR_OPERATIONS_ERROR);
687                         }
688                         DLIST_ADD(replmd_private->ncs, modified_partition);
689                 }
690
691                 if (ac->seq_num > modified_partition->mod_usn) {
692                         modified_partition->mod_usn = ac->seq_num;
693                         if (ac->is_urgent) {
694                                 modified_partition->mod_usn_urgent = ac->seq_num;
695                         }
696                 }
697                 if (!ac->apply_mode) {
698                         replmd_private->originating_updates = true;
699                 }
700         }
701
702         if (ac->apply_mode) {
703                 ret = replmd_replicated_apply_isDeleted(ac);
704                 if (ret != LDB_SUCCESS) {
705                         return ldb_module_done(ac->req, NULL, NULL, ret);
706                 }
707                 return ret;
708         } else {
709                 /* free the partition control container here, for the
710                  * common path.  Other cases will have it cleaned up
711                  * eventually with the ares */
712                 talloc_free(partition_ctrl);
713                 return ldb_module_done(ac->req, controls,
714                                        ares->response, LDB_SUCCESS);
715         }
716 }
717
718
719 /*
720  * update a @REPLCHANGED record in each partition if there have been
721  * any writes of replicated data in the partition
722  */
723 static int replmd_notify_store(struct ldb_module *module, struct ldb_request *parent)
724 {
725         struct replmd_private *replmd_private =
726                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
727
728         while (replmd_private->ncs) {
729                 int ret;
730                 struct nc_entry *modified_partition = replmd_private->ncs;
731
732                 ret = dsdb_module_save_partition_usn(module, modified_partition->dn,
733                                                      modified_partition->mod_usn,
734                                                      modified_partition->mod_usn_urgent, parent);
735                 if (ret != LDB_SUCCESS) {
736                         DEBUG(0,(__location__ ": Failed to save partition uSN for %s\n",
737                                  ldb_dn_get_linearized(modified_partition->dn)));
738                         return ret;
739                 }
740
741                 if (ldb_dn_compare(modified_partition->dn,
742                                    replmd_private->schema_dn) == 0) {
743                         struct ldb_result *ext_res;
744                         ret = dsdb_module_extended(module,
745                                                    replmd_private->schema_dn,
746                                                    &ext_res,
747                                                    DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID,
748                                                    ext_res,
749                                                    DSDB_FLAG_NEXT_MODULE,
750                                                    parent);
751                         if (ret != LDB_SUCCESS) {
752                                 return ret;
753                         }
754                         talloc_free(ext_res);
755                 }
756
757                 DLIST_REMOVE(replmd_private->ncs, modified_partition);
758                 talloc_free(modified_partition);
759         }
760
761         return LDB_SUCCESS;
762 }
763
764
765 /*
766   created a replmd_replicated_request context
767  */
768 static struct replmd_replicated_request *replmd_ctx_init(struct ldb_module *module,
769                                                          struct ldb_request *req)
770 {
771         struct ldb_context *ldb;
772         struct replmd_replicated_request *ac;
773         const struct GUID *our_invocation_id;
774
775         ldb = ldb_module_get_ctx(module);
776
777         ac = talloc_zero(req, struct replmd_replicated_request);
778         if (ac == NULL) {
779                 ldb_oom(ldb);
780                 return NULL;
781         }
782
783         ac->module = module;
784         ac->req = req;
785
786         ac->schema = dsdb_get_schema(ldb, ac);
787         if (!ac->schema) {
788                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
789                               "replmd_modify: no dsdb_schema loaded");
790                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
791                 talloc_free(ac);
792                 return NULL;
793         }
794
795         /* get our invocationId */
796         our_invocation_id = samdb_ntds_invocation_id(ldb);
797         if (!our_invocation_id) {
798                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
799                               "replmd_add: unable to find invocationId\n");
800                 talloc_free(ac);
801                 return NULL;
802         }
803         ac->our_invocation_id = *our_invocation_id;
804
805         return ac;
806 }
807
808 /*
809   add a time element to a record
810 */
811 static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
812 {
813         struct ldb_message_element *el;
814         char *s;
815         int ret;
816
817         if (ldb_msg_find_element(msg, attr) != NULL) {
818                 return LDB_SUCCESS;
819         }
820
821         s = ldb_timestring(msg, t);
822         if (s == NULL) {
823                 return LDB_ERR_OPERATIONS_ERROR;
824         }
825
826         ret = ldb_msg_add_string(msg, attr, s);
827         if (ret != LDB_SUCCESS) {
828                 return ret;
829         }
830
831         el = ldb_msg_find_element(msg, attr);
832         /* always set as replace. This works because on add ops, the flag
833            is ignored */
834         el->flags = LDB_FLAG_MOD_REPLACE;
835
836         return LDB_SUCCESS;
837 }
838
839 /*
840   add a uint64_t element to a record
841 */
842 static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg,
843                               const char *attr, uint64_t v)
844 {
845         struct ldb_message_element *el;
846         int ret;
847
848         if (ldb_msg_find_element(msg, attr) != NULL) {
849                 return LDB_SUCCESS;
850         }
851
852         ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v);
853         if (ret != LDB_SUCCESS) {
854                 return ret;
855         }
856
857         el = ldb_msg_find_element(msg, attr);
858         /* always set as replace. This works because on add ops, the flag
859            is ignored */
860         el->flags = LDB_FLAG_MOD_REPLACE;
861
862         return LDB_SUCCESS;
863 }
864
865 static int replmd_replPropertyMetaData1_attid_sort(const struct replPropertyMetaData1 *m1,
866                                                    const struct replPropertyMetaData1 *m2,
867                                                    const uint32_t *rdn_attid)
868 {
869         /*
870          * This assignment seems inoccous, but it is critical for the
871          * system, as we need to do the comparisons as a unsigned
872          * quantity, not signed (enums are signed integers)
873          */
874         uint32_t attid_1 = m1->attid;
875         uint32_t attid_2 = m2->attid;
876
877         if (attid_1 == attid_2) {
878                 return 0;
879         }
880
881         /*
882          * See above regarding this being an unsigned comparison.
883          * Otherwise when the high bit is set on non-standard
884          * attributes, they would end up first, before objectClass
885          * (0).
886          */
887         return attid_1 > attid_2 ? 1 : -1;
888 }
889
890 static int replmd_replPropertyMetaDataCtr1_verify(struct ldb_context *ldb,
891                                                   struct replPropertyMetaDataCtr1 *ctr1,
892                                                   struct ldb_dn *dn)
893 {
894         if (ctr1->count == 0) {
895                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
896                               "No elements found in replPropertyMetaData for %s!\n",
897                               ldb_dn_get_linearized(dn));
898                 return LDB_ERR_CONSTRAINT_VIOLATION;
899         }
900
901         /* the objectClass attribute is value 0x00000000, so must be first */
902         if (ctr1->array[0].attid != DRSUAPI_ATTID_objectClass) {
903                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
904                               "No objectClass found in replPropertyMetaData for %s!\n",
905                               ldb_dn_get_linearized(dn));
906                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
907         }
908
909         return LDB_SUCCESS;
910 }
911
912 static int replmd_replPropertyMetaDataCtr1_sort_and_verify(struct ldb_context *ldb,
913                                                            struct replPropertyMetaDataCtr1 *ctr1,
914                                                            struct ldb_dn *dn)
915 {
916         /* Note this is O(n^2) for the almost-sorted case, which this is */
917         LDB_TYPESAFE_QSORT(ctr1->array, ctr1->count, NULL,
918                            replmd_replPropertyMetaData1_attid_sort);
919         return replmd_replPropertyMetaDataCtr1_verify(ldb, ctr1, dn);
920 }
921
922 static int replmd_ldb_message_element_attid_sort(const struct ldb_message_element *e1,
923                                                  const struct ldb_message_element *e2,
924                                                  const struct dsdb_schema *schema)
925 {
926         const struct dsdb_attribute *a1;
927         const struct dsdb_attribute *a2;
928
929         /*
930          * TODO: make this faster by caching the dsdb_attribute pointer
931          *       on the ldb_messag_element
932          */
933
934         a1 = dsdb_attribute_by_lDAPDisplayName(schema, e1->name);
935         a2 = dsdb_attribute_by_lDAPDisplayName(schema, e2->name);
936
937         /*
938          * TODO: remove this check, we should rely on e1 and e2 having valid attribute names
939          *       in the schema
940          */
941         if (!a1 || !a2) {
942                 return strcasecmp(e1->name, e2->name);
943         }
944         if (a1->attributeID_id == a2->attributeID_id) {
945                 return 0;
946         }
947         return a1->attributeID_id > a2->attributeID_id ? 1 : -1;
948 }
949
950 static void replmd_ldb_message_sort(struct ldb_message *msg,
951                                     const struct dsdb_schema *schema)
952 {
953         LDB_TYPESAFE_QSORT(msg->elements, msg->num_elements, schema, replmd_ldb_message_element_attid_sort);
954 }
955
956 static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
957                                const struct GUID *invocation_id,
958                                uint64_t local_usn, NTTIME nttime);
959
960 static int parsed_dn_compare(struct parsed_dn *pdn1, struct parsed_dn *pdn2);
961
962 static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
963                           struct ldb_message_element *el, struct parsed_dn **pdn,
964                           const char *ldap_oid, struct ldb_request *parent);
965
966 static int check_parsed_dn_duplicates(struct ldb_module *module,
967                                       struct ldb_message_element *el,
968                                       struct parsed_dn *pdn);
969
970 /*
971   fix up linked attributes in replmd_add.
972   This involves setting up the right meta-data in extended DN
973   components, and creating backlinks to the object
974  */
975 static int replmd_add_fix_la(struct ldb_module *module, TALLOC_CTX *mem_ctx,
976                              struct replmd_private *replmd_private,
977                              struct ldb_message_element *el,
978                              struct replmd_replicated_request *ac,
979                              NTTIME now,
980                              struct ldb_dn *forward_dn,
981                              const struct dsdb_attribute *sa,
982                              struct ldb_request *parent)
983 {
984         unsigned int i;
985         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
986         struct ldb_context *ldb = ldb_module_get_ctx(module);
987         struct parsed_dn *pdn;
988         /* We will take a reference to the schema in replmd_add_backlink */
989         const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
990         struct ldb_val *new_values = NULL;
991         int ret;
992
993         if (dsdb_check_single_valued_link(sa, el) == LDB_SUCCESS) {
994                 el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
995         } else {
996                 ldb_asprintf_errstring(ldb,
997                                        "Attribute %s is single valued but "
998                                        "more than one value has been supplied",
999                                        el->name);
1000                 talloc_free(tmp_ctx);
1001                 return LDB_ERR_CONSTRAINT_VIOLATION;
1002         }
1003         
1004         ret = get_parsed_dns(module, tmp_ctx, el, &pdn,
1005                              sa->syntax->ldap_oid, parent);
1006         if (ret != LDB_SUCCESS) {
1007                 talloc_free(tmp_ctx);
1008                 return ret;
1009         }
1010
1011         ret = check_parsed_dn_duplicates(module, el, pdn);
1012         if (ret != LDB_SUCCESS) {
1013                 talloc_free(tmp_ctx);
1014                 return ret;
1015         }
1016
1017         new_values = talloc_array(tmp_ctx, struct ldb_val, el->num_values);
1018         if (new_values == NULL) {
1019                 ldb_module_oom(module);
1020                 talloc_free(tmp_ctx);
1021                 return LDB_ERR_OPERATIONS_ERROR;
1022         }
1023
1024         for (i = 0; i < el->num_values; i++) {
1025                 struct parsed_dn *p = &pdn[i];
1026                 ret = replmd_build_la_val(el->values, p->v, p->dsdb_dn,
1027                                           &ac->our_invocation_id,
1028                                           ac->seq_num, now);
1029                 if (ret != LDB_SUCCESS) {
1030                         talloc_free(tmp_ctx);
1031                         return ret;
1032                 }
1033
1034                 ret = replmd_defer_add_backlink(module, replmd_private,
1035                                                 schema, ac,
1036                                                 forward_dn, &p->guid, true, sa,
1037                                                 parent);
1038                 if (ret != LDB_SUCCESS) {
1039                         talloc_free(tmp_ctx);
1040                         return ret;
1041                 }
1042
1043                 new_values[i] = *p->v;
1044         }
1045         el->values = talloc_steal(mem_ctx, new_values);
1046
1047         talloc_free(tmp_ctx);
1048         return LDB_SUCCESS;
1049 }
1050
1051 static int replmd_add_make_extended_dn(struct ldb_request *req,
1052                                        const DATA_BLOB *guid_blob,
1053                                        struct ldb_dn **_extended_dn)
1054 {
1055         int ret;
1056         const DATA_BLOB *sid_blob;
1057         /* Calculate an extended DN for any linked attributes */
1058         struct ldb_dn *extended_dn = ldb_dn_copy(req, req->op.add.message->dn);
1059         if (!extended_dn) {
1060                 return LDB_ERR_OPERATIONS_ERROR;
1061         }
1062         ret = ldb_dn_set_extended_component(extended_dn, "GUID", guid_blob);
1063         if (ret != LDB_SUCCESS) {
1064                 return ret;
1065         }
1066
1067         sid_blob = ldb_msg_find_ldb_val(req->op.add.message, "objectSID");
1068         if (sid_blob != NULL) {
1069                 ret = ldb_dn_set_extended_component(extended_dn, "SID", sid_blob);
1070                 if (ret != LDB_SUCCESS) {
1071                         return ret;
1072                 }
1073         }
1074         *_extended_dn = extended_dn;
1075         return LDB_SUCCESS;
1076 }
1077
1078 /*
1079   intercept add requests
1080  */
1081 static int replmd_add(struct ldb_module *module, struct ldb_request *req)
1082 {
1083         struct ldb_context *ldb;
1084         struct ldb_control *control;
1085         struct replmd_replicated_request *ac;
1086         enum ndr_err_code ndr_err;
1087         struct ldb_request *down_req;
1088         struct ldb_message *msg;
1089         const DATA_BLOB *guid_blob;
1090         DATA_BLOB guid_blob_stack;
1091         struct GUID guid;
1092         uint8_t guid_data[16];
1093         struct replPropertyMetaDataBlob nmd;
1094         struct ldb_val nmd_value;
1095         struct ldb_dn *extended_dn = NULL;
1096         
1097         /*
1098          * The use of a time_t here seems odd, but as the NTTIME
1099          * elements are actually declared as NTTIME_1sec in the IDL,
1100          * getting a higher resolution timestamp is not required.
1101          */
1102         time_t t = time(NULL);
1103         NTTIME now;
1104         char *time_str;
1105         int ret;
1106         unsigned int i;
1107         unsigned int functional_level;
1108         uint32_t ni=0;
1109         bool allow_add_guid = false;
1110         bool remove_current_guid = false;
1111         bool is_urgent = false;
1112         bool is_schema_nc = false;
1113         struct ldb_message_element *objectclass_el;
1114         struct replmd_private *replmd_private =
1115                 talloc_get_type_abort(ldb_module_get_private(module), struct replmd_private);
1116
1117         /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
1118         control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
1119         if (control) {
1120                 allow_add_guid = true;
1121         }
1122
1123         /* do not manipulate our control entries */
1124         if (ldb_dn_is_special(req->op.add.message->dn)) {
1125                 return ldb_next_request(module, req);
1126         }
1127
1128         ldb = ldb_module_get_ctx(module);
1129
1130         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_add\n");
1131
1132         guid_blob = ldb_msg_find_ldb_val(req->op.add.message, "objectGUID");
1133         if (guid_blob != NULL) {
1134                 if (!allow_add_guid) {
1135                         ldb_set_errstring(ldb,
1136                                           "replmd_add: it's not allowed to add an object with objectGUID!");
1137                         return LDB_ERR_UNWILLING_TO_PERFORM;
1138                 } else {
1139                         NTSTATUS status = GUID_from_data_blob(guid_blob,&guid);
1140                         if (!NT_STATUS_IS_OK(status)) {
1141                                 ldb_set_errstring(ldb,
1142                                                   "replmd_add: Unable to parse the 'objectGUID' as a GUID!");
1143                                 return LDB_ERR_UNWILLING_TO_PERFORM;
1144                         }
1145                         /* we remove this attribute as it can be a string and
1146                          * will not be treated correctly and then we will re-add
1147                          * it later on in the good format */
1148                         remove_current_guid = true;
1149                 }
1150         } else {
1151                 /* a new GUID */
1152                 guid = GUID_random();
1153                 
1154                 guid_blob_stack = data_blob_const(guid_data, sizeof(guid_data));
1155                 
1156                 /* This can't fail */
1157                 ndr_push_struct_into_fixed_blob(&guid_blob_stack, &guid,
1158                                                 (ndr_push_flags_fn_t)ndr_push_GUID);
1159                 guid_blob = &guid_blob_stack;
1160         }
1161
1162         ac = replmd_ctx_init(module, req);
1163         if (ac == NULL) {
1164                 return ldb_module_oom(module);
1165         }
1166
1167         functional_level = dsdb_functional_level(ldb);
1168
1169         /* Get a sequence number from the backend */
1170         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ac->seq_num);
1171         if (ret != LDB_SUCCESS) {
1172                 talloc_free(ac);
1173                 return ret;
1174         }
1175
1176         /* we have to copy the message as the caller might have it as a const */
1177         msg = ldb_msg_copy_shallow(ac, req->op.add.message);
1178         if (msg == NULL) {
1179                 ldb_oom(ldb);
1180                 talloc_free(ac);
1181                 return LDB_ERR_OPERATIONS_ERROR;
1182         }
1183
1184         /* generated times */
1185         unix_to_nt_time(&now, t);
1186         time_str = ldb_timestring(msg, t);
1187         if (!time_str) {
1188                 ldb_oom(ldb);
1189                 talloc_free(ac);
1190                 return LDB_ERR_OPERATIONS_ERROR;
1191         }
1192         if (remove_current_guid) {
1193                 ldb_msg_remove_attr(msg,"objectGUID");
1194         }
1195
1196         /*
1197          * remove autogenerated attributes
1198          */
1199         ldb_msg_remove_attr(msg, "whenCreated");
1200         ldb_msg_remove_attr(msg, "whenChanged");
1201         ldb_msg_remove_attr(msg, "uSNCreated");
1202         ldb_msg_remove_attr(msg, "uSNChanged");
1203         ldb_msg_remove_attr(msg, "replPropertyMetaData");
1204
1205         /*
1206          * readd replicated attributes
1207          */
1208         ret = ldb_msg_add_string(msg, "whenCreated", time_str);
1209         if (ret != LDB_SUCCESS) {
1210                 ldb_oom(ldb);
1211                 talloc_free(ac);
1212                 return ret;
1213         }
1214
1215         /* build the replication meta_data */
1216         ZERO_STRUCT(nmd);
1217         nmd.version             = 1;
1218         nmd.ctr.ctr1.count      = msg->num_elements;
1219         nmd.ctr.ctr1.array      = talloc_array(msg,
1220                                                struct replPropertyMetaData1,
1221                                                nmd.ctr.ctr1.count);
1222         if (!nmd.ctr.ctr1.array) {
1223                 ldb_oom(ldb);
1224                 talloc_free(ac);
1225                 return LDB_ERR_OPERATIONS_ERROR;
1226         }
1227
1228         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
1229
1230         for (i=0; i < msg->num_elements;) {
1231                 struct ldb_message_element *e = &msg->elements[i];
1232                 struct replPropertyMetaData1 *m = &nmd.ctr.ctr1.array[ni];
1233                 const struct dsdb_attribute *sa;
1234
1235                 if (e->name[0] == '@') {
1236                         i++;
1237                         continue;
1238                 }
1239
1240                 sa = dsdb_attribute_by_lDAPDisplayName(ac->schema, e->name);
1241                 if (!sa) {
1242                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
1243                                       "replmd_add: attribute '%s' not defined in schema\n",
1244                                       e->name);
1245                         talloc_free(ac);
1246                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
1247                 }
1248
1249                 if ((sa->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (sa->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
1250                         /* if the attribute is not replicated (0x00000001)
1251                          * or constructed (0x00000004) it has no metadata
1252                          */
1253                         i++;
1254                         continue;
1255                 }
1256
1257                 if (sa->linkID != 0 && functional_level > DS_DOMAIN_FUNCTION_2000) {
1258                         if (extended_dn == NULL) {
1259                                 ret = replmd_add_make_extended_dn(req,
1260                                                                   guid_blob,
1261                                                                   &extended_dn);
1262                                 if (ret != LDB_SUCCESS) {
1263                                         talloc_free(ac);
1264                                         return ret;
1265                                 }
1266                         }                       
1267
1268                         /*
1269                          * Prepare the context for the backlinks and
1270                          * create metadata for the forward links.  The
1271                          * backlinks are created in
1272                          * replmd_op_callback() after the successful
1273                          * ADD of the object.
1274                          */
1275                         ret = replmd_add_fix_la(module, msg->elements,
1276                                                 replmd_private, e,
1277                                                 ac, now,
1278                                                 extended_dn,
1279                                                 sa, req);
1280                         if (ret != LDB_SUCCESS) {
1281                                 talloc_free(ac);
1282                                 return ret;
1283                         }
1284                         /* linked attributes are not stored in
1285                            replPropertyMetaData in FL above w2k */
1286                         i++;
1287                         continue;
1288                 }
1289
1290                 m->attid   = dsdb_attribute_get_attid(sa, is_schema_nc);
1291                 m->version = 1;
1292                 if (m->attid == DRSUAPI_ATTID_isDeleted) {
1293                         const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
1294                         const char* rdn;
1295
1296                         if (rdn_val == NULL) {
1297                                 ldb_oom(ldb);
1298                                 talloc_free(ac);
1299                                 return LDB_ERR_OPERATIONS_ERROR;
1300                         }
1301
1302                         rdn = (const char*)rdn_val->data;
1303                         if (strcmp(rdn, "Deleted Objects") == 0) {
1304                                 /*
1305                                  * Set the originating_change_time to 29/12/9999 at 23:59:59
1306                                  * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container
1307                                  */
1308                                 m->originating_change_time      = DELETED_OBJECT_CONTAINER_CHANGE_TIME;
1309                         } else {
1310                                 m->originating_change_time      = now;
1311                         }
1312                 } else {
1313                         m->originating_change_time      = now;
1314                 }
1315                 m->originating_invocation_id    = ac->our_invocation_id;
1316                 m->originating_usn              = ac->seq_num;
1317                 m->local_usn                    = ac->seq_num;
1318                 ni++;
1319
1320                 if (!(e->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA)) {
1321                         i++;
1322                         continue;
1323                 }
1324
1325                 e->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
1326
1327                 if (e->num_values != 0) {
1328                         i++;
1329                         continue;
1330                 }
1331
1332                 ldb_msg_remove_element(msg, e);
1333         }
1334
1335         /* fix meta data count */
1336         nmd.ctr.ctr1.count = ni;
1337
1338         /*
1339          * sort meta data array
1340          */
1341         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, msg->dn);
1342         if (ret != LDB_SUCCESS) {
1343                 ldb_asprintf_errstring(ldb, "%s: error during direct ADD: %s", __func__, ldb_errstring(ldb));
1344                 talloc_free(ac);
1345                 return ret;
1346         }
1347
1348         /* generated NDR encoded values */
1349         ndr_err = ndr_push_struct_blob(&nmd_value, msg,
1350                                        &nmd,
1351                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
1352         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1353                 ldb_oom(ldb);
1354                 talloc_free(ac);
1355                 return LDB_ERR_OPERATIONS_ERROR;
1356         }
1357
1358         /*
1359          * add the autogenerated values
1360          */
1361         ret = dsdb_msg_add_guid(msg, &guid, "objectGUID");
1362         if (ret != LDB_SUCCESS) {
1363                 ldb_oom(ldb);
1364                 talloc_free(ac);
1365                 return ret;
1366         }
1367         ret = ldb_msg_add_string(msg, "whenChanged", time_str);
1368         if (ret != LDB_SUCCESS) {
1369                 ldb_oom(ldb);
1370                 talloc_free(ac);
1371                 return ret;
1372         }
1373         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ac->seq_num);
1374         if (ret != LDB_SUCCESS) {
1375                 ldb_oom(ldb);
1376                 talloc_free(ac);
1377                 return ret;
1378         }
1379         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ac->seq_num);
1380         if (ret != LDB_SUCCESS) {
1381                 ldb_oom(ldb);
1382                 talloc_free(ac);
1383                 return ret;
1384         }
1385         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
1386         if (ret != LDB_SUCCESS) {
1387                 ldb_oom(ldb);
1388                 talloc_free(ac);
1389                 return ret;
1390         }
1391
1392         /*
1393          * sort the attributes by attid before storing the object
1394          */
1395         replmd_ldb_message_sort(msg, ac->schema);
1396
1397         /*
1398          * Assert that we do have an objectClass
1399          */
1400         objectclass_el = ldb_msg_find_element(msg, "objectClass");
1401         if (objectclass_el == NULL) {
1402                 ldb_asprintf_errstring(ldb, __location__
1403                                        ": objectClass missing on %s\n",
1404                                        ldb_dn_get_linearized(msg->dn));
1405                 talloc_free(ac);
1406                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1407         }
1408         is_urgent = replmd_check_urgent_objectclass(objectclass_el,
1409                                                         REPL_URGENT_ON_CREATE);
1410
1411         ac->is_urgent = is_urgent;
1412         ret = ldb_build_add_req(&down_req, ldb, ac,
1413                                 msg,
1414                                 req->controls,
1415                                 ac, replmd_op_callback,
1416                                 req);
1417
1418         LDB_REQ_SET_LOCATION(down_req);
1419         if (ret != LDB_SUCCESS) {
1420                 talloc_free(ac);
1421                 return ret;
1422         }
1423
1424         /* current partition control is needed by "replmd_op_callback" */
1425         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
1426                 ret = ldb_request_add_control(down_req,
1427                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
1428                                               false, NULL);
1429                 if (ret != LDB_SUCCESS) {
1430                         talloc_free(ac);
1431                         return ret;
1432                 }
1433         }
1434
1435         if (functional_level == DS_DOMAIN_FUNCTION_2000) {
1436                 ret = ldb_request_add_control(down_req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
1437                 if (ret != LDB_SUCCESS) {
1438                         talloc_free(ac);
1439                         return ret;
1440                 }
1441         }
1442
1443         /* mark the control done */
1444         if (control) {
1445                 control->critical = 0;
1446         }
1447         /* go on with the call chain */
1448         return ldb_next_request(module, down_req);
1449 }
1450
1451
1452 /*
1453  * update the replPropertyMetaData for one element
1454  */
1455 static int replmd_update_rpmd_element(struct ldb_context *ldb,
1456                                       struct ldb_message *msg,
1457                                       struct ldb_message_element *el,
1458                                       struct ldb_message_element *old_el,
1459                                       struct replPropertyMetaDataBlob *omd,
1460                                       const struct dsdb_schema *schema,
1461                                       uint64_t *seq_num,
1462                                       const struct GUID *our_invocation_id,
1463                                       NTTIME now,
1464                                       bool is_schema_nc,
1465                                       bool is_forced_rodc,
1466                                       struct ldb_request *req)
1467 {
1468         uint32_t i;
1469         const struct dsdb_attribute *a;
1470         struct replPropertyMetaData1 *md1;
1471         bool may_skip = false;
1472         uint32_t attid;
1473
1474         a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
1475         if (a == NULL) {
1476                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
1477                         /* allow this to make it possible for dbcheck
1478                            to remove bad attributes */
1479                         return LDB_SUCCESS;
1480                 }
1481
1482                 DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n",
1483                          el->name));
1484                 return LDB_ERR_OPERATIONS_ERROR;
1485         }
1486
1487         attid = dsdb_attribute_get_attid(a, is_schema_nc);
1488
1489         if ((a->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (a->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
1490                 return LDB_SUCCESS;
1491         }
1492
1493         /*
1494          * if the attribute's value haven't changed, and this isn't
1495          * just a delete of everything then return LDB_SUCCESS Unless
1496          * we have the provision control or if the attribute is
1497          * interSiteTopologyGenerator as this page explain:
1498          * http://support.microsoft.com/kb/224815 this attribute is
1499          * periodicaly written by the DC responsible for the intersite
1500          * generation in a given site
1501          *
1502          * Unchanged could be deleting or replacing an already-gone
1503          * thing with an unconstrained delete/empty replace or a
1504          * replace with the same value, but not an add with the same
1505          * value because that could be about adding a duplicate (which
1506          * is for someone else to error out on).
1507          */
1508         if (old_el != NULL && ldb_msg_element_equal_ordered(el, old_el)) {
1509                 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) {
1510                         may_skip = true;
1511                 }
1512         } else if (old_el == NULL && el->num_values == 0) {
1513                 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) {
1514                         may_skip = true;
1515                 } else if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
1516                         may_skip = true;
1517                 }
1518         } else if (a->linkID != 0 && LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE &&
1519                    ldb_request_get_control(req, DSDB_CONTROL_REPLMD_VANISH_LINKS) != NULL) {
1520                 /*
1521                  * We intentionally skip the version bump when attempting to
1522                  * vanish links.
1523                  *
1524                  * The control is set by dbcheck and expunge-tombstones which
1525                  * both attempt to be non-replicating. Otherwise, making an
1526                  * alteration to the replication state would trigger a
1527                  * broadcast of all expunged objects.
1528                  */
1529                 may_skip = true;
1530         }
1531
1532         if (el->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA) {
1533                 may_skip = false;
1534                 el->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
1535         }
1536
1537         if (may_skip) {
1538                 if (strcmp(el->name, "interSiteTopologyGenerator") != 0 &&
1539                     !ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID)) {
1540                         /*
1541                          * allow this to make it possible for dbcheck
1542                          * to rebuild broken metadata
1543                          */
1544                         return LDB_SUCCESS;
1545                 }
1546         }
1547
1548         for (i=0; i<omd->ctr.ctr1.count; i++) {
1549                 /*
1550                  * First check if we find it under the msDS-IntID,
1551                  * then check if we find it under the OID and
1552                  * prefixMap ID.
1553                  *
1554                  * This allows the administrator to simply re-write
1555                  * the attributes and so restore replication, which is
1556                  * likely what they will try to do.
1557                  */
1558                 if (attid == omd->ctr.ctr1.array[i].attid) {
1559                         break;
1560                 }
1561
1562                 if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) {
1563                         break;
1564                 }
1565         }
1566
1567         if (a->linkID != 0 && dsdb_functional_level(ldb) > DS_DOMAIN_FUNCTION_2000) {
1568                 /* linked attributes are not stored in
1569                    replPropertyMetaData in FL above w2k, but we do
1570                    raise the seqnum for the object  */
1571                 if (*seq_num == 0 &&
1572                     ldb_sequence_number(ldb, LDB_SEQ_NEXT, seq_num) != LDB_SUCCESS) {
1573                         return LDB_ERR_OPERATIONS_ERROR;
1574                 }
1575                 return LDB_SUCCESS;
1576         }
1577
1578         if (i == omd->ctr.ctr1.count) {
1579                 /* we need to add a new one */
1580                 omd->ctr.ctr1.array = talloc_realloc(msg, omd->ctr.ctr1.array,
1581                                                      struct replPropertyMetaData1, omd->ctr.ctr1.count+1);
1582                 if (omd->ctr.ctr1.array == NULL) {
1583                         ldb_oom(ldb);
1584                         return LDB_ERR_OPERATIONS_ERROR;
1585                 }
1586                 omd->ctr.ctr1.count++;
1587                 ZERO_STRUCT(omd->ctr.ctr1.array[i]);
1588         }
1589
1590         /* Get a new sequence number from the backend. We only do this
1591          * if we have a change that requires a new
1592          * replPropertyMetaData element
1593          */
1594         if (*seq_num == 0) {
1595                 int ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, seq_num);
1596                 if (ret != LDB_SUCCESS) {
1597                         return LDB_ERR_OPERATIONS_ERROR;
1598                 }
1599         }
1600
1601         md1 = &omd->ctr.ctr1.array[i];
1602         md1->version++;
1603         md1->attid = attid;
1604
1605         if (md1->attid == DRSUAPI_ATTID_isDeleted) {
1606                 const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
1607                 const char* rdn;
1608
1609                 if (rdn_val == NULL) {
1610                         ldb_oom(ldb);
1611                         return LDB_ERR_OPERATIONS_ERROR;
1612                 }
1613
1614                 rdn = (const char*)rdn_val->data;
1615                 if (strcmp(rdn, "Deleted Objects") == 0) {
1616                         /*
1617                          * Set the originating_change_time to 29/12/9999 at 23:59:59
1618                          * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container
1619                          */
1620                         md1->originating_change_time    = DELETED_OBJECT_CONTAINER_CHANGE_TIME;
1621                 } else {
1622                         md1->originating_change_time    = now;
1623                 }
1624         } else {
1625                 md1->originating_change_time    = now;
1626         }
1627         md1->originating_invocation_id = *our_invocation_id;
1628         md1->originating_usn           = *seq_num;
1629         md1->local_usn                 = *seq_num;
1630
1631         if (is_forced_rodc) {
1632                 /* Force version to 0 to be overriden later via replication */
1633                 md1->version = 0;
1634         }
1635
1636         return LDB_SUCCESS;
1637 }
1638
1639 /*
1640  * Bump the replPropertyMetaData version on an attribute, and if it
1641  * has changed (or forced by leaving rdn_old NULL), update the value
1642  * in the entry.
1643  *
1644  * This is important, as calling a modify operation may not change the
1645  * version number if the values appear unchanged, but a rename between
1646  * parents bumps this value.
1647  *
1648  */
1649 static int replmd_update_rpmd_rdn_attr(struct ldb_context *ldb,
1650                                        struct ldb_message *msg,
1651                                        const struct ldb_val *rdn_new,
1652                                        const struct ldb_val *rdn_old,
1653                                        struct replPropertyMetaDataBlob *omd,
1654                                        struct replmd_replicated_request *ar,
1655                                        NTTIME now,
1656                                        bool is_schema_nc,
1657                                        bool is_forced_rodc)
1658 {
1659         const char *rdn_name = ldb_dn_get_rdn_name(msg->dn);
1660         const struct dsdb_attribute *rdn_attr =
1661                 dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name);
1662         const char *attr_name = rdn_attr != NULL ?
1663                                 rdn_attr->lDAPDisplayName :
1664                                 rdn_name;
1665         struct ldb_message_element new_el = {
1666                 .flags = LDB_FLAG_MOD_REPLACE,
1667                 .name = attr_name,
1668                 .num_values = 1,
1669                 .values = discard_const_p(struct ldb_val, rdn_new)
1670         };
1671         struct ldb_message_element old_el = {
1672                 .flags = LDB_FLAG_MOD_REPLACE,
1673                 .name = attr_name,
1674                 .num_values = rdn_old ? 1 : 0,
1675                 .values = discard_const_p(struct ldb_val, rdn_old)
1676         };
1677
1678         if (ldb_msg_element_equal_ordered(&new_el, &old_el) == false) {
1679                 int ret = ldb_msg_add(msg, &new_el, LDB_FLAG_MOD_REPLACE);
1680                 if (ret != LDB_SUCCESS) {
1681                         return ldb_oom(ldb);
1682                 }
1683         }
1684
1685         return replmd_update_rpmd_element(ldb, msg, &new_el, NULL,
1686                                           omd, ar->schema, &ar->seq_num,
1687                                           &ar->our_invocation_id,
1688                                           now, is_schema_nc, is_forced_rodc,
1689                                           ar->req);
1690
1691 }
1692
1693 static uint64_t find_max_local_usn(struct replPropertyMetaDataBlob omd)
1694 {
1695         uint32_t count = omd.ctr.ctr1.count;
1696         uint64_t max = 0;
1697         uint32_t i;
1698         for (i=0; i < count; i++) {
1699                 struct replPropertyMetaData1 m = omd.ctr.ctr1.array[i];
1700                 if (max < m.local_usn) {
1701                         max = m.local_usn;
1702                 }
1703         }
1704         return max;
1705 }
1706
1707 /*
1708  * update the replPropertyMetaData object each time we modify an
1709  * object. This is needed for DRS replication, as the merge on the
1710  * client is based on this object
1711  */
1712 static int replmd_update_rpmd(struct ldb_module *module,
1713                               const struct dsdb_schema *schema,
1714                               struct ldb_request *req,
1715                               const char * const *rename_attrs,
1716                               struct ldb_message *msg, uint64_t *seq_num,
1717                               time_t t, bool is_schema_nc,
1718                               bool *is_urgent, bool *rodc)
1719 {
1720         const struct ldb_val *omd_value;
1721         enum ndr_err_code ndr_err;
1722         struct replPropertyMetaDataBlob omd;
1723         unsigned int i;
1724         NTTIME now;
1725         const struct GUID *our_invocation_id;
1726         int ret;
1727         const char * const *attrs = NULL;
1728         const char * const attrs2[] = { "uSNChanged", "objectClass", "instanceType", NULL };
1729         struct ldb_result *res;
1730         struct ldb_context *ldb;
1731         struct ldb_message_element *objectclass_el;
1732         enum urgent_situation situation;
1733         bool rmd_is_provided;
1734         bool rmd_is_just_resorted = false;
1735         const char *not_rename_attrs[4 + msg->num_elements];
1736         bool is_forced_rodc = false;
1737
1738         if (rename_attrs) {
1739                 attrs = rename_attrs;
1740         } else {
1741                 for (i = 0; i < msg->num_elements; i++) {
1742                         not_rename_attrs[i] = msg->elements[i].name;
1743                 }
1744                 not_rename_attrs[i] = "replPropertyMetaData";
1745                 not_rename_attrs[i+1] = "objectClass";
1746                 not_rename_attrs[i+2] = "instanceType";
1747                 not_rename_attrs[i+3] = NULL;
1748                 attrs = not_rename_attrs;
1749         }
1750
1751         ldb = ldb_module_get_ctx(module);
1752
1753         ret = samdb_rodc(ldb, rodc);
1754         if (ret != LDB_SUCCESS) {
1755                 DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
1756                 *rodc = false;
1757         }
1758
1759         if (*rodc &&
1760             ldb_request_get_control(req, DSDB_CONTROL_FORCE_RODC_LOCAL_CHANGE)) {
1761                 is_forced_rodc = true;
1762         }
1763
1764         our_invocation_id = samdb_ntds_invocation_id(ldb);
1765         if (!our_invocation_id) {
1766                 /* this happens during an initial vampire while
1767                    updating the schema */
1768                 DEBUG(5,("No invocationID - skipping replPropertyMetaData update\n"));
1769                 return LDB_SUCCESS;
1770         }
1771
1772         unix_to_nt_time(&now, t);
1773
1774         if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_OID)) {
1775                 rmd_is_provided = true;
1776                 if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_RESORT_OID)) {
1777                         rmd_is_just_resorted = true;
1778                 }
1779         } else {
1780                 rmd_is_provided = false;
1781         }
1782
1783         /* if isDeleted is present and is TRUE, then we consider we are deleting,
1784          * otherwise we consider we are updating */
1785         if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
1786                 situation = REPL_URGENT_ON_DELETE;
1787         } else if (rename_attrs) {
1788                 situation = REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE;
1789         } else {
1790                 situation = REPL_URGENT_ON_UPDATE;
1791         }
1792
1793         if (rmd_is_provided) {
1794                 /* In this case the change_replmetadata control was supplied */
1795                 /* We check that it's the only attribute that is provided
1796                  * (it's a rare case so it's better to keep the code simplier)
1797                  * We also check that the highest local_usn is bigger or the same as
1798                  * uSNChanged. */
1799                 uint64_t db_seq;
1800                 if( msg->num_elements != 1 ||
1801                         strncmp(msg->elements[0].name,
1802                                 "replPropertyMetaData", 20) ) {
1803                         DEBUG(0,(__location__ ": changereplmetada control called without "\
1804                                 "a specified replPropertyMetaData attribute or with others\n"));
1805                         return LDB_ERR_OPERATIONS_ERROR;
1806                 }
1807                 if (situation != REPL_URGENT_ON_UPDATE) {
1808                         DEBUG(0,(__location__ ": changereplmetada control can't be called when deleting an object\n"));
1809                         return LDB_ERR_OPERATIONS_ERROR;
1810                 }
1811                 omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
1812                 if (!omd_value) {
1813                         DEBUG(0,(__location__ ": replPropertyMetaData was not specified for Object %s\n",
1814                                  ldb_dn_get_linearized(msg->dn)));
1815                         return LDB_ERR_OPERATIONS_ERROR;
1816                 }
1817                 ndr_err = ndr_pull_struct_blob(omd_value, msg, &omd,
1818                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
1819                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1820                         DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
1821                                  ldb_dn_get_linearized(msg->dn)));
1822                         return LDB_ERR_OPERATIONS_ERROR;
1823                 }
1824
1825                 ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs2,
1826                                             DSDB_FLAG_NEXT_MODULE |
1827                                             DSDB_SEARCH_SHOW_RECYCLED |
1828                                             DSDB_SEARCH_SHOW_EXTENDED_DN |
1829                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
1830                                             DSDB_SEARCH_REVEAL_INTERNALS, req);
1831
1832                 if (ret != LDB_SUCCESS) {
1833                         return ret;
1834                 }
1835
1836                 if (rmd_is_just_resorted == false) {
1837                         *seq_num = find_max_local_usn(omd);
1838
1839                         db_seq = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNChanged", 0);
1840
1841                         /*
1842                          * The test here now allows for a new
1843                          * replPropertyMetaData with no change, if was
1844                          * just dbcheck re-sorting the values.
1845                          */
1846                         if (*seq_num <= db_seq) {
1847                                 DEBUG(0,(__location__ ": changereplmetada control provided but max(local_usn)" \
1848                                          " is less than uSNChanged (max = %lld uSNChanged = %lld)\n",
1849                                          (long long)*seq_num, (long long)db_seq));
1850                                 return LDB_ERR_OPERATIONS_ERROR;
1851                         }
1852                 }
1853
1854         } else {
1855                 /* search for the existing replPropertyMetaDataBlob. We need
1856                  * to use REVEAL and ask for DNs in storage format to support
1857                  * the check for values being the same in
1858                  * replmd_update_rpmd_element()
1859                  */
1860                 ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs,
1861                                             DSDB_FLAG_NEXT_MODULE |
1862                                             DSDB_SEARCH_SHOW_RECYCLED |
1863                                             DSDB_SEARCH_SHOW_EXTENDED_DN |
1864                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
1865                                             DSDB_SEARCH_REVEAL_INTERNALS, req);
1866                 if (ret != LDB_SUCCESS) {
1867                         return ret;
1868                 }
1869
1870                 omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
1871                 if (!omd_value) {
1872                         DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
1873                                  ldb_dn_get_linearized(msg->dn)));
1874                         return LDB_ERR_OPERATIONS_ERROR;
1875                 }
1876
1877                 ndr_err = ndr_pull_struct_blob(omd_value, msg, &omd,
1878                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
1879                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1880                         DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
1881                                  ldb_dn_get_linearized(msg->dn)));
1882                         return LDB_ERR_OPERATIONS_ERROR;
1883                 }
1884
1885                 if (omd.version != 1) {
1886                         DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s\n",
1887                                  omd.version, ldb_dn_get_linearized(msg->dn)));
1888                         return LDB_ERR_OPERATIONS_ERROR;
1889                 }
1890
1891                 for (i=0; i<msg->num_elements;) {
1892                         struct ldb_message_element *el = &msg->elements[i];
1893                         struct ldb_message_element *old_el;
1894
1895                         old_el = ldb_msg_find_element(res->msgs[0], el->name);
1896                         ret = replmd_update_rpmd_element(ldb, msg, el, old_el,
1897                                                          &omd, schema, seq_num,
1898                                                          our_invocation_id,
1899                                                          now, is_schema_nc,
1900                                                          is_forced_rodc,
1901                                                          req);
1902                         if (ret != LDB_SUCCESS) {
1903                                 return ret;
1904                         }
1905
1906                         if (!*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) {
1907                                 *is_urgent = replmd_check_urgent_attribute(el);
1908                         }
1909
1910                         if (!(el->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA)) {
1911                                 i++;
1912                                 continue;
1913                         }
1914
1915                         el->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
1916
1917                         if (el->num_values != 0) {
1918                                 i++;
1919                                 continue;
1920                         }
1921
1922                         ldb_msg_remove_element(msg, el);
1923                 }
1924         }
1925
1926         /*
1927          * Assert that we have an objectClass attribute - this is major
1928          * corruption if we don't have this!
1929          */
1930         objectclass_el = ldb_msg_find_element(res->msgs[0], "objectClass");
1931         if (objectclass_el != NULL) {
1932                 /*
1933                  * Now check if this objectClass means we need to do urgent replication
1934                  */
1935                 if (!*is_urgent && replmd_check_urgent_objectclass(objectclass_el,
1936                                                                    situation)) {
1937                         *is_urgent = true;
1938                 }
1939         } else if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
1940                 ldb_asprintf_errstring(ldb, __location__
1941                                        ": objectClass missing on %s\n",
1942                                        ldb_dn_get_linearized(msg->dn));
1943                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1944         }
1945
1946         /*
1947          * replmd_update_rpmd_element has done an update if the
1948          * seq_num is set
1949          */
1950         if (*seq_num != 0 || rmd_is_just_resorted == true) {
1951                 struct ldb_val *md_value;
1952                 struct ldb_message_element *el;
1953
1954                 /*if we are RODC and this is a DRSR update then its ok*/
1955                 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)
1956                     && !ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)
1957                     && !is_forced_rodc) {
1958                         unsigned instanceType;
1959
1960                         if (*rodc) {
1961                                 ldb_set_errstring(ldb, "RODC modify is forbidden!");
1962                                 return LDB_ERR_REFERRAL;
1963                         }
1964
1965                         instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], "instanceType", INSTANCE_TYPE_WRITE);
1966                         if (!(instanceType & INSTANCE_TYPE_WRITE)) {
1967                                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM,
1968                                                  "cannot change replicated attribute on partial replica");
1969                         }
1970                 }
1971
1972                 md_value = talloc(msg, struct ldb_val);
1973                 if (md_value == NULL) {
1974                         ldb_oom(ldb);
1975                         return LDB_ERR_OPERATIONS_ERROR;
1976                 }
1977
1978                 ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &omd.ctr.ctr1, msg->dn);
1979                 if (ret != LDB_SUCCESS) {
1980                         ldb_asprintf_errstring(ldb, "%s: %s", __func__, ldb_errstring(ldb));
1981                         return ret;
1982                 }
1983
1984                 ndr_err = ndr_push_struct_blob(md_value, msg, &omd,
1985                                                (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
1986                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1987                         DEBUG(0,(__location__ ": Failed to marshall replPropertyMetaData for %s\n",
1988                                  ldb_dn_get_linearized(msg->dn)));
1989                         return LDB_ERR_OPERATIONS_ERROR;
1990                 }
1991
1992                 ret = ldb_msg_add_empty(msg, "replPropertyMetaData", LDB_FLAG_MOD_REPLACE, &el);
1993                 if (ret != LDB_SUCCESS) {
1994                         DEBUG(0,(__location__ ": Failed to add updated replPropertyMetaData %s\n",
1995                                  ldb_dn_get_linearized(msg->dn)));
1996                         return ret;
1997                 }
1998
1999                 el->num_values = 1;
2000                 el->values = md_value;
2001         }
2002
2003         return LDB_SUCCESS;
2004 }
2005
2006 static int parsed_dn_compare(struct parsed_dn *pdn1, struct parsed_dn *pdn2)
2007 {
2008         int ret = ndr_guid_compare(&pdn1->guid, &pdn2->guid);
2009         if (ret == 0) {
2010                 return data_blob_cmp(&pdn1->dsdb_dn->extra_part,
2011                                      &pdn2->dsdb_dn->extra_part);
2012         }
2013         return ret;
2014 }
2015
2016 /*
2017   get a series of message element values as an array of DNs and GUIDs
2018   the result is sorted by GUID
2019  */
2020 static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
2021                           struct ldb_message_element *el, struct parsed_dn **pdn,
2022                           const char *ldap_oid, struct ldb_request *parent)
2023 {
2024         unsigned int i;
2025         bool values_are_sorted = true;
2026         struct ldb_context *ldb = ldb_module_get_ctx(module);
2027
2028         if (el == NULL) {
2029                 *pdn = NULL;
2030                 return LDB_SUCCESS;
2031         }
2032
2033         (*pdn) = talloc_array(mem_ctx, struct parsed_dn, el->num_values);
2034         if (!*pdn) {
2035                 ldb_module_oom(module);
2036                 return LDB_ERR_OPERATIONS_ERROR;
2037         }
2038
2039         for (i=0; i<el->num_values; i++) {
2040                 struct ldb_val *v = &el->values[i];
2041                 NTSTATUS status;
2042                 struct ldb_dn *dn;
2043                 struct parsed_dn *p;
2044
2045                 p = &(*pdn)[i];
2046
2047                 p->dsdb_dn = dsdb_dn_parse(*pdn, ldb, v, ldap_oid);
2048                 if (p->dsdb_dn == NULL) {
2049                         return LDB_ERR_INVALID_DN_SYNTAX;
2050                 }
2051
2052                 dn = p->dsdb_dn->dn;
2053
2054                 status = dsdb_get_extended_dn_guid(dn, &p->guid, "GUID");
2055                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
2056                     unlikely(GUID_all_zero(&p->guid))) {
2057                         /* we got a DN without a GUID - go find the GUID */
2058                         int ret = dsdb_module_guid_by_dn(module, dn, &p->guid, parent);
2059                         if (ret != LDB_SUCCESS) {
2060                                 char *dn_str = NULL;
2061                                 dn_str = ldb_dn_get_extended_linearized(mem_ctx,
2062                                                                         (dn), 1);
2063                                 ldb_asprintf_errstring(ldb,
2064                                                 "Unable to find GUID for DN %s\n",
2065                                                 dn_str);
2066                                 if (ret == LDB_ERR_NO_SUCH_OBJECT &&
2067                                     LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE &&
2068                                     ldb_attr_cmp(el->name, "member") == 0) {
2069                                         return LDB_ERR_UNWILLING_TO_PERFORM;
2070                                 }
2071                                 return ret;
2072                         }
2073                         ret = dsdb_set_extended_dn_guid(dn, &p->guid, "GUID");
2074                         if (ret != LDB_SUCCESS) {
2075                                 return ret;
2076                         }
2077                 } else if (!NT_STATUS_IS_OK(status)) {
2078                         return LDB_ERR_OPERATIONS_ERROR;
2079                 }
2080                 if (i > 0 && values_are_sorted) {
2081                         int cmp = parsed_dn_compare(p, &(*pdn)[i - 1]);
2082                         if (cmp < 0) {
2083                                 values_are_sorted = false;
2084                         }
2085                 }
2086                 /* keep a pointer to the original ldb_val */
2087                 p->v = v;
2088         }
2089         if (! values_are_sorted) {
2090                 TYPESAFE_QSORT(*pdn, el->num_values, parsed_dn_compare);
2091         }
2092         return LDB_SUCCESS;
2093 }
2094
2095 /*
2096  * Get a series of trusted message element values. The result is sorted by
2097  * GUID, even though the GUIDs might not be known. That works because we trust
2098  * the database to give us the elements like that if the
2099  * replmd_private->sorted_links flag is set.
2100  *
2101  * We also ensure that the links are in the Functional Level 2003
2102  * linked attributes format.
2103  */
2104 static int get_parsed_dns_trusted(struct ldb_module *module,
2105                                   struct replmd_private *replmd_private,
2106                                   TALLOC_CTX *mem_ctx,
2107                                   struct ldb_message_element *el,
2108                                   struct parsed_dn **pdn,
2109                                   const char *ldap_oid,
2110                                   struct ldb_request *parent)
2111 {
2112         unsigned int i;
2113         int ret;
2114         if (el == NULL) {
2115                 *pdn = NULL;
2116                 return LDB_SUCCESS;
2117         }
2118
2119         if (!replmd_private->sorted_links) {
2120                 /* We need to sort the list. This is the slow old path we want
2121                    to avoid.
2122                  */
2123                 ret = get_parsed_dns(module, mem_ctx, el, pdn, ldap_oid,
2124                                       parent);
2125                 if (ret != LDB_SUCCESS) {
2126                         return ret;
2127                 }
2128         } else {
2129                 /* Here we get a list of 'struct parsed_dns' without the parsing */
2130                 *pdn = talloc_zero_array(mem_ctx, struct parsed_dn,
2131                                          el->num_values);
2132                 if (!*pdn) {
2133                         ldb_module_oom(module);
2134                         return LDB_ERR_OPERATIONS_ERROR;
2135                 }
2136
2137                 for (i = 0; i < el->num_values; i++) {
2138                         (*pdn)[i].v = &el->values[i];
2139                 }
2140         }
2141
2142         /*
2143          * This upgrades links to FL2003 style, and sorts the result
2144          * if that was needed.
2145          *
2146          * TODO: Add a database feature that asserts we have no FL2000
2147          *       style links to avoid this check or add a feature that
2148          *       uses a similar check to find sorted/unsorted links
2149          *       for an on-the-fly upgrade.
2150          */
2151
2152         ret = replmd_check_upgrade_links(ldb_module_get_ctx(module),
2153                                          *pdn, el->num_values,
2154                                          el,
2155                                          ldap_oid);
2156         if (ret != LDB_SUCCESS) {
2157                 return ret;
2158         }
2159
2160         return LDB_SUCCESS;
2161 }
2162
2163 /*
2164    Return LDB_SUCCESS if a parsed_dn list contains no duplicate values,
2165    otherwise an error code. For compatibility the error code differs depending
2166    on whether or not the attribute is "member".
2167
2168    As always, the parsed_dn list is assumed to be sorted.
2169  */
2170 static int check_parsed_dn_duplicates(struct ldb_module *module,
2171                                       struct ldb_message_element *el,
2172                                       struct parsed_dn *pdn)
2173 {
2174         unsigned int i;
2175         struct ldb_context *ldb = ldb_module_get_ctx(module);
2176
2177         for (i = 1; i < el->num_values; i++) {
2178                 struct parsed_dn *p = &pdn[i];
2179                 if (parsed_dn_compare(p, &pdn[i - 1]) == 0) {
2180                         ldb_asprintf_errstring(ldb,
2181                                                "Linked attribute %s has "
2182                                                "multiple identical values",
2183                                                el->name);
2184                         if (ldb_attr_cmp(el->name, "member") == 0) {
2185                                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
2186                         } else {
2187                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2188                         }
2189                 }
2190         }
2191         return LDB_SUCCESS;
2192 }
2193
2194 /*
2195   build a new extended DN, including all meta data fields
2196
2197   RMD_FLAGS           = DSDB_RMD_FLAG_* bits
2198   RMD_ADDTIME         = originating_add_time
2199   RMD_INVOCID         = originating_invocation_id
2200   RMD_CHANGETIME      = originating_change_time
2201   RMD_ORIGINATING_USN = originating_usn
2202   RMD_LOCAL_USN       = local_usn
2203   RMD_VERSION         = version
2204  */
2205 static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v,
2206                                struct dsdb_dn *dsdb_dn,
2207                                const struct GUID *invocation_id,
2208                                uint64_t local_usn, NTTIME nttime)
2209 {
2210         return replmd_set_la_val(mem_ctx, v, dsdb_dn, NULL, invocation_id,
2211                                  local_usn, local_usn, nttime,
2212                                  RMD_VERSION_INITIAL, false);
2213 }
2214
2215 static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
2216                                 struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
2217                                 uint64_t seq_num, uint64_t local_usn, NTTIME nttime,
2218                                 bool deleted);
2219
2220 /*
2221   check if any links need upgrading from w2k format
2222  */
2223 static int replmd_check_upgrade_links(struct ldb_context *ldb,
2224                                       struct parsed_dn *dns, uint32_t count,
2225                                       struct ldb_message_element *el,
2226                                       const char *ldap_oid)
2227 {
2228         uint32_t i;
2229         const struct GUID *invocation_id = NULL;
2230         for (i=0; i<count; i++) {
2231                 NTSTATUS status;
2232                 uint32_t version;
2233                 int ret;
2234                 if (dns[i].dsdb_dn == NULL) {
2235                         ret = really_parse_trusted_dn(dns, ldb, &dns[i],
2236                                                       ldap_oid);
2237                         if (ret != LDB_SUCCESS) {
2238                                 return LDB_ERR_INVALID_DN_SYNTAX;
2239                         }
2240                 }
2241
2242                 status = dsdb_get_extended_dn_uint32(dns[i].dsdb_dn->dn,
2243                                                      &version, "RMD_VERSION");
2244                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2245                         /*
2246                          *  We optimistically assume they are all the same; if
2247                          *  the first one is fixed, they are all fixed.
2248                          *
2249                          *  If the first one was *not* fixed and we find a
2250                          *  later one that is, that is an occasion to shout
2251                          *  with DEBUG(0).
2252                          */
2253                         if (i == 0) {
2254                                 return LDB_SUCCESS;
2255                         }
2256                         DEBUG(0, ("Mixed w2k and fixed format "
2257                                   "linked attributes\n"));
2258                         continue;
2259                 }
2260
2261                 if (invocation_id == NULL) {
2262                         invocation_id = samdb_ntds_invocation_id(ldb);
2263                         if (invocation_id == NULL) {
2264                                 return LDB_ERR_OPERATIONS_ERROR;
2265                         }
2266                 }
2267
2268
2269                 /* it's an old one that needs upgrading */
2270                 ret = replmd_update_la_val(el->values, dns[i].v,
2271                                            dns[i].dsdb_dn, dns[i].dsdb_dn,
2272                                            invocation_id, 1, 1, 0, false);
2273                 if (ret != LDB_SUCCESS) {
2274                         return ret;
2275                 }
2276         }
2277
2278         /*
2279          * This sort() is critical for the operation of
2280          * get_parsed_dns_trusted() because callers of this function
2281          * expect a sorted list, and FL2000 style links are not
2282          * sorted.  In particular, as well as the upgrade case,
2283          * get_parsed_dns_trusted() is called from
2284          * replmd_delete_remove_link() even in FL2000 mode
2285          *
2286          * We do not normally pay the cost of the qsort() due to the
2287          * early return in the RMD_VERSION found case.
2288          */
2289         TYPESAFE_QSORT(dns, count, parsed_dn_compare);
2290         return LDB_SUCCESS;
2291 }
2292
2293 /*
2294   Sets the value for a linked attribute, including all meta data fields
2295
2296   see replmd_build_la_val for value names
2297  */
2298 static int replmd_set_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
2299                              struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
2300                              uint64_t usn, uint64_t local_usn, NTTIME nttime,
2301                              uint32_t version, bool deleted)
2302 {
2303         struct ldb_dn *dn = dsdb_dn->dn;
2304         const char *tstring, *usn_string, *flags_string;
2305         struct ldb_val tval;
2306         struct ldb_val iid;
2307         struct ldb_val usnv, local_usnv;
2308         struct ldb_val vers, flagsv;
2309         const struct ldb_val *old_addtime = NULL;
2310         NTSTATUS status;
2311         int ret;
2312         const char *dnstring;
2313         char *vstring;
2314         uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
2315
2316         tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
2317         if (!tstring) {
2318                 return LDB_ERR_OPERATIONS_ERROR;
2319         }
2320         tval = data_blob_string_const(tstring);
2321
2322         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)usn);
2323         if (!usn_string) {
2324                 return LDB_ERR_OPERATIONS_ERROR;
2325         }
2326         usnv = data_blob_string_const(usn_string);
2327
2328         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)local_usn);
2329         if (!usn_string) {
2330                 return LDB_ERR_OPERATIONS_ERROR;
2331         }
2332         local_usnv = data_blob_string_const(usn_string);
2333
2334         status = GUID_to_ndr_blob(invocation_id, dn, &iid);
2335         if (!NT_STATUS_IS_OK(status)) {
2336                 return LDB_ERR_OPERATIONS_ERROR;
2337         }
2338
2339         flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
2340         if (!flags_string) {
2341                 return LDB_ERR_OPERATIONS_ERROR;
2342         }
2343         flagsv = data_blob_string_const(flags_string);
2344
2345         ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
2346         if (ret != LDB_SUCCESS) return ret;
2347
2348         /* get the ADDTIME from the original */
2349         if (old_dsdb_dn != NULL) {
2350                 old_addtime = ldb_dn_get_extended_component(old_dsdb_dn->dn,
2351                                                             "RMD_ADDTIME");
2352         }
2353         if (old_addtime == NULL) {
2354                 old_addtime = &tval;
2355         }
2356         if (dsdb_dn != old_dsdb_dn ||
2357             ldb_dn_get_extended_component(dn, "RMD_ADDTIME") == NULL) {
2358                 ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime);
2359                 if (ret != LDB_SUCCESS) return ret;
2360         }
2361
2362         /* use our invocation id */
2363         ret = ldb_dn_set_extended_component(dn, "RMD_INVOCID", &iid);
2364         if (ret != LDB_SUCCESS) return ret;
2365
2366         /* changetime is the current time */
2367         ret = ldb_dn_set_extended_component(dn, "RMD_CHANGETIME", &tval);
2368         if (ret != LDB_SUCCESS) return ret;
2369
2370         /* update the USN */
2371         ret = ldb_dn_set_extended_component(dn, "RMD_ORIGINATING_USN", &usnv);
2372         if (ret != LDB_SUCCESS) return ret;
2373
2374         ret = ldb_dn_set_extended_component(dn, "RMD_LOCAL_USN", &local_usnv);
2375         if (ret != LDB_SUCCESS) return ret;
2376
2377         vstring = talloc_asprintf(mem_ctx, "%lu", (unsigned long)version);
2378         vers = data_blob_string_const(vstring);
2379         ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
2380         if (ret != LDB_SUCCESS) return ret;
2381
2382         dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
2383         if (dnstring == NULL) {
2384                 return LDB_ERR_OPERATIONS_ERROR;
2385         }
2386         *v = data_blob_string_const(dnstring);
2387
2388         return LDB_SUCCESS;
2389 }
2390
2391 /**
2392  * Updates the value for a linked attribute, including all meta data fields
2393  */
2394 static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
2395                                 struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
2396                                 uint64_t usn, uint64_t local_usn, NTTIME nttime,
2397                                 bool deleted)
2398 {
2399         uint32_t old_version;
2400         uint32_t version = RMD_VERSION_INITIAL;
2401         NTSTATUS status;
2402
2403         /*
2404          * We're updating the linked attribute locally, so increase the version
2405          * by 1 so that other DCs will see the change when it gets replicated out
2406          */
2407         status = dsdb_get_extended_dn_uint32(old_dsdb_dn->dn, &old_version,
2408                                              "RMD_VERSION");
2409
2410         if (NT_STATUS_IS_OK(status)) {
2411                 version = old_version + 1;
2412         }
2413
2414         return replmd_set_la_val(mem_ctx, v, dsdb_dn, old_dsdb_dn, invocation_id,
2415                                  usn, local_usn, nttime, version, deleted);
2416 }
2417
2418 /*
2419   handle adding a linked attribute
2420  */
2421 static int replmd_modify_la_add(struct ldb_module *module,
2422                                 struct replmd_private *replmd_private,
2423                                 struct replmd_replicated_request *ac,
2424                                 struct ldb_message *msg,
2425                                 struct ldb_message_element *el,
2426                                 struct ldb_message_element *old_el,
2427                                 const struct dsdb_attribute *schema_attr,
2428                                 time_t t,
2429                                 struct ldb_dn *msg_dn,
2430                                 struct ldb_request *parent)
2431 {
2432         unsigned int i, j;
2433         struct parsed_dn *dns, *old_dns;
2434         TALLOC_CTX *tmp_ctx = talloc_new(msg);
2435         int ret;
2436         struct ldb_val *new_values = NULL;
2437         unsigned old_num_values = old_el ? old_el->num_values : 0;
2438         unsigned num_values = 0;
2439         unsigned max_num_values;
2440         struct ldb_context *ldb = ldb_module_get_ctx(module);
2441         NTTIME now;
2442         unix_to_nt_time(&now, t);
2443
2444         /* get the DNs to be added, fully parsed.
2445          *
2446          * We need full parsing because they came off the wire and we don't
2447          * trust them, besides which we need their details to know where to put
2448          * them.
2449          */
2450         ret = get_parsed_dns(module, tmp_ctx, el, &dns,
2451                              schema_attr->syntax->ldap_oid, parent);
2452         if (ret != LDB_SUCCESS) {
2453                 talloc_free(tmp_ctx);
2454                 return ret;
2455         }
2456
2457         /* get the existing DNs, lazily parsed */
2458         ret = get_parsed_dns_trusted(module, replmd_private,
2459                                      tmp_ctx, old_el, &old_dns,
2460                                      schema_attr->syntax->ldap_oid, parent);
2461
2462         if (ret != LDB_SUCCESS) {
2463                 talloc_free(tmp_ctx);
2464                 return ret;
2465         }
2466
2467         max_num_values = old_num_values + el->num_values;
2468         if (max_num_values < old_num_values) {
2469                 DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. "
2470                           "old values: %u, new values: %u, sum: %u\n",
2471                           old_num_values, el->num_values, max_num_values));
2472                 talloc_free(tmp_ctx);
2473                 return LDB_ERR_OPERATIONS_ERROR;
2474         }
2475
2476         new_values = talloc_zero_array(tmp_ctx, struct ldb_val, max_num_values);
2477
2478         if (new_values == NULL) {
2479                 ldb_module_oom(module);
2480                 talloc_free(tmp_ctx);
2481                 return LDB_ERR_OPERATIONS_ERROR;
2482         }
2483
2484         /*
2485          * For each new value, find where it would go in the list. If there is
2486          * a matching GUID there, we update the existing value; otherwise we
2487          * put it in place.
2488          */
2489         j = 0;
2490         for (i = 0; i < el->num_values; i++) {
2491                 struct parsed_dn *exact;
2492                 struct parsed_dn *next;
2493                 unsigned offset;
2494                 int err = parsed_dn_find(ldb, old_dns, old_num_values,
2495                                          &dns[i].guid,
2496                                          dns[i].dsdb_dn->dn,
2497                                          dns[i].dsdb_dn->extra_part, 0,
2498                                          &exact, &next,
2499                                          schema_attr->syntax->ldap_oid,
2500                                          true);
2501                 if (err != LDB_SUCCESS) {
2502                         talloc_free(tmp_ctx);
2503                         return err;
2504                 }
2505
2506                 if (ac->fix_link_sid) {
2507                         char *fixed_dnstring = NULL;
2508                         struct dom_sid tmp_sid = { 0, };
2509                         DATA_BLOB sid_blob = data_blob_null;
2510                         enum ndr_err_code ndr_err;
2511                         NTSTATUS status;
2512                         int num;
2513
2514                         if (exact == NULL) {
2515                                 talloc_free(tmp_ctx);
2516                                 return ldb_operr(ldb);
2517                         }
2518
2519                         if (dns[i].dsdb_dn->dn_format != DSDB_NORMAL_DN) {
2520                                 talloc_free(tmp_ctx);
2521                                 return ldb_operr(ldb);
2522                         }
2523
2524                         /*
2525                          * Only "<GUID=...><SID=...>" is allowed.
2526                          *
2527                          * We get the GUID to just to find the old
2528                          * value and the SID in order to add it
2529                          * to the found value.
2530                          */
2531
2532                         num = ldb_dn_get_comp_num(dns[i].dsdb_dn->dn);
2533                         if (num != 0) {
2534                                 talloc_free(tmp_ctx);
2535                                 return ldb_operr(ldb);
2536                         }
2537
2538                         num = ldb_dn_get_extended_comp_num(dns[i].dsdb_dn->dn);
2539                         if (num != 2) {
2540                                 talloc_free(tmp_ctx);
2541                                 return ldb_operr(ldb);
2542                         }
2543
2544                         status = dsdb_get_extended_dn_sid(exact->dsdb_dn->dn,
2545                                                           &tmp_sid, "SID");
2546                         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2547                                 /* this is what we expect */
2548                         } else if (NT_STATUS_IS_OK(status)) {
2549                                 struct GUID_txt_buf guid_str;
2550                                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
2551                                                        "i[%u] SID NOT MISSING... Attribute %s already "
2552                                                        "exists for target GUID %s, SID %s, DN: %s",
2553                                                        i, el->name,
2554                                                        GUID_buf_string(&exact->guid,
2555                                                                        &guid_str),
2556                                                        dom_sid_string(tmp_ctx, &tmp_sid),
2557                                                        dsdb_dn_get_extended_linearized(tmp_ctx,
2558                                                                exact->dsdb_dn, 1));
2559                                 talloc_free(tmp_ctx);
2560                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2561                         } else {
2562                                 talloc_free(tmp_ctx);
2563                                 return ldb_operr(ldb);
2564                         }
2565
2566                         status = dsdb_get_extended_dn_sid(dns[i].dsdb_dn->dn,
2567                                                           &tmp_sid, "SID");
2568                         if (!NT_STATUS_IS_OK(status)) {
2569                                 struct GUID_txt_buf guid_str;
2570                                 ldb_asprintf_errstring(ldb,
2571                                                        "NO SID PROVIDED... Attribute %s already "
2572                                                        "exists for target GUID %s",
2573                                                        el->name,
2574                                                        GUID_buf_string(&exact->guid,
2575                                                                        &guid_str));
2576                                 talloc_free(tmp_ctx);
2577                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2578                         }
2579
2580                         ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &tmp_sid,
2581                                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
2582                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2583                                 talloc_free(tmp_ctx);
2584                                 return ldb_operr(ldb);
2585                         }
2586
2587                         ret = ldb_dn_set_extended_component(exact->dsdb_dn->dn, "SID", &sid_blob);
2588                         data_blob_free(&sid_blob);
2589                         if (ret != LDB_SUCCESS) {
2590                                 talloc_free(tmp_ctx);
2591                                 return ret;
2592                         }
2593
2594                         fixed_dnstring = dsdb_dn_get_extended_linearized(
2595                                         new_values, exact->dsdb_dn, 1);
2596                         if (fixed_dnstring == NULL) {
2597                                 talloc_free(tmp_ctx);
2598                                 return ldb_operr(ldb);
2599                         }
2600
2601                         /*
2602                          * We just replace the existing value...
2603                          */
2604                         *exact->v = data_blob_string_const(fixed_dnstring);
2605
2606                         continue;
2607                 }
2608
2609                 if (exact != NULL) {
2610                         /*
2611                          * We are trying to add one that exists, which is only
2612                          * allowed if it was previously deleted.
2613                          *
2614                          * When we do undelete a link we change it in place.
2615                          * It will be copied across into the right spot in due
2616                          * course.
2617                          */
2618                         uint32_t rmd_flags;
2619                         rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2620
2621                         if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
2622                                 struct GUID_txt_buf guid_str;
2623                                 ldb_asprintf_errstring(ldb,
2624                                                        "Attribute %s already "
2625                                                        "exists for target GUID %s",
2626                                                        el->name,
2627                                                        GUID_buf_string(&exact->guid,
2628                                                                        &guid_str));
2629                                 talloc_free(tmp_ctx);
2630                                 /* error codes for 'member' need to be
2631                                    special cased */
2632                                 if (ldb_attr_cmp(el->name, "member") == 0) {
2633                                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
2634                                 } else {
2635                                         return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2636                                 }
2637                         }
2638
2639                         ret = replmd_update_la_val(new_values, exact->v,
2640                                                    dns[i].dsdb_dn,
2641                                                    exact->dsdb_dn,
2642                                                    &ac->our_invocation_id,
2643                                                    ac->seq_num, ac->seq_num,
2644                                                    now, false);
2645                         if (ret != LDB_SUCCESS) {
2646                                 talloc_free(tmp_ctx);
2647                                 return ret;
2648                         }
2649
2650                         ret = replmd_add_backlink(module, replmd_private,
2651                                                   ac->schema,
2652                                                   msg_dn,
2653                                                   &dns[i].guid, 
2654                                                   true,
2655                                                   schema_attr,
2656                                                   parent);
2657                         if (ret != LDB_SUCCESS) {
2658                                 talloc_free(tmp_ctx);
2659                                 return ret;
2660                                 }
2661                         continue;
2662                 }
2663                 /*
2664                  * Here we don't have an exact match.
2665                  *
2666                  * If next is NULL, this one goes beyond the end of the
2667                  * existing list, so we need to add all of those ones first.
2668                  *
2669                  * If next is not NULL, we need to add all the ones before
2670                  * next.
2671                  */
2672                 if (next == NULL) {
2673                         offset = old_num_values;
2674                 } else {
2675                         /* next should have been parsed, but let's make sure */
2676                         if (next->dsdb_dn == NULL) {
2677                                 ret = really_parse_trusted_dn(tmp_ctx, ldb, next,
2678                                                               schema_attr->syntax->ldap_oid);
2679                                 if (ret != LDB_SUCCESS) {
2680                                         return ret;
2681                                 }
2682                         }
2683                         offset = MIN(next - old_dns, old_num_values);
2684                 }
2685
2686                 /* put all the old ones before next on the list */
2687                 for (; j < offset; j++) {
2688                         new_values[num_values] = *old_dns[j].v;
2689                         num_values++;
2690                 }
2691
2692                 ret = replmd_add_backlink(module, replmd_private,
2693                                           ac->schema, msg_dn,
2694                                           &dns[i].guid,
2695                                           true, schema_attr,
2696                                           parent);
2697                 /* Make the new linked attribute ldb_val. */
2698                 ret = replmd_build_la_val(new_values, &new_values[num_values],
2699                                           dns[i].dsdb_dn, &ac->our_invocation_id,
2700                                           ac->seq_num, now);
2701                 if (ret != LDB_SUCCESS) {
2702                         talloc_free(tmp_ctx);
2703                         return ret;
2704                 }
2705                 num_values++;
2706                 if (ret != LDB_SUCCESS) {
2707                         talloc_free(tmp_ctx);
2708                         return ret;
2709                 }
2710         }
2711         /* copy the rest of the old ones (if any) */
2712         for (; j < old_num_values; j++) {
2713                 new_values[num_values] = *old_dns[j].v;
2714                 num_values++;
2715         }
2716
2717         talloc_steal(msg->elements, new_values);
2718         if (old_el != NULL) {
2719                 talloc_steal(msg->elements, old_el->values);
2720         }
2721         el->values = new_values;
2722         el->num_values = num_values;
2723
2724         talloc_free(tmp_ctx);
2725
2726         /* we now tell the backend to replace all existing values
2727            with the one we have constructed */
2728         el->flags = LDB_FLAG_MOD_REPLACE;
2729
2730         return LDB_SUCCESS;
2731 }
2732
2733
2734 /*
2735   handle deleting all active linked attributes
2736  */
2737 static int replmd_modify_la_delete(struct ldb_module *module,
2738                                    struct replmd_private *replmd_private,
2739                                    struct replmd_replicated_request *ac,
2740                                    struct ldb_message *msg,
2741                                    struct ldb_message_element *el,
2742                                    struct ldb_message_element *old_el,
2743                                    const struct dsdb_attribute *schema_attr,
2744                                    time_t t,
2745                                    struct ldb_dn *msg_dn,
2746                                    struct ldb_request *parent)
2747 {
2748         unsigned int i;
2749         struct parsed_dn *dns, *old_dns;
2750         TALLOC_CTX *tmp_ctx = NULL;
2751         int ret;
2752         struct ldb_context *ldb = ldb_module_get_ctx(module);
2753         struct ldb_control *vanish_links_ctrl = NULL;
2754         bool vanish_links = false;
2755         unsigned int num_to_delete = el->num_values;
2756         uint32_t rmd_flags;
2757         NTTIME now;
2758
2759         unix_to_nt_time(&now, t);
2760
2761         if (old_el == NULL || old_el->num_values == 0) {
2762                 /* there is nothing to delete... */
2763                 if (num_to_delete == 0) {
2764                         /* and we're deleting nothing, so that's OK */
2765                         return LDB_SUCCESS;
2766                 }
2767                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2768         }
2769
2770         tmp_ctx = talloc_new(msg);
2771         if (tmp_ctx == NULL) {
2772                 return LDB_ERR_OPERATIONS_ERROR;
2773         }
2774
2775         ret = get_parsed_dns(module, tmp_ctx, el, &dns,
2776                              schema_attr->syntax->ldap_oid, parent);
2777         if (ret != LDB_SUCCESS) {
2778                 talloc_free(tmp_ctx);
2779                 return ret;
2780         }
2781
2782         ret = get_parsed_dns_trusted(module, replmd_private,
2783                                      tmp_ctx, old_el, &old_dns,
2784                                      schema_attr->syntax->ldap_oid, parent);
2785
2786         if (ret != LDB_SUCCESS) {
2787                 talloc_free(tmp_ctx);
2788                 return ret;
2789         }
2790
2791         if (parent) {
2792                 vanish_links_ctrl = ldb_request_get_control(parent, DSDB_CONTROL_REPLMD_VANISH_LINKS);
2793                 if (vanish_links_ctrl) {
2794                         vanish_links = true;
2795                         vanish_links_ctrl->critical = false;
2796                 }
2797         }
2798
2799         /* we empty out el->values here to avoid damage if we return early. */
2800         el->num_values = 0;
2801         el->values = NULL;
2802
2803         /*
2804          * If vanish links is set, we are actually removing members of
2805          *  old_el->values; otherwise we are just marking them deleted.
2806          *
2807          * There is a special case when no values are given: we remove them
2808          * all. When we have the vanish_links control we just have to remove
2809          * the backlinks and change our element to replace the existing values
2810          * with the empty list.
2811          */
2812
2813         if (num_to_delete == 0) {
2814                 for (i = 0; i < old_el->num_values; i++) {
2815                         struct parsed_dn *p = &old_dns[i];
2816                         if (p->dsdb_dn == NULL) {
2817                                 ret = really_parse_trusted_dn(tmp_ctx, ldb, p,
2818                                                               schema_attr->syntax->ldap_oid);
2819                                 if (ret != LDB_SUCCESS) {
2820                                         return ret;
2821                                 }
2822                         }
2823                         ret = replmd_add_backlink(module, replmd_private,
2824                                                   ac->schema, msg_dn, &p->guid,
2825                                                   false, schema_attr,
2826                                                   parent);
2827                         if (ret != LDB_SUCCESS) {
2828                                 talloc_free(tmp_ctx);
2829                                 return ret;
2830                         }
2831                         if (vanish_links) {
2832                                 continue;
2833                         }
2834
2835                         rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
2836                         if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
2837                                 continue;
2838                         }
2839
2840                         ret = replmd_update_la_val(old_el->values, p->v,
2841                                                    p->dsdb_dn, p->dsdb_dn,
2842                                                    &ac->our_invocation_id,
2843                                                    ac->seq_num, ac->seq_num,
2844                                                    now, true);
2845                         if (ret != LDB_SUCCESS) {
2846                                 talloc_free(tmp_ctx);
2847                                 return ret;
2848                         }
2849                 }
2850
2851                 if (vanish_links) {
2852                         el->flags = LDB_FLAG_MOD_REPLACE;
2853                         talloc_free(tmp_ctx);
2854                         return LDB_SUCCESS;
2855                 }
2856         }
2857
2858
2859         for (i = 0; i < num_to_delete; i++) {
2860                 struct parsed_dn *p = &dns[i];
2861                 struct parsed_dn *exact = NULL;
2862                 struct parsed_dn *next = NULL;
2863                 ret = parsed_dn_find(ldb, old_dns, old_el->num_values,
2864                                      &p->guid,
2865                                      NULL,
2866                                      p->dsdb_dn->extra_part, 0,
2867                                      &exact, &next,
2868                                      schema_attr->syntax->ldap_oid,
2869                                      true);
2870                 if (ret != LDB_SUCCESS) {
2871                         talloc_free(tmp_ctx);
2872                         return ret;
2873                 }
2874                 if (exact == NULL) {
2875                         struct GUID_txt_buf buf;
2876                         ldb_asprintf_errstring(ldb, "Attribute %s doesn't "
2877                                                "exist for target GUID %s",
2878                                                el->name,
2879                                                GUID_buf_string(&p->guid, &buf));
2880                         if (ldb_attr_cmp(el->name, "member") == 0) {
2881                                 talloc_free(tmp_ctx);
2882                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2883                         } else {
2884                                 talloc_free(tmp_ctx);
2885                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2886                         }
2887                 }
2888
2889                 if (vanish_links) {
2890                         if (CHECK_DEBUGLVL(5)) {
2891                                 rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2892                                 if ((rmd_flags & DSDB_RMD_FLAG_DELETED)) {
2893                                         struct GUID_txt_buf buf;
2894                                         const char *guid_str = \
2895                                                 GUID_buf_string(&p->guid, &buf);
2896                                         DEBUG(5, ("Deleting deleted linked "
2897                                                   "attribute %s to %s, because "
2898                                                   "vanish_links control is set\n",
2899                                                   el->name, guid_str));
2900                                 }
2901                         }
2902
2903                         /* remove the backlink */
2904                         ret = replmd_add_backlink(module,
2905                                                   replmd_private,
2906                                                   ac->schema,
2907                                                   msg_dn,
2908                                                   &p->guid,
2909                                                   false, schema_attr,
2910                                                   parent);
2911                         if (ret != LDB_SUCCESS) {
2912                                 talloc_free(tmp_ctx);
2913                                 return ret;
2914                         }
2915
2916                         /* We flag the deletion and tidy it up later. */
2917                         exact->v = NULL;
2918                         continue;
2919                 }
2920
2921                 rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2922
2923                 if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
2924                         struct GUID_txt_buf buf;
2925                         const char *guid_str = GUID_buf_string(&p->guid, &buf);
2926                         ldb_asprintf_errstring(ldb, "Attribute %s already "
2927                                                "deleted for target GUID %s",
2928                                                el->name, guid_str);
2929                         if (ldb_attr_cmp(el->name, "member") == 0) {
2930                                 talloc_free(tmp_ctx);
2931                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2932                         } else {
2933                                 talloc_free(tmp_ctx);
2934                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2935                         }
2936                 }
2937
2938                 ret = replmd_update_la_val(old_el->values, exact->v,
2939                                            exact->dsdb_dn, exact->dsdb_dn,
2940                                            &ac->our_invocation_id,
2941                                            ac->seq_num, ac->seq_num,
2942                                            now, true);
2943                 if (ret != LDB_SUCCESS) {
2944                         talloc_free(tmp_ctx);
2945                         return ret;
2946                 }
2947                 ret = replmd_add_backlink(module, replmd_private,
2948                                           ac->schema, msg_dn,
2949                                           &p->guid,
2950                                           false, schema_attr,
2951                                           parent);
2952                 if (ret != LDB_SUCCESS) {
2953                         talloc_free(tmp_ctx);
2954                         return ret;
2955                 }
2956         }
2957
2958         if (vanish_links) {
2959                 unsigned j = 0;
2960                 struct ldb_val *tmp_vals = NULL;
2961
2962                 tmp_vals = talloc_array(tmp_ctx, struct ldb_val,
2963                                         old_el->num_values);
2964                 if (tmp_vals == NULL) {
2965                         talloc_free(tmp_ctx);
2966                         return ldb_module_oom(module);
2967                 }
2968                 for (i = 0; i < old_el->num_values; i++) {
2969                         if (old_dns[i].v == NULL) {
2970                                 continue;
2971                         }
2972                         tmp_vals[j] = *old_dns[i].v;
2973                         j++;
2974                 }
2975                 for (i = 0; i < j; i++) {
2976                         old_el->values[i] = tmp_vals[i];
2977                 }
2978                 old_el->num_values = j;
2979         }
2980
2981         el->values = talloc_steal(msg->elements, old_el->values);
2982         el->num_values = old_el->num_values;
2983
2984         talloc_free(tmp_ctx);
2985
2986         /* we now tell the backend to replace all existing values
2987            with the one we have constructed */
2988         el->flags = LDB_FLAG_MOD_REPLACE;
2989
2990         return LDB_SUCCESS;
2991 }
2992
2993 /*
2994   handle replacing a linked attribute
2995  */
2996 static int replmd_modify_la_replace(struct ldb_module *module,
2997                                     struct replmd_private *replmd_private,
2998                                     struct replmd_replicated_request *ac,
2999                                     struct ldb_message *msg,
3000                                     struct ldb_message_element *el,
3001                                     struct ldb_message_element *old_el,
3002                                     const struct dsdb_attribute *schema_attr,
3003                                     time_t t,
3004                                     struct ldb_dn *msg_dn,
3005                                     struct ldb_request *parent)
3006 {
3007         unsigned int i, old_i, new_i;
3008         struct parsed_dn *dns, *old_dns;
3009         TALLOC_CTX *tmp_ctx = talloc_new(msg);
3010         int ret;
3011         struct ldb_context *ldb = ldb_module_get_ctx(module);
3012         struct ldb_val *new_values = NULL;
3013         const char *ldap_oid = schema_attr->syntax->ldap_oid;
3014         unsigned int old_num_values;
3015         unsigned int repl_num_values;
3016         unsigned int max_num_values;
3017         NTTIME now;
3018
3019         unix_to_nt_time(&now, t);
3020
3021         /*
3022          * The replace operation is unlike the replace and delete cases in that
3023          * we need to look at every existing link to see whether it is being
3024          * retained or deleted. In other words, we can't avoid parsing the GUIDs.
3025          *
3026          * As we are trying to combine two sorted lists, the algorithm we use
3027          * is akin to the merge phase of a merge sort. We interleave the two
3028          * lists, doing different things depending on which side the current
3029          * item came from.
3030          *
3031          * There are three main cases, with some sub-cases.
3032          *
3033          *  - a DN is in the old list but not the new one. It needs to be
3034          *    marked as deleted (but left in the list).
3035          *     - maybe it is already deleted, and we have less to do.
3036          *
3037          *  - a DN is in both lists. The old data gets replaced by the new,
3038          *    and the list doesn't grow. The old link may have been marked as
3039          *    deleted, in which case we undelete it.
3040          *
3041          *  - a DN is in the new list only. We add it in the right place.
3042          */
3043
3044         old_num_values = old_el ? old_el->num_values : 0;
3045         repl_num_values = el->num_values;
3046         max_num_values = old_num_values + repl_num_values;
3047
3048         if (max_num_values == 0) {
3049                 /* There is nothing to do! */
3050                 return LDB_SUCCESS;
3051         }
3052
3053         ret = get_parsed_dns(module, tmp_ctx, el, &dns, ldap_oid, parent);
3054         if (ret != LDB_SUCCESS) {
3055                 talloc_free(tmp_ctx);
3056                 return ret;
3057         }
3058
3059         ret = check_parsed_dn_duplicates(module, el, dns);
3060         if (ret != LDB_SUCCESS) {
3061                 talloc_free(tmp_ctx);
3062                 return ret;
3063         }
3064
3065         ret = get_parsed_dns(module, tmp_ctx, old_el, &old_dns,
3066                              ldap_oid, parent);
3067         if (ret != LDB_SUCCESS) {
3068                 talloc_free(tmp_ctx);
3069                 return ret;
3070         }
3071
3072         ret = replmd_check_upgrade_links(ldb, old_dns, old_num_values,
3073                                          old_el, ldap_oid);
3074         if (ret != LDB_SUCCESS) {
3075                 talloc_free(tmp_ctx);
3076                 return ret;
3077         }
3078
3079         new_values = talloc_array(tmp_ctx, struct ldb_val, max_num_values);
3080         if (new_values == NULL) {
3081                 ldb_module_oom(module);
3082                 talloc_free(tmp_ctx);
3083                 return LDB_ERR_OPERATIONS_ERROR;
3084         }
3085
3086         old_i = 0;
3087         new_i = 0;
3088         for (i = 0; i < max_num_values; i++) {
3089                 int cmp;
3090                 struct parsed_dn *old_p, *new_p;
3091                 if (old_i < old_num_values && new_i < repl_num_values) {
3092                         old_p = &old_dns[old_i];
3093                         new_p = &dns[new_i];
3094                         cmp = parsed_dn_compare(old_p, new_p);
3095                 } else if (old_i < old_num_values) {
3096                         /* the new list is empty, read the old list */
3097                         old_p = &old_dns[old_i];
3098                         new_p = NULL;
3099                         cmp = -1;
3100                 } else if (new_i < repl_num_values) {
3101                         /* the old list is empty, read new list */
3102                         old_p = NULL;
3103                         new_p = &dns[new_i];
3104                         cmp = 1;
3105                 } else {
3106                         break;
3107                 }
3108
3109                 if (cmp < 0) {
3110                         /*
3111                          * An old ones that come before the next replacement
3112                          * (if any). We mark it as deleted and add it to the
3113                          * final list.
3114                          */
3115                         uint32_t rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
3116                         if ((rmd_flags & DSDB_RMD_FLAG_DELETED) == 0) {
3117                                 ret = replmd_update_la_val(new_values, old_p->v,
3118                                                            old_p->dsdb_dn,
3119                                                            old_p->dsdb_dn,
3120                                                            &ac->our_invocation_id,
3121                                                            ac->seq_num, ac->seq_num,
3122                                                            now, true);
3123                                 if (ret != LDB_SUCCESS) {
3124                                         talloc_free(tmp_ctx);
3125                                         return ret;
3126                                 }
3127
3128                                 ret = replmd_add_backlink(module, replmd_private,
3129                                                           ac->schema,
3130                                                           msg_dn,
3131                                                           &old_p->guid, false,
3132                                                           schema_attr,
3133                                                           parent);
3134                                 if (ret != LDB_SUCCESS) {
3135                                         talloc_free(tmp_ctx);
3136                                         return ret;
3137                                 }
3138                         }
3139                         new_values[i] = *old_p->v;
3140                         old_i++;
3141                 } else if (cmp == 0) {
3142                         /*
3143                          * We are overwriting one. If it was previously
3144                          * deleted, we need to add a backlink.
3145                          *
3146                          * Note that if any RMD_FLAGs in an extended new DN
3147                          * will be ignored.
3148                          */
3149                         uint32_t rmd_flags;
3150
3151                         ret = replmd_update_la_val(new_values, old_p->v,
3152                                                    new_p->dsdb_dn,
3153                                                    old_p->dsdb_dn,
3154                                                    &ac->our_invocation_id,
3155                                                    ac->seq_num, ac->seq_num,
3156                                                    now, false);
3157                         if (ret != LDB_SUCCESS) {
3158                                 talloc_free(tmp_ctx);
3159                                 return ret;
3160                         }
3161
3162                         rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
3163                         if ((rmd_flags & DSDB_RMD_FLAG_DELETED) != 0) {
3164                                 ret = replmd_add_backlink(module, replmd_private,
3165                                                           ac->schema,
3166                                                           msg_dn,
3167                                                           &new_p->guid, true,
3168                                                           schema_attr,
3169                                                           parent);
3170                                 if (ret != LDB_SUCCESS) {
3171                                         talloc_free(tmp_ctx);
3172                                         return ret;
3173                                 }
3174                         }
3175
3176                         new_values[i] = *old_p->v;
3177                         old_i++;
3178                         new_i++;
3179                 } else {
3180                         /*
3181                          * Replacements that don't match an existing one. We
3182                          * just add them to the final list.
3183                          */
3184                         ret = replmd_build_la_val(new_values,
3185                                                   new_p->v,
3186                                                   new_p->dsdb_dn,
3187                                                   &ac->our_invocation_id,
3188                                                   ac->seq_num, now);
3189                         if (ret != LDB_SUCCESS) {
3190                                 talloc_free(tmp_ctx);
3191                                 return ret;
3192                         }
3193                         ret = replmd_add_backlink(module, replmd_private,
3194                                                   ac->schema,
3195                                                   msg_dn,
3196                                                   &new_p->guid, true,
3197                                                   schema_attr,
3198                                                   parent);
3199                         if (ret != LDB_SUCCESS) {
3200                                 talloc_free(tmp_ctx);
3201                                 return ret;
3202                         }
3203                         new_values[i] = *new_p->v;
3204                         new_i++;
3205                 }
3206         }
3207         if (old_el != NULL) {
3208                 talloc_steal(msg->elements, old_el->values);
3209         }
3210         el->values = talloc_steal(msg->elements, new_values);
3211         el->num_values = i;
3212         talloc_free(tmp_ctx);
3213
3214         el->flags = LDB_FLAG_MOD_REPLACE;
3215
3216         return LDB_SUCCESS;
3217 }
3218
3219
3220 /*
3221   handle linked attributes in modify requests
3222  */
3223 static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
3224                                                struct replmd_private *replmd_private,
3225                                                struct replmd_replicated_request *ac,
3226                                                struct ldb_message *msg,
3227                                                time_t t,
3228                                                struct ldb_request *parent)
3229 {
3230         struct ldb_result *res;
3231         unsigned int i;
3232         int ret;
3233         struct ldb_context *ldb = ldb_module_get_ctx(module);
3234         struct ldb_message *old_msg;
3235
3236         if (dsdb_functional_level(ldb) == DS_DOMAIN_FUNCTION_2000) {
3237                 /*
3238                  * Nothing special is required for modifying or vanishing links
3239                  * in fl2000 since they are just strings in a multi-valued
3240                  * attribute.
3241                  */
3242                 struct ldb_control *ctrl = ldb_request_get_control(parent,
3243                                                                    DSDB_CONTROL_REPLMD_VANISH_LINKS);
3244                 if (ctrl) {
3245                         ctrl->critical = false;
3246                 }
3247                 return LDB_SUCCESS;
3248         }
3249
3250         /*
3251          * TODO:
3252          *
3253          * We should restrict this to the intersection of the list of
3254          * linked attributes in the schema and the list of attributes
3255          * being modified.
3256          *
3257          * This will help performance a little, as otherwise we have
3258          * to allocate the entire object value-by-value.
3259          */
3260         ret = dsdb_module_search_dn(module, msg, &res, msg->dn, NULL,
3261                                     DSDB_FLAG_NEXT_MODULE |
3262                                     DSDB_SEARCH_SHOW_RECYCLED |
3263                                     DSDB_SEARCH_REVEAL_INTERNALS |
3264                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
3265                                     parent);
3266         if (ret != LDB_SUCCESS) {
3267                 return ret;
3268         }
3269
3270         old_msg = res->msgs[0];
3271
3272         for (i=0; i<msg->num_elements; i++) {
3273                 struct ldb_message_element *el = &msg->elements[i];
3274                 struct ldb_message_element *old_el, *new_el;
3275                 unsigned int mod_type = LDB_FLAG_MOD_TYPE(el->flags);
3276                 const struct dsdb_attribute *schema_attr
3277                         = dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name);
3278                 if (!schema_attr) {
3279                         ldb_asprintf_errstring(ldb,
3280                                                "%s: attribute %s is not a valid attribute in schema",
3281                                                __FUNCTION__, el->name);
3282                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
3283                 }
3284                 if (schema_attr->linkID == 0) {
3285                         continue;
3286                 }
3287                 if ((schema_attr->linkID & 1) == 1) {
3288                         if (parent) {
3289                                 struct ldb_control *ctrl;
3290
3291                                 ctrl = ldb_request_get_control(parent,
3292                                                 DSDB_CONTROL_REPLMD_VANISH_LINKS);
3293                                 if (ctrl != NULL) {
3294                                         ctrl->critical = false;
3295                                         continue;
3296                                 }
3297                                 ctrl = ldb_request_get_control(parent,
3298                                                 DSDB_CONTROL_DBCHECK);
3299                                 if (ctrl != NULL) {
3300                                         continue;
3301                                 }
3302                         }
3303
3304                         /* Odd is for the target.  Illegal to modify */
3305                         ldb_asprintf_errstring(ldb,
3306                                                "attribute %s must not be modified directly, it is a linked attribute", el->name);
3307                         return LDB_ERR_UNWILLING_TO_PERFORM;
3308                 }
3309                 old_el = ldb_msg_find_element(old_msg, el->name);
3310                 switch (mod_type) {
3311                 case LDB_FLAG_MOD_REPLACE:
3312                         ret = replmd_modify_la_replace(module, replmd_private,
3313                                                        ac, msg, el, old_el,
3314                                                        schema_attr, t,
3315                                                        old_msg->dn,
3316                                                        parent);
3317                         break;
3318                 case LDB_FLAG_MOD_DELETE:
3319                         ret = replmd_modify_la_delete(module, replmd_private,
3320                                                       ac, msg, el, old_el,
3321                                                       schema_attr, t,
3322                                                       old_msg->dn,
3323                                                       parent);
3324                         break;
3325                 case LDB_FLAG_MOD_ADD:
3326                         ret = replmd_modify_la_add(module, replmd_private,
3327                                                    ac, msg, el, old_el,
3328                                                    schema_attr, t,
3329                                                    old_msg->dn,
3330                                                    parent);
3331                         break;
3332                 default:
3333                         ldb_asprintf_errstring(ldb,
3334                                                "invalid flags 0x%x for %s linked attribute",
3335                                                el->flags, el->name);
3336                         return LDB_ERR_UNWILLING_TO_PERFORM;
3337                 }
3338                 if (dsdb_check_single_valued_link(schema_attr, el) != LDB_SUCCESS) {
3339                         ldb_asprintf_errstring(ldb,
3340                                                "Attribute %s is single valued but more than one value has been supplied",
3341                                                el->name);
3342                         /* Return codes as found on Windows 2012r2 */
3343                         if (mod_type == LDB_FLAG_MOD_REPLACE) {
3344                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3345                         } else {
3346                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
3347                         }
3348                 } else {
3349                         el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
3350                 }
3351
3352                 if (ret != LDB_SUCCESS) {
3353                         return ret;
3354                 }
3355                 if (old_el) {
3356                         ldb_msg_remove_attr(old_msg, el->name);
3357                 }
3358                 ldb_msg_add_empty(old_msg, el->name, 0, &new_el);
3359                 new_el->num_values = el->num_values;
3360                 new_el->values = talloc_steal(msg->elements, el->values);
3361
3362                 /* TODO: this relises a bit too heavily on the exact
3363                    behaviour of ldb_msg_find_element and
3364                    ldb_msg_remove_element */
3365                 old_el = ldb_msg_find_element(msg, el->name);
3366                 if (old_el != el) {
3367                         ldb_msg_remove_element(msg, old_el);
3368                         i--;
3369                 }
3370         }
3371
3372         talloc_free(res);
3373         return ret;
3374 }
3375
3376
3377 static int send_rodc_referral(struct ldb_request *req,
3378                               struct ldb_context *ldb,
3379                               struct ldb_dn *dn)
3380 {
3381         char *referral = NULL;
3382         struct loadparm_context *lp_ctx = NULL;
3383         struct ldb_dn *fsmo_role_dn = NULL;
3384         struct ldb_dn *role_owner_dn = NULL;
3385         const char *domain = NULL;
3386         WERROR werr;
3387
3388         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
3389                                  struct loadparm_context);
3390
3391         werr = dsdb_get_fsmo_role_info(req, ldb, DREPL_PDC_MASTER,
3392                                        &fsmo_role_dn, &role_owner_dn);
3393
3394         if (W_ERROR_IS_OK(werr)) {
3395                 struct ldb_dn *server_dn = ldb_dn_copy(req, role_owner_dn);
3396                 if (server_dn != NULL) {
3397                         ldb_dn_remove_child_components(server_dn, 1);
3398                         domain = samdb_dn_to_dnshostname(ldb, req,
3399                                                          server_dn);
3400                 }
3401         }
3402
3403         if (domain == NULL) {
3404                 domain = lpcfg_dnsdomain(lp_ctx);
3405         }
3406
3407         referral = talloc_asprintf(req, "ldap://%s/%s",
3408                                    domain,
3409                                    ldb_dn_get_linearized(dn));
3410         if (referral == NULL) {
3411                 ldb_oom(ldb);
3412                 return LDB_ERR_OPERATIONS_ERROR;
3413         }
3414
3415         return ldb_module_send_referral(req, referral);
3416 }
3417
3418
3419 static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
3420 {
3421         struct ldb_context *ldb;
3422         struct replmd_replicated_request *ac;
3423         struct ldb_request *down_req;
3424         struct ldb_message *msg;
3425         time_t t = time(NULL);
3426         int ret;
3427         bool is_urgent = false, rodc = false;
3428         bool is_schema_nc = false;
3429         unsigned int functional_level;
3430         const struct ldb_message_element *guid_el = NULL;
3431         struct ldb_control *sd_propagation_control;
3432         struct ldb_control *fix_links_control = NULL;
3433         struct ldb_control *fix_dn_name_control = NULL;
3434         struct ldb_control *fix_dn_sid_control = NULL;
3435         struct replmd_private *replmd_private =
3436                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3437
3438         /* do not manipulate our control entries */
3439         if (ldb_dn_is_special(req->op.mod.message->dn)) {
3440                 return ldb_next_request(module, req);
3441         }
3442
3443         sd_propagation_control = ldb_request_get_control(req,
3444                                         DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
3445         if (sd_propagation_control != NULL) {
3446                 if (req->op.mod.message->num_elements != 1) {
3447                         return ldb_module_operr(module);
3448                 }
3449                 ret = strcmp(req->op.mod.message->elements[0].name,
3450                              "nTSecurityDescriptor");
3451                 if (ret != 0) {
3452                         return ldb_module_operr(module);
3453                 }
3454
3455                 return ldb_next_request(module, req);
3456         }
3457
3458         ldb = ldb_module_get_ctx(module);
3459
3460         fix_links_control = ldb_request_get_control(req,
3461                                         DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS);
3462         if (fix_links_control != NULL) {
3463                 struct dsdb_schema *schema = NULL;
3464                 const struct dsdb_attribute *sa = NULL;
3465
3466                 if (req->op.mod.message->num_elements != 1) {
3467                         return ldb_module_operr(module);
3468                 }
3469
3470                 if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_REPLACE) {
3471                         return ldb_module_operr(module);
3472                 }
3473
3474                 schema = dsdb_get_schema(ldb, req);
3475                 if (schema == NULL) {
3476                         return ldb_module_operr(module);
3477                 }
3478
3479                 sa = dsdb_attribute_by_lDAPDisplayName(schema,
3480                                 req->op.mod.message->elements[0].name);
3481                 if (sa == NULL) {
3482                         return ldb_module_operr(module);
3483                 }
3484
3485                 if (sa->linkID == 0) {
3486                         return ldb_module_operr(module);
3487                 }
3488
3489                 fix_links_control->critical = false;
3490                 return ldb_next_request(module, req);
3491         }
3492
3493         fix_dn_name_control = ldb_request_get_control(req,
3494                                         DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME);
3495         if (fix_dn_name_control != NULL) {
3496                 struct dsdb_schema *schema = NULL;
3497                 const struct dsdb_attribute *sa = NULL;
3498
3499                 if (req->op.mod.message->num_elements != 2) {
3500                         return ldb_module_operr(module);
3501                 }
3502
3503                 if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) {
3504                         return ldb_module_operr(module);
3505                 }
3506
3507                 if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) {
3508                         return ldb_module_operr(module);
3509                 }
3510
3511                 if (req->op.mod.message->elements[0].num_values != 1) {
3512                         return ldb_module_operr(module);
3513                 }
3514
3515                 if (req->op.mod.message->elements[1].num_values != 1) {
3516                         return ldb_module_operr(module);
3517                 }
3518
3519                 schema = dsdb_get_schema(ldb, req);
3520                 if (schema == NULL) {
3521                         return ldb_module_operr(module);
3522                 }
3523
3524                 if (ldb_attr_cmp(req->op.mod.message->elements[0].name,
3525                                  req->op.mod.message->elements[1].name) != 0) {
3526                         return ldb_module_operr(module);
3527                 }
3528
3529                 sa = dsdb_attribute_by_lDAPDisplayName(schema,
3530                                 req->op.mod.message->elements[0].name);
3531                 if (sa == NULL) {
3532                         return ldb_module_operr(module);
3533                 }
3534
3535                 if (sa->dn_format == DSDB_INVALID_DN) {
3536                         return ldb_module_operr(module);
3537                 }
3538
3539                 if (sa->linkID != 0) {
3540                         return ldb_module_operr(module);
3541                 }
3542
3543                 /*
3544                  * If we are run from dbcheck and we are not updating
3545                  * a link (as these would need to be sorted and so
3546                  * can't go via such a simple update, then do not
3547                  * trigger replicated updates and a new USN from this
3548                  * change, it wasn't a real change, just a new
3549                  * (correct) string DN
3550                  */
3551
3552                 fix_dn_name_control->critical = false;
3553                 return ldb_next_request(module, req);
3554         }
3555
3556         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
3557
3558         guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
3559         if (guid_el != NULL) {
3560                 ldb_set_errstring(ldb,
3561                                   "replmd_modify: it's not allowed to change the objectGUID!");
3562                 return LDB_ERR_CONSTRAINT_VIOLATION;
3563         }
3564
3565         ac = replmd_ctx_init(module, req);
3566         if (ac == NULL) {
3567                 return ldb_module_oom(module);
3568         }
3569
3570         functional_level = dsdb_functional_level(ldb);
3571
3572         /* we have to copy the message as the caller might have it as a const */
3573         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
3574         if (msg == NULL) {
3575                 ldb_oom(ldb);
3576                 talloc_free(ac);
3577                 return LDB_ERR_OPERATIONS_ERROR;
3578         }
3579
3580         fix_dn_sid_control = ldb_request_get_control(req,
3581                                         DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID);
3582         if (fix_dn_sid_control != NULL) {
3583                 const struct dsdb_attribute *sa = NULL;
3584
3585                 if (msg->num_elements != 1) {
3586                         talloc_free(ac);
3587                         return ldb_module_operr(module);
3588                 }
3589
3590                 if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) {
3591                         talloc_free(ac);
3592                         return ldb_module_operr(module);
3593                 }
3594
3595                 if (msg->elements[0].num_values != 1) {
3596                         talloc_free(ac);
3597                         return ldb_module_operr(module);
3598                 }
3599
3600                 sa = dsdb_attribute_by_lDAPDisplayName(ac->schema,
3601                                 msg->elements[0].name);
3602                 if (sa == NULL) {
3603                         talloc_free(ac);
3604                         return ldb_module_operr(module);
3605                 }
3606
3607                 if (sa->dn_format != DSDB_NORMAL_DN) {
3608                         talloc_free(ac);
3609                         return ldb_module_operr(module);
3610                 }
3611
3612                 fix_dn_sid_control->critical = false;
3613                 ac->fix_link_sid = true;
3614
3615                 goto handle_linked_attribs;
3616         }
3617
3618         ldb_msg_remove_attr(msg, "whenChanged");
3619         ldb_msg_remove_attr(msg, "uSNChanged");
3620
3621         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
3622
3623         ret = replmd_update_rpmd(module, ac->schema, req, NULL,
3624                                  msg, &ac->seq_num, t, is_schema_nc,
3625                                  &is_urgent, &rodc);
3626         if (rodc && (ret == LDB_ERR_REFERRAL)) {
3627                 ret = send_rodc_referral(req, ldb, msg->dn);
3628                 talloc_free(ac);
3629                 return ret;
3630
3631         }
3632
3633         if (ret != LDB_SUCCESS) {
3634                 talloc_free(ac);
3635                 return ret;
3636         }
3637
3638  handle_linked_attribs:
3639         ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3640                                                   ac, msg, t, req);
3641         if (ret != LDB_SUCCESS) {
3642                 talloc_free(ac);
3643                 return ret;
3644         }
3645
3646         /* TODO:
3647          * - replace the old object with the newly constructed one
3648          */
3649
3650         ac->is_urgent = is_urgent;
3651
3652         ret = ldb_build_mod_req(&down_req, ldb, ac,
3653                                 msg,
3654                                 req->controls,
3655                                 ac, replmd_op_callback,
3656                                 req);
3657         LDB_REQ_SET_LOCATION(down_req);
3658         if (ret != LDB_SUCCESS) {
3659                 talloc_free(ac);
3660                 return ret;
3661         }
3662
3663         /* current partition control is needed by "replmd_op_callback" */
3664         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
3665                 ret = ldb_request_add_control(down_req,
3666                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
3667                                               false, NULL);
3668                 if (ret != LDB_SUCCESS) {
3669                         talloc_free(ac);
3670                         return ret;
3671                 }
3672         }
3673
3674         /* If we are in functional level 2000, then
3675          * replmd_modify_handle_linked_attribs will have done
3676          * nothing */
3677         if (functional_level == DS_DOMAIN_FUNCTION_2000) {
3678                 ret = ldb_request_add_control(down_req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
3679                 if (ret != LDB_SUCCESS) {
3680                         talloc_free(ac);
3681                         return ret;
3682                 }
3683         }
3684
3685         talloc_steal(down_req, msg);
3686
3687         /* we only change whenChanged and uSNChanged if the seq_num
3688            has changed */
3689         if (ac->seq_num != 0) {
3690                 ret = add_time_element(msg, "whenChanged", t);
3691                 if (ret != LDB_SUCCESS) {
3692                         talloc_free(ac);
3693                         ldb_operr(ldb);
3694                         return ret;
3695                 }
3696
3697                 ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
3698                 if (ret != LDB_SUCCESS) {
3699                         talloc_free(ac);
3700                         ldb_operr(ldb);
3701                         return ret;
3702                 }
3703         }
3704
3705         /* go on with the call chain */
3706         return ldb_next_request(module, down_req);
3707 }
3708
3709 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares);
3710
3711 /*
3712   handle a rename request
3713
3714   On a rename we need to do an extra ldb_modify which sets the
3715   whenChanged and uSNChanged attributes.  We do this in a callback after the success.
3716  */
3717 static int replmd_rename(struct ldb_module *module, struct ldb_request *req)
3718 {
3719         struct ldb_context *ldb;
3720         struct replmd_replicated_request *ac;
3721         int ret;
3722         struct ldb_request *down_req;
3723
3724         /* do not manipulate our control entries */
3725         if (ldb_dn_is_special(req->op.mod.message->dn)) {
3726                 return ldb_next_request(module, req);
3727         }
3728
3729         ldb = ldb_module_get_ctx(module);
3730
3731         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_rename\n");
3732
3733         ac = replmd_ctx_init(module, req);
3734         if (ac == NULL) {
3735                 return ldb_module_oom(module);
3736         }
3737
3738         ret = ldb_build_rename_req(&down_req, ldb, ac,
3739                                    ac->req->op.rename.olddn,
3740                                    ac->req->op.rename.newdn,
3741                                    ac->req->controls,
3742                                    ac, replmd_rename_callback,
3743                                    ac->req);
3744         LDB_REQ_SET_LOCATION(down_req);
3745         if (ret != LDB_SUCCESS) {
3746                 talloc_free(ac);
3747                 return ret;
3748         }
3749
3750         /* go on with the call chain */
3751         return ldb_next_request(module, down_req);
3752 }
3753
3754 /* After the rename is compleated, update the whenchanged etc */
3755 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
3756 {
3757         struct ldb_context *ldb;
3758         struct ldb_request *down_req;
3759         struct ldb_message *msg;
3760         const struct dsdb_attribute *rdn_attr;
3761         const char *rdn_name;
3762         const struct ldb_val *rdn_val;
3763         const char *attrs[5] = { NULL, };
3764         time_t t = time(NULL);
3765         int ret;
3766         bool is_urgent = false, rodc = false;
3767         bool is_schema_nc;
3768         struct replmd_replicated_request *ac =
3769                 talloc_get_type(req->context, struct replmd_replicated_request);
3770         struct replmd_private *replmd_private =
3771                 talloc_get_type(ldb_module_get_private(ac->module),
3772                                 struct replmd_private);
3773
3774         ldb = ldb_module_get_ctx(ac->module);
3775
3776         if (ares->error != LDB_SUCCESS) {
3777                 return ldb_module_done(ac->req, ares->controls,
3778                                         ares->response, ares->error);
3779         }
3780
3781         if (ares->type != LDB_REPLY_DONE) {
3782                 ldb_set_errstring(ldb,
3783                                   "invalid ldb_reply_type in callback");
3784                 talloc_free(ares);
3785                 return ldb_module_done(ac->req, NULL, NULL,
3786                                         LDB_ERR_OPERATIONS_ERROR);
3787         }
3788
3789         /* TODO:
3790          * - replace the old object with the newly constructed one
3791          */
3792
3793         msg = ldb_msg_new(ac);
3794         if (msg == NULL) {
3795                 ldb_oom(ldb);
3796                 return LDB_ERR_OPERATIONS_ERROR;
3797         }
3798
3799         msg->dn = ac->req->op.rename.newdn;
3800
3801         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
3802
3803         rdn_name = ldb_dn_get_rdn_name(msg->dn);
3804         if (rdn_name == NULL) {
3805                 talloc_free(ares);
3806                 return ldb_module_done(ac->req, NULL, NULL,
3807                                        ldb_operr(ldb));
3808         }
3809
3810         /* normalize the rdn attribute name */
3811         rdn_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rdn_name);
3812         if (rdn_attr == NULL) {
3813                 talloc_free(ares);
3814                 return ldb_module_done(ac->req, NULL, NULL,
3815                                        ldb_operr(ldb));
3816         }
3817         rdn_name = rdn_attr->lDAPDisplayName;
3818
3819         rdn_val = ldb_dn_get_rdn_val(msg->dn);
3820         if (rdn_val == NULL) {
3821                 talloc_free(ares);
3822                 return ldb_module_done(ac->req, NULL, NULL,
3823                                        ldb_operr(ldb));
3824         }
3825
3826         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
3827                 talloc_free(ares);
3828                 return ldb_module_done(ac->req, NULL, NULL,
3829                                        ldb_oom(ldb));
3830         }
3831         if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
3832                 talloc_free(ares);
3833                 return ldb_module_done(ac->req, NULL, NULL,
3834                                        ldb_oom(ldb));
3835         }
3836         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
3837                 talloc_free(ares);
3838                 return ldb_module_done(ac->req, NULL, NULL,
3839                                        ldb_oom(ldb));
3840         }
3841         if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
3842                 talloc_free(ares);
3843                 return ldb_module_done(ac->req, NULL, NULL,
3844                                        ldb_oom(ldb));
3845         }
3846
3847         /*
3848          * here we let replmd_update_rpmd() only search for
3849          * the existing "replPropertyMetaData" and rdn_name attributes.
3850          *
3851          * We do not want the existing "name" attribute as
3852          * the "name" attribute needs to get the version
3853          * updated on rename even if the rdn value hasn't changed.
3854          *
3855          * This is the diff of the meta data, for a moved user
3856          * on a w2k8r2 server:
3857          *
3858          * # record 1
3859          * -dn: CN=sdf df,CN=Users,DC=bla,DC=base
3860          * +dn: CN=sdf df,OU=TestOU,DC=bla,DC=base
3861          *  replPropertyMetaData:     NDR: struct replPropertyMetaDataBlob
3862          *         version                  : 0x00000001 (1)
3863          *         reserved                 : 0x00000000 (0)
3864          * @@ -66,11 +66,11 @@ replPropertyMetaData:     NDR: struct re
3865          *                      local_usn                : 0x00000000000037a5 (14245)
3866          *                 array: struct replPropertyMetaData1
3867          *                      attid                    : DRSUAPI_ATTID_name (0x90001)
3868          * -                    version                  : 0x00000001 (1)
3869          * -                    originating_change_time  : Wed Feb  9 17:20:49 2011 CET
3870          * +                    version                  : 0x00000002 (2)
3871          * +                    originating_change_time  : Wed Apr  6 15:21:01 2011 CEST
3872          *                      originating_invocation_id: 0d36ca05-5507-4e62-aca3-354bab0d39e1
3873          * -                    originating_usn          : 0x00000000000037a5 (14245)
3874          * -                    local_usn                : 0x00000000000037a5 (14245)
3875          * +                    originating_usn          : 0x0000000000003834 (14388)
3876          * +                    local_usn                : 0x0000000000003834 (14388)
3877          *                 array: struct replPropertyMetaData1
3878          *                      attid                    : DRSUAPI_ATTID_userAccountControl (0x90008)
3879          *                      version                  : 0x00000004 (4)
3880          */
3881         attrs[0] = "replPropertyMetaData";
3882         attrs[1] = "objectClass";
3883         attrs[2] = "instanceType";
3884         attrs[3] = rdn_name;
3885         attrs[4] = NULL;
3886
3887         ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
3888                                  msg, &ac->seq_num, t,
3889                                  is_schema_nc, &is_urgent, &rodc);
3890         if (rodc && (ret == LDB_ERR_REFERRAL)) {
3891                 ret = send_rodc_referral(req, ldb, ac->req->op.rename.olddn);
3892                 talloc_free(ares);
3893                 return ldb_module_done(req, NULL, NULL, ret);
3894         }
3895
3896         if (ret != LDB_SUCCESS) {
3897                 talloc_free(ares);
3898                 return ldb_module_done(ac->req, NULL, NULL, ret);
3899         }
3900
3901         if (ac->seq_num == 0) {
3902                 talloc_free(ares);
3903                 return ldb_module_done(ac->req, NULL, NULL,
3904                                        ldb_error(ldb, ret,
3905                                         "internal error seq_num == 0"));
3906         }
3907         ac->is_urgent = is_urgent;
3908
3909         ret = ldb_build_mod_req(&down_req, ldb, ac,
3910                                 msg,
3911                                 req->controls,
3912                                 ac, replmd_op_callback,
3913                                 req);
3914         LDB_REQ_SET_LOCATION(down_req);
3915         if (ret != LDB_SUCCESS) {
3916                 talloc_free(ac);
3917                 return ret;
3918         }
3919
3920         /* current partition control is needed by "replmd_op_callback" */
3921         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
3922                 ret = ldb_request_add_control(down_req,
3923                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
3924                                               false, NULL);
3925                 if (ret != LDB_SUCCESS) {
3926                         talloc_free(ac);
3927                         return ret;
3928                 }
3929         }
3930
3931         talloc_steal(down_req, msg);
3932
3933         ret = add_time_element(msg, "whenChanged", t);
3934         if (ret != LDB_SUCCESS) {
3935                 talloc_free(ac);
3936                 ldb_operr(ldb);
3937                 return ret;
3938         }
3939
3940         ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
3941         if (ret != LDB_SUCCESS) {
3942                 talloc_free(ac);
3943                 ldb_operr(ldb);
3944                 return ret;
3945         }
3946
3947         /* go on with the call chain - do the modify after the rename */
3948         return ldb_next_request(ac->module, down_req);
3949 }
3950
3951 /*
3952  * remove links from objects that point at this object when an object
3953  * is deleted.  We remove it from the NEXT module per MS-DRSR 5.160
3954  * RemoveObj which states that link removal due to the object being
3955  * deleted is NOT an originating update - they just go away!
3956  *
3957  */
3958 static int replmd_delete_remove_link(struct ldb_module *module,
3959                                      const struct dsdb_schema *schema,
3960                                      struct replmd_private *replmd_private,
3961                                      struct ldb_dn *dn,
3962                                      struct GUID *guid,
3963                                      struct ldb_message_element *el,
3964                                      const struct dsdb_attribute *sa,
3965                                      struct ldb_request *parent)
3966 {
3967         unsigned int i;
3968         TALLOC_CTX *tmp_ctx = talloc_new(module);
3969         struct ldb_context *ldb = ldb_module_get_ctx(module);
3970
3971         for (i=0; i<el->num_values; i++) {
3972                 struct dsdb_dn *dsdb_dn;
3973                 int ret;
3974                 struct ldb_message *msg;
3975                 const struct dsdb_attribute *target_attr;
3976                 struct ldb_message_element *el2;
3977                 const char *dn_str;
3978                 struct ldb_val dn_val;
3979                 uint32_t dsdb_flags = 0;
3980                 const char *attrs[] = { NULL, NULL };
3981                 struct ldb_result *link_res;
3982                 struct ldb_message *link_msg;
3983                 struct ldb_message_element *link_el;
3984                 struct parsed_dn *link_dns;
3985                 struct parsed_dn *p = NULL, *unused = NULL;
3986
3987                 if (dsdb_dn_is_deleted_val(&el->values[i])) {
3988                         continue;
3989                 }
3990
3991                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], sa->syntax->ldap_oid);
3992                 if (!dsdb_dn) {
3993                         talloc_free(tmp_ctx);
3994                         return LDB_ERR_OPERATIONS_ERROR;
3995                 }
3996
3997                 /* remove the link */
3998                 msg = ldb_msg_new(tmp_ctx);
3999                 if (!msg) {
4000                         ldb_module_oom(module);
4001                         talloc_free(tmp_ctx);
4002                         return LDB_ERR_OPERATIONS_ERROR;
4003                 }
4004
4005
4006                 msg->dn = dsdb_dn->dn;
4007
4008                 target_attr = dsdb_attribute_by_linkID(schema, sa->linkID ^ 1);
4009                 if (target_attr == NULL) {
4010                         continue;
4011                 }
4012                 attrs[0] = target_attr->lDAPDisplayName;
4013
4014                 ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName,
4015                                         LDB_FLAG_MOD_DELETE, &el2);
4016                 if (ret != LDB_SUCCESS) {
4017                         ldb_module_oom(module);
4018                         talloc_free(tmp_ctx);
4019                         return LDB_ERR_OPERATIONS_ERROR;
4020                 }
4021
4022                 ret = dsdb_module_search_dn(module, tmp_ctx, &link_res,
4023                                             msg->dn, attrs,
4024                                             DSDB_FLAG_NEXT_MODULE |
4025                                             DSDB_SEARCH_SHOW_EXTENDED_DN |
4026                                             DSDB_SEARCH_SHOW_RECYCLED,
4027                                             parent);
4028
4029                 if (ret != LDB_SUCCESS) {
4030                         talloc_free(tmp_ctx);
4031                         return ret;
4032                 }
4033
4034                 link_msg = link_res->msgs[0];
4035                 link_el = ldb_msg_find_element(link_msg,
4036                                                target_attr->lDAPDisplayName);
4037                 if (link_el == NULL) {
4038                         talloc_free(tmp_ctx);
4039                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
4040                 }
4041
4042                 /*
4043                  * This call 'upgrades' the links in link_dns, but we
4044                  * do not commit the result back into the database, so
4045                  * this is safe to call in FL2000 or on databases that
4046                  * have been run at that level in the past.
4047                  */
4048                 ret = get_parsed_dns_trusted(module, replmd_private, tmp_ctx,
4049                                              link_el, &link_dns,
4050                                              target_attr->syntax->ldap_oid, parent);
4051                 if (ret != LDB_SUCCESS) {
4052                         talloc_free(tmp_ctx);
4053                         return ret;
4054                 }
4055
4056                 ret = parsed_dn_find(ldb, link_dns, link_el->num_values,
4057                                      guid, dn,
4058                                      data_blob_null, 0,
4059                                      &p, &unused,
4060                                      target_attr->syntax->ldap_oid, false);
4061                 if (ret != LDB_SUCCESS) {
4062                         talloc_free(tmp_ctx);
4063                         return ret;
4064                 }
4065
4066                 if (p == NULL) {
4067                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
4068                                                "Failed to find forward link on %s "
4069                                                "as %s to remove backlink %s on %s",
4070                                                ldb_dn_get_linearized(msg->dn),
4071                                                target_attr->lDAPDisplayName,
4072                                                sa->lDAPDisplayName,
4073                                                ldb_dn_get_linearized(dn));
4074                         talloc_free(tmp_ctx);
4075                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
4076                 }
4077
4078
4079                 /* This needs to get the Binary DN, by first searching */
4080                 dn_str = dsdb_dn_get_linearized(tmp_ctx,
4081                                                 p->dsdb_dn);
4082
4083                 dn_val = data_blob_string_const(dn_str);
4084                 el2->values = &dn_val;
4085                 el2->num_values = 1;
4086
4087                 /*
4088                  * Ensure that we tell the modification to vanish any linked
4089                  * attributes (not simply mark them as isDeleted = TRUE)
4090                  */
4091                 dsdb_flags |= DSDB_REPLMD_VANISH_LINKS;
4092
4093                 ret = dsdb_module_modify(module, msg, dsdb_flags|DSDB_FLAG_OWN_MODULE, parent);
4094                 if (ret != LDB_SUCCESS) {
4095                         talloc_free(tmp_ctx);
4096                         return ret;
4097                 }
4098         }
4099         talloc_free(tmp_ctx);
4100         return LDB_SUCCESS;
4101 }
4102
4103
4104 /*
4105   handle update of replication meta data for deletion of objects
4106
4107   This also handles the mapping of delete to a rename operation
4108   to allow deletes to be replicated.
4109
4110   It also handles the incoming deleted objects, to ensure they are
4111   fully deleted here.  In that case re_delete is true, and we do not
4112   use this as a signal to change the deleted state, just reinforce it.
4113
4114  */
4115 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete)
4116 {
4117         int ret = LDB_ERR_OTHER;
4118         bool retb, disallow_move_on_delete;
4119         struct ldb_dn *old_dn = NULL, *new_dn = NULL;
4120         const char *rdn_name;
4121         const struct ldb_val *rdn_value, *new_rdn_value;
4122         struct GUID guid;
4123         struct ldb_context *ldb = ldb_module_get_ctx(module);
4124         const struct dsdb_schema *schema;
4125         struct ldb_message *msg, *old_msg;
4126         struct ldb_message_element *el;
4127         TALLOC_CTX *tmp_ctx;
4128         struct ldb_result *res, *parent_res;
4129         static const char * const preserved_attrs[] = {
4130                 /* yes, this really is a hard coded list. See MS-ADTS
4131                    section 3.1.1.5.5.1.1 */
4132                 "attributeID",
4133                 "attributeSyntax",
4134                 "dNReferenceUpdate",
4135                 "dNSHostName",
4136                 "flatName",
4137                 "governsID",
4138                 "groupType",
4139                 "instanceType",
4140                 "lDAPDisplayName",
4141                 "legacyExchangeDN",
4142                 "isDeleted",
4143                 "isRecycled",
4144                 "lastKnownParent",
4145                 "msDS-LastKnownRDN",
4146                 "msDS-PortLDAP",
4147                 "mS-DS-CreatorSID",
4148                 "mSMQOwnerID",
4149                 "nCName",
4150                 "objectClass",
4151                 "distinguishedName",
4152                 "objectGUID",
4153                 "objectSid",
4154                 "oMSyntax",
4155                 "proxiedObjectName",
4156                 "name",
4157                 "nTSecurityDescriptor",
4158                 "replPropertyMetaData",
4159                 "sAMAccountName",
4160                 "securityIdentifier",
4161                 "sIDHistory",
4162                 "subClassOf",
4163                 "systemFlags",
4164                 "trustPartner",
4165                 "trustDirection",
4166                 "trustType",
4167                 "trustAttributes",
4168                 "userAccountControl",
4169                 "uSNChanged",
4170                 "uSNCreated",
4171                 "whenCreated",
4172                 "whenChanged",
4173                 NULL
4174         };
4175         static const char * const all_attrs[] = {
4176                 DSDB_SECRET_ATTRIBUTES,
4177                 "*",
4178                 NULL
4179         };
4180         static const struct ldb_val true_val = {
4181                 .data = discard_const_p(uint8_t, "TRUE"),
4182                 .length = 4
4183         };
4184         
4185         unsigned int i;
4186         uint32_t dsdb_flags = 0;
4187         struct replmd_private *replmd_private;
4188         enum deletion_state deletion_state, next_deletion_state;
4189
4190         if (ldb_dn_is_special(req->op.del.dn)) {
4191                 return ldb_next_request(module, req);
4192         }
4193
4194         /*
4195          * We have to allow dbcheck to remove an object that
4196          * is beyond repair, and to do so totally.  This could
4197          * mean we we can get a partial object from the other
4198          * DC, causing havoc, so dbcheck suggests
4199          * re-replication first.  dbcheck sets both DBCHECK
4200          * and RELAX in this situation.
4201          */
4202         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)
4203             && ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
4204                 /* really, really remove it */
4205                 return ldb_next_request(module, req);
4206         }
4207
4208         tmp_ctx = talloc_new(ldb);
4209         if (!tmp_ctx) {
4210                 ldb_oom(ldb);
4211                 return LDB_ERR_OPERATIONS_ERROR;
4212         }
4213
4214         schema = dsdb_get_schema(ldb, tmp_ctx);
4215         if (!schema) {
4216                 talloc_free(tmp_ctx);
4217                 return LDB_ERR_OPERATIONS_ERROR;
4218         }
4219
4220         old_dn = ldb_dn_copy(tmp_ctx, req->op.del.dn);
4221
4222         /* we need the complete msg off disk, so we can work out which
4223            attributes need to be removed */
4224         ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, all_attrs,
4225                                     DSDB_FLAG_NEXT_MODULE |
4226                                     DSDB_SEARCH_SHOW_RECYCLED |
4227                                     DSDB_SEARCH_REVEAL_INTERNALS |
4228                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req);
4229         if (ret != LDB_SUCCESS) {
4230                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
4231                                        "repmd_delete: Failed to %s %s, because we failed to find it: %s",
4232                                        re_delete ? "re-delete" : "delete",
4233                                        ldb_dn_get_linearized(old_dn),
4234                                        ldb_errstring(ldb_module_get_ctx(module)));
4235                 talloc_free(tmp_ctx);
4236                 return ret;
4237         }
4238         old_msg = res->msgs[0];
4239
4240         replmd_deletion_state(module, old_msg,
4241                               &deletion_state,
4242                               &next_deletion_state);
4243
4244         /* This supports us noticing an incoming isDeleted and acting on it */
4245         if (re_delete) {
4246                 SMB_ASSERT(deletion_state > OBJECT_NOT_DELETED);
4247                 next_deletion_state = deletion_state;
4248         }
4249
4250         if (next_deletion_state == OBJECT_REMOVED) {
4251                 /*
4252                  * We have to prevent objects being deleted, even if
4253                  * the administrator really wants them gone, as
4254                  * without the tombstone, we can get a partial object
4255                  * from the other DC, causing havoc.
4256                  *
4257                  * The only other valid case is when the 180 day
4258                  * timeout has expired, when relax is specified.
4259                  */
4260                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
4261                         /* it is already deleted - really remove it this time */
4262                         talloc_free(tmp_ctx);
4263                         return ldb_next_request(module, req);
4264                 }
4265
4266                 ldb_asprintf_errstring(ldb, "Refusing to delete tombstone object %s.  "
4267                                        "This check is to prevent corruption of the replicated state.",
4268                                        ldb_dn_get_linearized(old_msg->dn));
4269                 return LDB_ERR_UNWILLING_TO_PERFORM;
4270         }
4271
4272         rdn_name = ldb_dn_get_rdn_name(old_dn);
4273         rdn_value = ldb_dn_get_rdn_val(old_dn);
4274         if ((rdn_name == NULL) || (rdn_value == NULL)) {
4275                 talloc_free(tmp_ctx);
4276                 return ldb_operr(ldb);
4277         }
4278
4279         msg = ldb_msg_new(tmp_ctx);
4280         if (msg == NULL) {
4281                 ldb_module_oom(module);
4282                 talloc_free(tmp_ctx);
4283                 return LDB_ERR_OPERATIONS_ERROR;
4284         }
4285
4286         msg->dn = old_dn;
4287
4288         /* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */
4289         disallow_move_on_delete =
4290                 (ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0)
4291                  & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
4292
4293         /* work out where we will be renaming this object to */
4294         if (!disallow_move_on_delete) {
4295                 struct ldb_dn *deleted_objects_dn;
4296                 ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn,
4297                                                   &deleted_objects_dn);
4298
4299                 /*
4300                  * We should not move objects if we can't find the
4301                  * deleted objects DN.  Not moving (or otherwise
4302                  * harming) the Deleted Objects DN itself is handled
4303                  * in the caller.
4304                  */
4305                 if (re_delete && (ret != LDB_SUCCESS)) {
4306                         new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4307                         if (new_dn == NULL) {
4308                                 ldb_module_oom(module);
4309                                 talloc_free(tmp_ctx);
4310                                 return LDB_ERR_OPERATIONS_ERROR;
4311                         }
4312                 } else if (ret != LDB_SUCCESS) {
4313                         /* this is probably an attempted delete on a partition
4314                          * that doesn't allow delete operations, such as the
4315                          * schema partition */
4316                         ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s",
4317                                                ldb_dn_get_linearized(old_dn));
4318                         talloc_free(tmp_ctx);
4319                         return LDB_ERR_UNWILLING_TO_PERFORM;
4320                 } else {
4321                         new_dn = deleted_objects_dn;
4322                 }
4323         } else {
4324                 new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4325                 if (new_dn == NULL) {
4326                         ldb_module_oom(module);
4327                         talloc_free(tmp_ctx);
4328                         return LDB_ERR_OPERATIONS_ERROR;
4329                 }
4330         }
4331
4332         /* get the objects GUID from the search we just did */
4333         guid = samdb_result_guid(old_msg, "objectGUID");
4334
4335         if (deletion_state == OBJECT_NOT_DELETED) {
4336                 struct ldb_message_element *is_deleted_el;
4337
4338                 ret = replmd_make_deleted_child_dn(tmp_ctx,
4339                                                    ldb,
4340                                                    new_dn,
4341                                                    rdn_name, rdn_value,
4342                                                    guid);
4343
4344                 if (ret != LDB_SUCCESS) {
4345                         talloc_free(tmp_ctx);
4346                         return ret;
4347                 }
4348
4349                 ret = ldb_msg_add_value(msg, "isDeleted", &true_val,
4350                                         &is_deleted_el);
4351                 if (ret != LDB_SUCCESS) {
4352                         ldb_asprintf_errstring(ldb, __location__
4353                                                ": Failed to add isDeleted string to the msg");
4354                         talloc_free(tmp_ctx);
4355                         return ret;
4356                 }
4357                 is_deleted_el->flags = LDB_FLAG_MOD_REPLACE;
4358         } else {
4359                 /*
4360                  * No matter what has happened with other renames etc, try again to
4361                  * get this to be under the deleted DN. See MS-DRSR 5.160 RemoveObj
4362                  */
4363
4364                 struct ldb_dn *rdn = ldb_dn_copy(tmp_ctx, old_dn);
4365                 retb = ldb_dn_remove_base_components(rdn, ldb_dn_get_comp_num(rdn) - 1);
4366                 if (!retb) {
4367                         ldb_asprintf_errstring(ldb, __location__
4368                                                ": Unable to add a prepare rdn of %s",
4369                                                ldb_dn_get_linearized(rdn));
4370                         talloc_free(tmp_ctx);
4371                         return LDB_ERR_OPERATIONS_ERROR;
4372                 }
4373                 SMB_ASSERT(ldb_dn_get_comp_num(rdn) == 1);
4374
4375                 retb = ldb_dn_add_child(new_dn, rdn);
4376                 if (!retb) {
4377                         ldb_asprintf_errstring(ldb, __location__
4378                                                ": Unable to add rdn %s to base dn: %s",
4379                                                ldb_dn_get_linearized(rdn),
4380                                                ldb_dn_get_linearized(new_dn));
4381                         talloc_free(tmp_ctx);
4382                         return LDB_ERR_OPERATIONS_ERROR;
4383                 }
4384         }
4385
4386         /*
4387           now we need to modify the object in the following ways:
4388
4389           - add isDeleted=TRUE
4390           - update rDN and name, with new rDN
4391           - remove linked attributes
4392           - remove objectCategory and sAMAccountType
4393           - remove attribs not on the preserved list
4394              - preserved if in above list, or is rDN
4395           - remove all linked attribs from this object
4396           - remove all links from other objects to this object
4397             (note we use the backlinks to do this, so we won't find one-way
4398              links that still point to this object, or deactivated two-way
4399              links, i.e. 'member' after the user has been removed from the
4400              group)
4401           - add lastKnownParent
4402           - update replPropertyMetaData?
4403
4404           see MS-ADTS "Tombstone Requirements" section 3.1.1.5.5.1.1
4405          */
4406
4407         if (deletion_state == OBJECT_NOT_DELETED) {
4408                 struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4409                 char *parent_dn_str = NULL;
4410                 struct ldb_message_element *p_el;
4411
4412                 /* we need the storage form of the parent GUID */
4413                 ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
4414                                             parent_dn, NULL,
4415                                             DSDB_FLAG_NEXT_MODULE |
4416                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
4417                                             DSDB_SEARCH_REVEAL_INTERNALS|
4418                                             DSDB_SEARCH_SHOW_RECYCLED, req);
4419                 if (ret != LDB_SUCCESS) {
4420                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
4421                                                "repmd_delete: Failed to %s %s, "
4422                                                "because we failed to find it's parent (%s): %s",
4423                                                re_delete ? "re-delete" : "delete",
4424                                                ldb_dn_get_linearized(old_dn),
4425                                                ldb_dn_get_linearized(parent_dn),
4426                                                ldb_errstring(ldb_module_get_ctx(module)));
4427                         talloc_free(tmp_ctx);
4428                         return ret;
4429                 }
4430
4431                 /*
4432                  * Now we can use the DB version,
4433                  * it will have the extended DN info in it
4434                  */
4435                 parent_dn = parent_res->msgs[0]->dn;
4436                 parent_dn_str = ldb_dn_get_extended_linearized(tmp_ctx,
4437                                                                parent_dn,
4438                                                                1);
4439                 if (parent_dn_str == NULL) {
4440                         talloc_free(tmp_ctx);
4441                         return ldb_module_oom(module);
4442                 }
4443
4444                 ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
4445                                                parent_dn_str);
4446                 if (ret != LDB_SUCCESS) {
4447                         ldb_asprintf_errstring(ldb, __location__
4448                                                ": Failed to add lastKnownParent "
4449                                                "string when deleting %s",
4450                                                ldb_dn_get_linearized(old_dn));
4451                         talloc_free(tmp_ctx);
4452                         return ret;
4453                 }
4454                 p_el = ldb_msg_find_element(msg,
4455                                             "lastKnownParent");
4456                 if (p_el == NULL) {
4457                         talloc_free(tmp_ctx);
4458                         return ldb_module_operr(module);
4459                 }
4460                 p_el->flags = LDB_FLAG_MOD_REPLACE;
4461
4462                 if (next_deletion_state == OBJECT_DELETED) {
4463                         ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL);
4464                         if (ret != LDB_SUCCESS) {
4465                                 ldb_asprintf_errstring(ldb, __location__
4466                                                        ": Failed to add msDS-LastKnownRDN "
4467                                                        "string when deleting %s",
4468                                                        ldb_dn_get_linearized(old_dn));
4469                                 talloc_free(tmp_ctx);
4470                                 return ret;
4471                         }
4472                         p_el = ldb_msg_find_element(msg,
4473                                                     "msDS-LastKnownRDN");
4474                         if (p_el == NULL) {
4475                                 talloc_free(tmp_ctx);
4476                                 return ldb_module_operr(module);
4477                         }
4478                         p_el->flags = LDB_FLAG_MOD_ADD;
4479                 }
4480         }
4481
4482         switch (next_deletion_state) {
4483
4484         case OBJECT_RECYCLED:
4485         case OBJECT_TOMBSTONE:
4486
4487                 /*
4488                  * MS-ADTS 3.1.1.5.5.1.1 Tombstone Requirements
4489                  * describes what must be removed from a tombstone
4490                  * object
4491                  *
4492                  * MS-ADTS 3.1.1.5.5.1.3 Recycled-Object Requirements
4493                  * describes what must be removed from a recycled
4494                  * object
4495                  *
4496                  */
4497
4498                 /*
4499                  * we also mark it as recycled, meaning this object can't be
4500                  * recovered (we are stripping its attributes).
4501                  * This is done only if we have this schema object of course ...
4502                  * This behavior is identical to the one of Windows 2008R2 which
4503                  * always set the isRecycled attribute, even if the recycle-bin is
4504                  * not activated and what ever the forest level is.
4505                  */
4506                 if (dsdb_attribute_by_lDAPDisplayName(schema, "isRecycled") != NULL) {
4507                         struct ldb_message_element *is_recycled_el;
4508
4509                         ret = ldb_msg_add_value(msg, "isRecycled", &true_val,
4510                                                 &is_recycled_el);
4511                         if (ret != LDB_SUCCESS) {
4512                                 DEBUG(0,(__location__ ": Failed to add isRecycled string to the msg\n"));
4513                                 ldb_module_oom(module);
4514                                 talloc_free(tmp_ctx);
4515                                 return ret;
4516                         }
4517                         is_recycled_el->flags = LDB_FLAG_MOD_REPLACE;
4518                 }
4519
4520                 replmd_private = talloc_get_type(ldb_module_get_private(module),
4521                                                  struct replmd_private);
4522                 /* work out which of the old attributes we will be removing */
4523                 for (i=0; i<old_msg->num_elements; i++) {
4524                         const struct dsdb_attribute *sa;
4525                         el = &old_msg->elements[i];
4526                         sa = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
4527                         if (!sa) {
4528                                 talloc_free(tmp_ctx);
4529                                 return LDB_ERR_OPERATIONS_ERROR;
4530                         }
4531                         if (ldb_attr_cmp(el->name, rdn_name) == 0) {
4532                                 /* don't remove the rDN */
4533                                 continue;
4534                         }
4535
4536                         if (sa->linkID & 1) {
4537                                 /*
4538                                  * we have a backlink in this object
4539                                  * that needs to be removed. We're not
4540                                  * allowed to remove it directly
4541                                  * however, so we instead setup a
4542                                  * modify to delete the corresponding
4543                                  * forward link
4544                                  */
4545                                 ret = replmd_delete_remove_link(module, schema,
4546                                                                 replmd_private,
4547                                                                 old_dn, &guid,
4548                                                                 el, sa, req);
4549                                 if (ret == LDB_SUCCESS) {
4550                                         /*
4551                                          * now we continue, which means we
4552                                          * won't remove this backlink
4553                                          * directly
4554                                          */
4555                                         continue;
4556                                 }
4557
4558                                 if (ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
4559                                         const char *old_dn_str
4560                                                 = ldb_dn_get_linearized(old_dn);
4561                                         ldb_asprintf_errstring(ldb,
4562                                                                __location__
4563                                                                ": Failed to remove backlink of "
4564                                                                "%s when deleting %s: %s",
4565                                                                el->name,
4566                                                                old_dn_str,
4567                                                                ldb_errstring(ldb));
4568                                         talloc_free(tmp_ctx);
4569                                         return LDB_ERR_OPERATIONS_ERROR;
4570                                 }
4571
4572                                 /*
4573                                  * Otherwise vanish the link, we are
4574                                  * out of sync and the controlling
4575                                  * object does not have the source
4576                                  * link any more
4577                                  */
4578
4579                                 dsdb_flags |= DSDB_REPLMD_VANISH_LINKS;
4580
4581                         } else if (sa->linkID == 0) {
4582                                 if (ldb_attr_in_list(preserved_attrs, el->name)) {
4583                                         continue;
4584                                 }
4585                                 if (sa->searchFlags & SEARCH_FLAG_PRESERVEONDELETE) {
4586                                         continue;
4587                                 }
4588                         } else {
4589                                 /*
4590                                  * Ensure that we tell the modification to vanish any linked
4591                                  * attributes (not simply mark them as isDeleted = TRUE)
4592                                  */
4593                                 dsdb_flags |= DSDB_REPLMD_VANISH_LINKS;
4594                         }
4595                         ret = ldb_msg_add_empty(msg, el->name, LDB_FLAG_MOD_DELETE, &el);
4596                         if (ret != LDB_SUCCESS) {
4597                                 talloc_free(tmp_ctx);
4598                                 ldb_module_oom(module);
4599                                 return ret;
4600                         }
4601                 }
4602
4603                 break;
4604
4605         case OBJECT_DELETED:
4606                 /*
4607                  * MS-ADTS 3.1.1.5.5.1.2 Deleted-Object Requirements
4608                  * describes what must be removed from a deleted
4609                  * object
4610                  */
4611
4612                 ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_REPLACE, NULL);
4613                 if (ret != LDB_SUCCESS) {
4614                         talloc_free(tmp_ctx);
4615                         ldb_module_oom(module);
4616                         return ret;
4617                 }
4618
4619                 ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL);
4620                 if (ret != LDB_SUCCESS) {
4621                         talloc_free(tmp_ctx);
4622                         ldb_module_oom(module);
4623                         return ret;
4624                 }
4625
4626                 break;
4627
4628         default:
4629                 break;
4630         }
4631
4632         if (deletion_state == OBJECT_NOT_DELETED) {
4633                 const struct dsdb_attribute *sa;
4634
4635                 /* work out what the new rdn value is, for updating the
4636                    rDN and name fields */
4637                 new_rdn_value = ldb_dn_get_rdn_val(new_dn);
4638                 if (new_rdn_value == NULL) {
4639                         talloc_free(tmp_ctx);
4640                         return ldb_operr(ldb);
4641                 }
4642
4643                 sa = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
4644                 if (!sa) {
4645                         talloc_free(tmp_ctx);
4646                         return LDB_ERR_OPERATIONS_ERROR;
4647                 }
4648
4649                 ret = ldb_msg_add_value(msg, sa->lDAPDisplayName, new_rdn_value,
4650                                         &el);
4651                 if (ret != LDB_SUCCESS) {
4652                         talloc_free(tmp_ctx);
4653                         return ret;
4654                 }
4655                 el->flags = LDB_FLAG_MOD_REPLACE;
4656
4657                 el = ldb_msg_find_element(old_msg, "name");
4658                 if (el) {
4659                         ret = ldb_msg_add_value(msg, "name", new_rdn_value, &el);
4660                         if (ret != LDB_SUCCESS) {
4661                                 talloc_free(tmp_ctx);
4662                                 return ret;
4663                         }
4664                         el->flags = LDB_FLAG_MOD_REPLACE;
4665                 }
4666         }
4667
4668         /*
4669          * TODO: Per MS-DRSR 5.160 RemoveObj we should remove links directly, not as an originating update!
4670          *
4671          */
4672
4673         /*
4674          * No matter what has happned with other renames, try again to
4675          * get this to be under the deleted DN.
4676          */
4677         if (strcmp(ldb_dn_get_linearized(old_dn), ldb_dn_get_linearized(new_dn)) != 0) {
4678                 /* now rename onto the new DN */
4679                 ret = dsdb_module_rename(module, old_dn, new_dn, DSDB_FLAG_NEXT_MODULE, req);
4680                 if (ret != LDB_SUCCESS){
4681                         DEBUG(0,(__location__ ": Failed to rename object from '%s' to '%s' - %s\n",
4682                                  ldb_dn_get_linearized(old_dn),
4683                                  ldb_dn_get_linearized(new_dn),
4684                                  ldb_errstring(ldb)));
4685                         talloc_free(tmp_ctx);
4686                         return ret;
4687                 }
4688                 msg->dn = new_dn;
4689         }
4690
4691         ret = dsdb_module_modify(module, msg, dsdb_flags|DSDB_FLAG_OWN_MODULE, req);
4692         if (ret != LDB_SUCCESS) {
4693                 ldb_asprintf_errstring(ldb, "replmd_delete: Failed to modify object %s in delete - %s",
4694                                        ldb_dn_get_linearized(old_dn), ldb_errstring(ldb));
4695                 talloc_free(tmp_ctx);
4696                 return ret;
4697         }
4698
4699         talloc_free(tmp_ctx);
4700
4701         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
4702 }
4703
4704 static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
4705 {
4706         return replmd_delete_internals(module, req, false);
4707 }
4708
4709
4710 static int replmd_replicated_request_error(struct replmd_replicated_request *ar, int ret)
4711 {
4712         return ret;
4713 }
4714
4715 static int replmd_replicated_request_werror(struct replmd_replicated_request *ar, WERROR status)
4716 {
4717         int ret = LDB_ERR_OTHER;
4718         /* TODO: do some error mapping */
4719
4720         /* Let the caller know the full WERROR */
4721         ar->objs->error = status;
4722
4723         return ret;
4724 }
4725
4726
4727 static struct replPropertyMetaData1 *
4728 replmd_replPropertyMetaData1_find_attid(struct replPropertyMetaDataBlob *md_blob,
4729                                         enum drsuapi_DsAttributeId attid)
4730 {
4731         uint32_t i;
4732         struct replPropertyMetaDataCtr1 *rpmd_ctr = &md_blob->ctr.ctr1;
4733
4734         for (i = 0; i < rpmd_ctr->count; i++) {
4735                 if (rpmd_ctr->array[i].attid == attid) {
4736                         return &rpmd_ctr->array[i];
4737                 }
4738         }
4739         return NULL;
4740 }
4741
4742
4743 /*
4744    return true if an update is newer than an existing entry
4745    see section 5.11 of MS-ADTS
4746 */
4747 static bool replmd_update_is_newer(const struct GUID *current_invocation_id,
4748                                    const struct GUID *update_invocation_id,
4749                                    uint32_t current_version,
4750                                    uint32_t update_version,
4751                                    NTTIME current_change_time,
4752                                    NTTIME update_change_time)
4753 {
4754         if (update_version != current_version) {
4755                 return update_version > current_version;
4756         }
4757         if (update_change_time != current_change_time) {
4758                 return update_change_time > current_change_time;
4759         }
4760         return GUID_compare(update_invocation_id, current_invocation_id) > 0;
4761 }
4762
4763 static bool replmd_replPropertyMetaData1_is_newer(struct replPropertyMetaData1 *cur_m,
4764                                                   struct replPropertyMetaData1 *new_m)
4765 {
4766         return replmd_update_is_newer(&cur_m->originating_invocation_id,
4767                                       &new_m->originating_invocation_id,
4768                                       cur_m->version,
4769                                       new_m->version,
4770                                       cur_m->originating_change_time,
4771                                       new_m->originating_change_time);
4772 }
4773
4774 static bool replmd_replPropertyMetaData1_new_should_be_taken(uint32_t dsdb_repl_flags,
4775                                                              struct replPropertyMetaData1 *cur_m,
4776                                                              struct replPropertyMetaData1 *new_m)
4777 {
4778         bool cmp;
4779
4780         /*
4781          * If the new replPropertyMetaData entry for this attribute is
4782          * not provided (this happens in the case where we look for
4783          * ATTID_name, but the name was not changed), then the local
4784          * state is clearly still current, as the remote
4785          * server didn't send it due to being older the high watermark
4786          * USN we sent.
4787          */
4788         if (new_m == NULL) {
4789                 return false;
4790         }
4791
4792         if (dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING) {
4793                 /*
4794                  * if we compare equal then do an
4795                  * update. This is used when a client
4796                  * asks for a FULL_SYNC, and can be
4797                  * used to recover a corrupt
4798                  * replica.
4799                  *
4800                  * This call is a bit tricky, what we
4801                  * are doing it turning the 'is_newer'
4802                  * call into a 'not is older' by
4803                  * swapping cur_m and new_m, and negating the
4804                  * outcome.
4805                  */
4806                 cmp = !replmd_replPropertyMetaData1_is_newer(new_m,
4807                                                              cur_m);
4808         } else {
4809                 cmp = replmd_replPropertyMetaData1_is_newer(cur_m,
4810                                                             new_m);
4811         }
4812         return cmp;
4813 }
4814
4815
4816 /*
4817   form a DN for a deleted (DEL:) or conflict (CNF:) DN
4818  */
4819 static int replmd_make_prefix_child_dn(TALLOC_CTX *tmp_ctx,
4820                                        struct ldb_context *ldb,
4821                                        struct ldb_dn *dn,
4822                                        const char *four_char_prefix,
4823                                        const char *rdn_name,
4824                                        const struct ldb_val *rdn_value,
4825                                        struct GUID guid)
4826 {
4827         struct ldb_val deleted_child_rdn_val;
4828         struct GUID_txt_buf guid_str;
4829         int ret;
4830         bool retb;
4831
4832         GUID_buf_string(&guid, &guid_str);
4833
4834         retb = ldb_dn_add_child_fmt(dn, "X=Y");
4835         if (!retb) {
4836                 ldb_asprintf_errstring(ldb, __location__
4837                                        ": Unable to add a formatted child to dn: %s",
4838                                        ldb_dn_get_linearized(dn));
4839                 return LDB_ERR_OPERATIONS_ERROR;
4840         }
4841
4842         /*
4843          * TODO: Per MS-ADTS 3.1.1.5.5 Delete Operation
4844          * we should truncate this value to ensure the RDN is not more than 255 chars.
4845          *
4846          * However we MS-ADTS 3.1.1.5.1.2 Naming Constraints indicates that:
4847          *
4848          * "Naming constraints are not enforced for replicated
4849          * updates." so this is safe and we don't have to work out not
4850          * splitting a UTF8 char right now.
4851          */
4852         deleted_child_rdn_val = ldb_val_dup(tmp_ctx, rdn_value);
4853
4854         /*
4855          * sizeof(guid_str.buf) will always be longer than
4856          * strlen(guid_str.buf) but we allocate using this and
4857          * waste the trailing bytes to avoid scaring folks
4858          * with memcpy() using strlen() below
4859          */
4860
4861         deleted_child_rdn_val.data
4862                 = talloc_realloc(tmp_ctx, deleted_child_rdn_val.data,
4863                                  uint8_t,
4864                                  rdn_value->length + 5
4865                                  + sizeof(guid_str.buf));
4866         if (!deleted_child_rdn_val.data) {
4867                 ldb_asprintf_errstring(ldb, __location__
4868                                        ": Unable to add a formatted child to dn: %s",
4869                                        ldb_dn_get_linearized(dn));
4870                 return LDB_ERR_OPERATIONS_ERROR;
4871         }
4872
4873         deleted_child_rdn_val.length =
4874                 rdn_value->length + 5
4875                 + strlen(guid_str.buf);
4876
4877         SMB_ASSERT(deleted_child_rdn_val.length <
4878                    talloc_get_size(deleted_child_rdn_val.data));
4879
4880         /*
4881          * talloc won't allocate more than 256MB so we can't
4882          * overflow but just to be sure
4883          */
4884         if (deleted_child_rdn_val.length < rdn_value->length) {
4885                 return LDB_ERR_OPERATIONS_ERROR;
4886         }
4887
4888         deleted_child_rdn_val.data[rdn_value->length] = 0x0a;
4889         memcpy(&deleted_child_rdn_val.data[rdn_value->length + 1],
4890                four_char_prefix, 4);
4891         memcpy(&deleted_child_rdn_val.data[rdn_value->length + 5],
4892                guid_str.buf,
4893                sizeof(guid_str.buf));
4894
4895         /* Now set the value into the RDN, without parsing it */
4896         ret = ldb_dn_set_component(
4897                 dn,
4898                 0,
4899                 rdn_name,
4900                 deleted_child_rdn_val);
4901
4902         return ret;
4903 }
4904
4905
4906 /*
4907   form a conflict DN
4908  */
4909 static struct ldb_dn *replmd_conflict_dn(TALLOC_CTX *mem_ctx,
4910                                          struct ldb_context *ldb,
4911                                          struct ldb_dn *dn,
4912                                          struct GUID *guid)
4913 {
4914         const struct ldb_val *rdn_val;
4915         const char *rdn_name;
4916         struct ldb_dn *new_dn;
4917         int ret;
4918
4919         rdn_val = ldb_dn_get_rdn_val(dn);
4920         rdn_name = ldb_dn_get_rdn_name(dn);
4921         if (!rdn_val || !rdn_name) {
4922                 return NULL;
4923         }
4924
4925         new_dn = ldb_dn_get_parent(mem_ctx, dn);
4926         if (!new_dn) {
4927                 return NULL;
4928         }
4929
4930         ret = replmd_make_prefix_child_dn(mem_ctx,
4931                                           ldb, new_dn,
4932                                           "CNF:",
4933                                           rdn_name,
4934                                           rdn_val,
4935                                           *guid);
4936         if (ret != LDB_SUCCESS) {
4937                 return NULL;
4938         }
4939         return new_dn;
4940 }
4941
4942 /*
4943   form a deleted DN
4944  */
4945 static int replmd_make_deleted_child_dn(TALLOC_CTX *tmp_ctx,
4946                                         struct ldb_context *ldb,
4947                                         struct ldb_dn *dn,
4948                                         const char *rdn_name,
4949                                         const struct ldb_val *rdn_value,
4950                                         struct GUID guid)
4951 {
4952         return replmd_make_prefix_child_dn(tmp_ctx,
4953                                            ldb, dn,
4954                                            "DEL:",
4955                                            rdn_name,
4956                                            rdn_value,
4957                                            guid);
4958 }
4959
4960
4961 /*
4962   perform a modify operation which sets the rDN and name attributes to
4963   their current values. This has the effect of changing these
4964   attributes to have been last updated by the current DC. This is
4965   needed to ensure that renames performed as part of conflict
4966   resolution are propagated to other DCs
4967  */
4968 static int replmd_name_modify(struct replmd_replicated_request *ar,
4969                               struct ldb_request *req, struct ldb_dn *dn)
4970 {
4971         struct ldb_message *msg;
4972         const char *rdn_name;
4973         const struct ldb_val *rdn_val;
4974         const struct dsdb_attribute *rdn_attr;
4975         int ret;
4976
4977         msg = ldb_msg_new(req);
4978         if (msg == NULL) {
4979                 goto failed;
4980         }
4981         msg->dn = dn;
4982
4983         rdn_name = ldb_dn_get_rdn_name(dn);
4984         if (rdn_name == NULL) {
4985                 goto failed;
4986         }
4987
4988         /* normalize the rdn attribute name */
4989         rdn_attr = dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name);
4990         if (rdn_attr == NULL) {
4991                 goto failed;
4992         }
4993         rdn_name = rdn_attr->lDAPDisplayName;
4994
4995         rdn_val = ldb_dn_get_rdn_val(dn);
4996         if (rdn_val == NULL) {
4997                 goto failed;
4998         }
4999
5000         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
5001                 goto failed;
5002         }
5003         if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
5004                 goto failed;
5005         }
5006         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
5007                 goto failed;
5008         }
5009         if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
5010                 goto failed;
5011         }
5012
5013         /*
5014          * We have to mark this as a replicated update otherwise
5015          * schema_data may reject a rename in the schema partition
5016          */
5017
5018         ret = dsdb_module_modify(ar->module, msg,
5019                                  DSDB_FLAG_OWN_MODULE|DSDB_FLAG_REPLICATED_UPDATE,
5020                                  req);
5021         if (ret != LDB_SUCCESS) {
5022                 DEBUG(0,(__location__ ": Failed to modify rDN/name of DN being DRS renamed '%s' - %s",
5023                          ldb_dn_get_linearized(dn),
5024                          ldb_errstring(ldb_module_get_ctx(ar->module))));
5025                 return ret;
5026         }
5027
5028         talloc_free(msg);
5029
5030         return LDB_SUCCESS;
5031
5032 failed:
5033         talloc_free(msg);
5034         DEBUG(0,(__location__ ": Failed to setup modify rDN/name of DN being DRS renamed '%s'",
5035                  ldb_dn_get_linearized(dn)));
5036         return LDB_ERR_OPERATIONS_ERROR;
5037 }
5038
5039
5040 /*
5041   callback for conflict DN handling where we have renamed the incoming
5042   record. After renaming it, we need to ensure the change of name and
5043   rDN for the incoming record is seen as an originating update by this DC.
5044
5045   This also handles updating lastKnownParent for entries sent to lostAndFound
5046  */
5047 static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
5048 {
5049         struct replmd_replicated_request *ar =
5050                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
5051         struct ldb_dn *conflict_dn = NULL;
5052         int ret;
5053
5054         if (ares->error != LDB_SUCCESS) {
5055                 /* call the normal callback for everything except success */
5056                 return replmd_op_callback(req, ares);
5057         }
5058
5059         switch (req->operation) {
5060         case LDB_ADD:
5061                 conflict_dn = req->op.add.message->dn;
5062                 break;
5063         case LDB_MODIFY:
5064                 conflict_dn = req->op.mod.message->dn;
5065                 break;
5066         default:
5067                 smb_panic("replmd_op_name_modify_callback called in unknown circumstances");
5068         }
5069
5070         /* perform a modify of the rDN and name of the record */
5071         ret = replmd_name_modify(ar, req, conflict_dn);
5072         if (ret != LDB_SUCCESS) {
5073                 ares->error = ret;
5074                 return replmd_op_callback(req, ares);
5075         }
5076
5077         if (ar->objs->objects[ar->index_current].last_known_parent) {
5078                 struct ldb_message *msg = ldb_msg_new(req);
5079                 if (msg == NULL) {
5080                         ldb_module_oom(ar->module);
5081                         return LDB_ERR_OPERATIONS_ERROR;
5082                 }
5083
5084                 msg->dn = req->op.add.message->dn;
5085
5086                 ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
5087                                                ldb_dn_get_extended_linearized(msg, ar->objs->objects[ar->index_current].last_known_parent, 1));
5088                 if (ret != LDB_SUCCESS) {
5089                         DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n"));
5090                         ldb_module_oom(ar->module);
5091                         return ret;
5092                 }
5093                 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
5094
5095                 ret = dsdb_module_modify(ar->module, msg, DSDB_FLAG_OWN_MODULE, req);
5096                 if (ret != LDB_SUCCESS) {
5097                         DEBUG(0,(__location__ ": Failed to modify lastKnownParent of lostAndFound DN '%s' - %s",
5098                                  ldb_dn_get_linearized(msg->dn),
5099                                  ldb_errstring(ldb_module_get_ctx(ar->module))));
5100                         return ret;
5101                 }
5102                 TALLOC_FREE(msg);
5103         }
5104
5105         return replmd_op_callback(req, ares);
5106 }
5107
5108 /*
5109   callback for replmd_replicated_apply_add()
5110   This copes with the creation of conflict records in the case where
5111   the DN exists, but with a different objectGUID
5112  */
5113 static int replmd_op_possible_conflict_callback(struct ldb_request *req, struct ldb_reply *ares, int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
5114 {
5115         struct ldb_dn *conflict_dn;
5116         struct replmd_replicated_request *ar =
5117                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
5118         struct ldb_result *res;
5119         const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
5120         int ret;
5121         const struct ldb_val *omd_value;
5122         struct replPropertyMetaDataBlob omd, *rmd;
5123         enum ndr_err_code ndr_err;
5124         bool rename_incoming_record, rodc;
5125         struct replPropertyMetaData1 *rmd_name, *omd_name;
5126         struct ldb_message *msg;
5127         struct ldb_request *down_req = NULL;
5128
5129         /* call the normal callback for success */
5130         if (ares->error == LDB_SUCCESS) {
5131                 return callback(req, ares);
5132         }
5133
5134         /*
5135          * we have a conflict, and need to decide if we will keep the
5136          * new record or the old record
5137          */
5138
5139         msg = ar->objs->objects[ar->index_current].msg;
5140         conflict_dn = msg->dn;
5141
5142         /* For failures other than conflicts, fail the whole operation here */
5143         if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
5144                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote add of %s: %s",
5145                                        ldb_dn_get_linearized(conflict_dn),
5146                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
5147
5148                 return ldb_module_done(ar->req, NULL, NULL,
5149                                        LDB_ERR_OPERATIONS_ERROR);
5150         }
5151
5152         ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
5153         if (ret != LDB_SUCCESS) {
5154                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to determine if we are an RODC when attempting to form conflict DN: %s", ldb_errstring(ldb_module_get_ctx(ar->module)));
5155                 return ldb_module_done(ar->req, NULL, NULL,
5156                                        LDB_ERR_OPERATIONS_ERROR);
5157
5158         }
5159
5160         if (rodc) {
5161                 /*
5162                  * We are on an RODC, or were a GC for this
5163                  * partition, so we have to fail this until
5164                  * someone who owns the partition sorts it
5165                  * out
5166                  */
5167                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5168                                        "Conflict adding object '%s' from incoming replication as we are read only for the partition.  \n"
5169                                        " - We must fail the operation until a master for this partition resolves the conflict",
5170                                        ldb_dn_get_linearized(conflict_dn));
5171                 ret = LDB_ERR_OPERATIONS_ERROR;
5172                 goto failed;
5173         }
5174
5175         /*
5176          * first we need the replPropertyMetaData attribute from the
5177          * local, conflicting record
5178          */
5179         ret = dsdb_module_search_dn(ar->module, req, &res, conflict_dn,
5180                                     attrs,
5181                                     DSDB_FLAG_NEXT_MODULE |
5182                                     DSDB_SEARCH_SHOW_DELETED |
5183                                     DSDB_SEARCH_SHOW_RECYCLED, req);
5184         if (ret != LDB_SUCCESS) {
5185                 DEBUG(0,(__location__ ": Unable to find object for conflicting record '%s'\n",
5186                          ldb_dn_get_linearized(conflict_dn)));
5187                 goto failed;
5188         }
5189
5190         omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
5191         if (omd_value == NULL) {
5192                 DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for conflicting record '%s'\n",
5193                          ldb_dn_get_linearized(conflict_dn)));
5194                 goto failed;
5195         }
5196
5197         ndr_err = ndr_pull_struct_blob(omd_value, res->msgs[0], &omd,
5198                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
5199         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5200                 DEBUG(0,(__location__ ": Failed to parse old replPropertyMetaData for %s\n",
5201                          ldb_dn_get_linearized(conflict_dn)));
5202                 goto failed;
5203         }
5204
5205         rmd = ar->objs->objects[ar->index_current].meta_data;
5206
5207         /*
5208          * we decide which is newer based on the RPMD on the name
5209          * attribute.  See [MS-DRSR] ResolveNameConflict.
5210          *
5211          * We expect omd_name to be present, as this is from a local
5212          * search, but while rmd_name should have been given to us by
5213          * the remote server, if it is missing we just prefer the
5214          * local name in
5215          * replmd_replPropertyMetaData1_new_should_be_taken()
5216          */
5217         rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
5218         omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
5219         if (!omd_name) {
5220                 DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
5221                          ldb_dn_get_linearized(conflict_dn)));
5222                 goto failed;
5223         }
5224
5225         /*
5226          * Should we preserve the current record, and so rename the
5227          * incoming record to be a conflict?
5228          */
5229         rename_incoming_record
5230                 = !replmd_replPropertyMetaData1_new_should_be_taken(ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
5231                                                                     omd_name, rmd_name);
5232
5233         if (rename_incoming_record) {
5234                 struct GUID guid;
5235                 struct ldb_dn *new_dn;
5236
5237                 guid = samdb_result_guid(msg, "objectGUID");
5238                 if (GUID_all_zero(&guid)) {
5239                         DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
5240                                  ldb_dn_get_linearized(conflict_dn)));
5241                         goto failed;
5242                 }
5243                 new_dn = replmd_conflict_dn(req,
5244                                             ldb_module_get_ctx(ar->module),
5245                                             conflict_dn, &guid);
5246                 if (new_dn == NULL) {
5247                         DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
5248                                  ldb_dn_get_linearized(conflict_dn)));
5249                         goto failed;
5250                 }
5251
5252                 DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
5253                          ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
5254
5255                 /* re-submit the request, but with the new DN */
5256                 callback = replmd_op_name_modify_callback;
5257                 msg->dn = new_dn;
5258         } else {
5259                 /* we are renaming the existing record */
5260                 struct GUID guid;
5261                 struct ldb_dn *new_dn;
5262
5263                 guid = samdb_result_guid(res->msgs[0], "objectGUID");
5264                 if (GUID_all_zero(&guid)) {
5265                         DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
5266                                  ldb_dn_get_linearized(conflict_dn)));
5267                         goto failed;
5268                 }
5269
5270                 new_dn = replmd_conflict_dn(req,
5271                                             ldb_module_get_ctx(ar->module),
5272                                             conflict_dn, &guid);
5273                 if (new_dn == NULL) {
5274                         DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
5275                                  ldb_dn_get_linearized(conflict_dn)));
5276                         goto failed;
5277                 }
5278
5279                 DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
5280                          ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
5281
5282                 ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
5283                                          DSDB_FLAG_OWN_MODULE, req);
5284                 if (ret != LDB_SUCCESS) {
5285                         DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
5286                                  ldb_dn_get_linearized(conflict_dn),
5287                                  ldb_dn_get_linearized(new_dn),
5288                                  ldb_errstring(ldb_module_get_ctx(ar->module))));
5289                         goto failed;
5290                 }
5291
5292                 /*
5293                  * now we need to ensure that the rename is seen as an
5294                  * originating update. We do that with a modify.
5295                  */
5296                 ret = replmd_name_modify(ar, req, new_dn);
5297                 if (ret != LDB_SUCCESS) {
5298                         goto failed;
5299                 }
5300
5301                 DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated creation of '%s'\n",
5302                          ldb_dn_get_linearized(req->op.add.message->dn)));
5303         }
5304
5305         ret = ldb_build_add_req(&down_req,
5306                                 ldb_module_get_ctx(ar->module),
5307                                 req,
5308                                 msg,
5309                                 ar->controls,
5310                                 ar,
5311                                 callback,
5312                                 req);
5313         if (ret != LDB_SUCCESS) {
5314                 goto failed;
5315         }
5316         LDB_REQ_SET_LOCATION(down_req);
5317
5318         /* current partition control needed by "repmd_op_callback" */
5319         ret = ldb_request_add_control(down_req,
5320                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
5321                                       false, NULL);
5322         if (ret != LDB_SUCCESS) {
5323                 return replmd_replicated_request_error(ar, ret);
5324         }
5325
5326         if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
5327                 /* this tells the partition module to make it a
5328                    partial replica if creating an NC */
5329                 ret = ldb_request_add_control(down_req,
5330                                               DSDB_CONTROL_PARTIAL_REPLICA,
5331                                               false, NULL);
5332                 if (ret != LDB_SUCCESS) {
5333                         return replmd_replicated_request_error(ar, ret);
5334                 }
5335         }
5336
5337         /*
5338          * Finally we re-run the add, otherwise the new record won't
5339          * exist, as we are here because of that exact failure!
5340          */
5341         return ldb_next_request(ar->module, down_req);
5342 failed:
5343
5344         /* on failure make the caller get the error. This means
5345          * replication will stop with an error, but there is not much
5346          * else we can do.
5347          */
5348         if (ret == LDB_SUCCESS) {
5349                 ret = LDB_ERR_OPERATIONS_ERROR;
5350         }
5351         return ldb_module_done(ar->req, NULL, NULL,
5352                                ret);
5353 }
5354
5355 /*
5356   callback for replmd_replicated_apply_add()
5357   This copes with the creation of conflict records in the case where
5358   the DN exists, but with a different objectGUID
5359  */
5360 static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *ares)
5361 {
5362         struct replmd_replicated_request *ar =
5363                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
5364
5365         if (ar->objs->objects[ar->index_current].last_known_parent) {
5366                 /* This is like a conflict DN, where we put the object in LostAndFound
5367                    see MS-DRSR 4.1.10.6.10 FindBestParentObject */
5368                 return replmd_op_possible_conflict_callback(req, ares, replmd_op_name_modify_callback);
5369         }
5370
5371         return replmd_op_possible_conflict_callback(req, ares, replmd_op_callback);
5372 }
5373
5374 /*
5375   this is called when a new object comes in over DRS
5376  */
5377 static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
5378 {
5379         struct ldb_context *ldb;
5380         struct ldb_request *change_req;
5381         enum ndr_err_code ndr_err;
5382         struct ldb_message *msg;
5383         struct replPropertyMetaDataBlob *md;
5384         struct ldb_val md_value;
5385         unsigned int i;
5386         int ret;
5387         bool remote_isDeleted = false;
5388         bool is_schema_nc;
5389         NTTIME now;
5390         time_t t = time(NULL);
5391         const struct ldb_val *rdn_val;
5392         struct replmd_private *replmd_private =
5393                 talloc_get_type(ldb_module_get_private(ar->module),
5394                                 struct replmd_private);
5395         unix_to_nt_time(&now, t);
5396
5397         ldb = ldb_module_get_ctx(ar->module);
5398         msg = ar->objs->objects[ar->index_current].msg;
5399         md = ar->objs->objects[ar->index_current].meta_data;
5400         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
5401
5402         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
5403         if (ret != LDB_SUCCESS) {
5404                 return replmd_replicated_request_error(ar, ret);
5405         }
5406
5407         ret = dsdb_msg_add_guid(msg,
5408                                 &ar->objs->objects[ar->index_current].object_guid,
5409                                 "objectGUID");
5410         if (ret != LDB_SUCCESS) {
5411                 return replmd_replicated_request_error(ar, ret);
5412         }
5413
5414         ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed);
5415         if (ret != LDB_SUCCESS) {
5416                 return replmd_replicated_request_error(ar, ret);
5417         }
5418
5419         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ar->seq_num);
5420         if (ret != LDB_SUCCESS) {
5421                 return replmd_replicated_request_error(ar, ret);
5422         }
5423
5424         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num);
5425         if (ret != LDB_SUCCESS) {
5426                 return replmd_replicated_request_error(ar, ret);
5427         }
5428
5429         /* remove any message elements that have zero values */
5430         for (i=0; i<msg->num_elements; i++) {
5431                 struct ldb_message_element *el = &msg->elements[i];
5432
5433                 if (el->num_values == 0) {
5434                         if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) {
5435                                 ldb_asprintf_errstring(ldb, __location__
5436                                                        ": empty objectClass sent on %s, aborting replication\n",
5437                                                        ldb_dn_get_linearized(msg->dn));
5438                                 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION);
5439                         }
5440
5441                         DEBUG(4,(__location__ ": Removing attribute %s with num_values==0\n",
5442                                  el->name));
5443                         memmove(el, el+1, sizeof(*el)*(msg->num_elements - (i+1)));
5444                         msg->num_elements--;
5445                         i--;
5446                         continue;
5447                 }
5448         }
5449
5450         if (DEBUGLVL(8)) {
5451                 struct GUID_txt_buf guid_txt;
5452
5453                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
5454                                                            LDB_CHANGETYPE_ADD,
5455                                                            msg);
5456                 DEBUG(8, ("DRS replication add message of %s:\n%s\n",
5457                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
5458                           s));
5459                 talloc_free(s);
5460         } else if (DEBUGLVL(4)) {
5461                 struct GUID_txt_buf guid_txt;
5462                 DEBUG(4, ("DRS replication add DN of %s is %s\n",
5463                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
5464                           ldb_dn_get_linearized(msg->dn)));
5465         }
5466         remote_isDeleted = ldb_msg_find_attr_as_bool(msg,
5467                                                      "isDeleted", false);
5468
5469         /*
5470          * the meta data array is already sorted by the caller, except
5471          * for the RDN, which needs to be added.
5472          */
5473
5474
5475         rdn_val = ldb_dn_get_rdn_val(msg->dn);
5476         ret = replmd_update_rpmd_rdn_attr(ldb, msg, rdn_val, NULL,
5477                                           md, ar, now, is_schema_nc,
5478                                           false);
5479         if (ret != LDB_SUCCESS) {
5480                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl ADD: %s", __func__, ldb_errstring(ldb));
5481                 return replmd_replicated_request_error(ar, ret);
5482         }
5483
5484         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &md->ctr.ctr1, msg->dn);
5485         if (ret != LDB_SUCCESS) {
5486                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl ADD: %s", __func__, ldb_errstring(ldb));
5487                 return replmd_replicated_request_error(ar, ret);
5488         }
5489
5490         for (i=0; i < md->ctr.ctr1.count; i++) {
5491                 md->ctr.ctr1.array[i].local_usn = ar->seq_num;
5492         }
5493         ndr_err = ndr_push_struct_blob(&md_value, msg, md,
5494                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
5495         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5496                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
5497                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
5498         }
5499         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL);
5500         if (ret != LDB_SUCCESS) {
5501                 return replmd_replicated_request_error(ar, ret);
5502         }
5503
5504         replmd_ldb_message_sort(msg, ar->schema);
5505
5506         if (!remote_isDeleted) {
5507                 ret = dsdb_module_schedule_sd_propagation(ar->module,
5508                                                           ar->objs->partition_dn,
5509                                                           msg->dn, true);
5510                 if (ret != LDB_SUCCESS) {
5511                         return replmd_replicated_request_error(ar, ret);
5512                 }
5513         }
5514
5515         ar->isDeleted = remote_isDeleted;
5516
5517         ret = ldb_build_add_req(&change_req,
5518                                 ldb,
5519                                 ar,
5520                                 msg,
5521                                 ar->controls,
5522                                 ar,
5523                                 replmd_op_add_callback,
5524                                 ar->req);
5525         LDB_REQ_SET_LOCATION(change_req);
5526         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5527
5528         /* current partition control needed by "repmd_op_callback" */
5529         ret = ldb_request_add_control(change_req,
5530                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
5531                                       false, NULL);
5532         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5533
5534         if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
5535                 /* this tells the partition module to make it a
5536                    partial replica if creating an NC */
5537                 ret = ldb_request_add_control(change_req,
5538                                               DSDB_CONTROL_PARTIAL_REPLICA,
5539                                               false, NULL);
5540                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5541         }
5542
5543         return ldb_next_request(ar->module, change_req);
5544 }
5545
5546 static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request *req,
5547                                                               struct ldb_reply *ares)
5548 {
5549         struct replmd_replicated_request *ar = talloc_get_type(req->context,
5550                                                struct replmd_replicated_request);
5551         int ret;
5552
5553         if (!ares) {
5554                 return ldb_module_done(ar->req, NULL, NULL,
5555                                         LDB_ERR_OPERATIONS_ERROR);
5556         }
5557
5558         /*
5559          * The error NO_SUCH_OBJECT is not expected, unless the search
5560          * base is the partition DN, and that case doesn't happen here
5561          * because then we wouldn't get a parent_guid_value in any
5562          * case.
5563          */
5564         if (ares->error != LDB_SUCCESS) {
5565                 return ldb_module_done(ar->req, ares->controls,
5566                                         ares->response, ares->error);
5567         }
5568
5569         switch (ares->type) {
5570         case LDB_REPLY_ENTRY:
5571         {
5572                 struct ldb_message *parent_msg = ares->message;
5573                 struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
5574                 struct ldb_dn *parent_dn = NULL;
5575                 int comp_num;
5576
5577                 if (!ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")
5578                     && ldb_msg_check_string_attribute(parent_msg, "isDeleted", "TRUE")) {
5579                         /* Per MS-DRSR 4.1.10.6.10
5580                          * FindBestParentObject we need to move this
5581                          * new object under a deleted object to
5582                          * lost-and-found */
5583                         struct ldb_dn *nc_root;
5584
5585                         ret = dsdb_find_nc_root(ldb_module_get_ctx(ar->module), msg, msg->dn, &nc_root);
5586                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
5587                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5588                                                        "No suitable NC root found for %s.  "
5589                                                        "We need to move this object because parent object %s "
5590                                                        "is deleted, but this object is not.",
5591                                                        ldb_dn_get_linearized(msg->dn),
5592                                                        ldb_dn_get_linearized(parent_msg->dn));
5593                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5594                         } else if (ret != LDB_SUCCESS) {
5595                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5596                                                        "Unable to find NC root for %s: %s. "
5597                                                        "We need to move this object because parent object %s "
5598                                                        "is deleted, but this object is not.",
5599                                                        ldb_dn_get_linearized(msg->dn),
5600                                                        ldb_errstring(ldb_module_get_ctx(ar->module)),
5601                                                        ldb_dn_get_linearized(parent_msg->dn));
5602                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5603                         }
5604
5605                         ret = dsdb_wellknown_dn(ldb_module_get_ctx(ar->module), msg,
5606                                                 nc_root,
5607                                                 DS_GUID_LOSTANDFOUND_CONTAINER,
5608                                                 &parent_dn);
5609                         if (ret != LDB_SUCCESS) {
5610                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5611                                                        "Unable to find LostAndFound Container for %s "
5612                                                        "in partition %s: %s. "
5613                                                        "We need to move this object because parent object %s "
5614                                                        "is deleted, but this object is not.",
5615                                                        ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(nc_root),
5616                                                        ldb_errstring(ldb_module_get_ctx(ar->module)),
5617                                                        ldb_dn_get_linearized(parent_msg->dn));
5618                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5619                         }
5620                         ar->objs->objects[ar->index_current].last_known_parent
5621                                 = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
5622
5623                 } else {
5624                         parent_dn
5625                                 = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
5626
5627                 }
5628                 ar->objs->objects[ar->index_current].local_parent_dn = parent_dn;
5629
5630                 comp_num = ldb_dn_get_comp_num(msg->dn);
5631                 if (comp_num > 1) {
5632                         if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) {
5633                                 talloc_free(ares);
5634                                 return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
5635                         }
5636                 }
5637                 if (!ldb_dn_add_base(msg->dn, parent_dn)) {
5638                         talloc_free(ares);
5639                         return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
5640                 }
5641                 break;
5642         }
5643         case LDB_REPLY_REFERRAL:
5644                 /* we ignore referrals */
5645                 break;
5646
5647         case LDB_REPLY_DONE:
5648
5649                 if (ar->objs->objects[ar->index_current].local_parent_dn == NULL) {
5650                         struct GUID_txt_buf str_buf;
5651                         if (ar->search_msg != NULL) {
5652                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5653                                                        "No parent with GUID %s found for object locally known as %s",
5654                                                        GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
5655                                                        ldb_dn_get_linearized(ar->search_msg->dn));
5656                         } else {
5657                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5658                                                        "No parent with GUID %s found for object remotely known as %s",
5659                                                        GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
5660                                                        ldb_dn_get_linearized(ar->objs->objects[ar->index_current].msg->dn));
5661                         }
5662
5663                         /*
5664                          * This error code is really important, as it
5665                          * is the flag back to the callers to retry
5666                          * this with DRSUAPI_DRS_GET_ANC, and so get
5667                          * the parent objects before the child
5668                          * objects
5669                          */
5670                         return ldb_module_done(ar->req, NULL, NULL,
5671                                                replmd_replicated_request_werror(ar, WERR_DS_DRA_MISSING_PARENT));
5672                 }
5673
5674                 if (ar->search_msg != NULL) {
5675                         ret = replmd_replicated_apply_merge(ar);
5676                 } else {
5677                         ret = replmd_replicated_apply_add(ar);
5678                 }
5679                 if (ret != LDB_SUCCESS) {
5680                         return ldb_module_done(ar->req, NULL, NULL, ret);
5681                 }
5682         }
5683
5684         talloc_free(ares);
5685         return LDB_SUCCESS;
5686 }
5687
5688 /*
5689  * Look for the parent object, so we put the new object in the right
5690  * place This is akin to NameObject in MS-DRSR - this routine and the
5691  * callbacks find the right parent name, and correct name for this
5692  * object
5693  */
5694
5695 static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_request *ar)
5696 {
5697         struct ldb_context *ldb;
5698         int ret;
5699         char *tmp_str;
5700         char *filter;
5701         struct ldb_request *search_req;
5702         static const char *attrs[] = {"isDeleted", NULL};
5703         struct GUID_txt_buf guid_str_buf;
5704
5705         ldb = ldb_module_get_ctx(ar->module);
5706
5707         if (ar->objs->objects[ar->index_current].parent_guid == NULL) {
5708                 if (ar->search_msg != NULL) {
5709                         return replmd_replicated_apply_merge(ar);
5710                 } else {
5711                         return replmd_replicated_apply_add(ar);
5712                 }
5713         }
5714
5715         tmp_str = GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
5716                                   &guid_str_buf);
5717
5718         filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
5719         if (!filter) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
5720
5721         ret = ldb_build_search_req(&search_req,
5722                                    ldb,
5723                                    ar,
5724                                    ar->objs->partition_dn,
5725                                    LDB_SCOPE_SUBTREE,
5726                                    filter,
5727                                    attrs,
5728                                    NULL,
5729                                    ar,
5730                                    replmd_replicated_apply_search_for_parent_callback,
5731                                    ar->req);
5732         LDB_REQ_SET_LOCATION(search_req);
5733
5734         ret = dsdb_request_add_controls(search_req,
5735                                         DSDB_SEARCH_SHOW_RECYCLED|
5736                                         DSDB_SEARCH_SHOW_DELETED|
5737                                         DSDB_SEARCH_SHOW_EXTENDED_DN);
5738         if (ret != LDB_SUCCESS) {
5739                 return ret;
5740         }
5741
5742         return ldb_next_request(ar->module, search_req);
5743 }
5744
5745 /*
5746   handle renames that come in over DRS replication
5747  */
5748 static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar,
5749                                            struct ldb_message *msg,
5750                                            struct ldb_request *parent,
5751                                            bool *renamed)
5752 {
5753         int ret;
5754         TALLOC_CTX *tmp_ctx = talloc_new(msg);
5755         struct ldb_result *res;
5756         struct ldb_dn *conflict_dn;
5757         const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
5758         const struct ldb_val *omd_value;
5759         struct replPropertyMetaDataBlob omd, *rmd;
5760         enum ndr_err_code ndr_err;
5761         bool rename_incoming_record, rodc;
5762         struct replPropertyMetaData1 *rmd_name, *omd_name;
5763         struct ldb_dn *new_dn;
5764         struct GUID guid;
5765
5766         DEBUG(4,("replmd_replicated_request rename %s => %s\n",
5767                  ldb_dn_get_linearized(ar->search_msg->dn),
5768                  ldb_dn_get_linearized(msg->dn)));
5769
5770
5771         ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
5772                                  DSDB_FLAG_NEXT_MODULE, ar->req);
5773         if (ret == LDB_SUCCESS) {
5774                 talloc_free(tmp_ctx);
5775                 *renamed = true;
5776                 return ret;
5777         }
5778
5779         if (ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
5780                 talloc_free(tmp_ctx);
5781                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote rename from %s to %s: %s",
5782                                        ldb_dn_get_linearized(ar->search_msg->dn),
5783                                        ldb_dn_get_linearized(msg->dn),
5784                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
5785                 return ret;
5786         }
5787
5788         ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
5789         if (ret != LDB_SUCCESS) {
5790                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5791                                        "Failed to determine if we are an RODC when attempting to form conflict DN: %s",
5792                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
5793                 return LDB_ERR_OPERATIONS_ERROR;
5794         }
5795         /*
5796          * we have a conflict, and need to decide if we will keep the
5797          * new record or the old record
5798          */
5799
5800         conflict_dn = msg->dn;
5801
5802         if (rodc) {
5803                 /*
5804                  * We are on an RODC, or were a GC for this
5805                  * partition, so we have to fail this until
5806                  * someone who owns the partition sorts it
5807                  * out
5808                  */
5809                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5810                                        "Conflict adding object '%s' from incoming replication but we are read only for the partition.  \n"
5811                                        " - We must fail the operation until a master for this partition resolves the conflict",
5812                                        ldb_dn_get_linearized(conflict_dn));
5813                 ret = LDB_ERR_OPERATIONS_ERROR;
5814                 goto failed;
5815         }
5816
5817         /*
5818          * first we need the replPropertyMetaData attribute from the
5819          * old record
5820          */
5821         ret = dsdb_module_search_dn(ar->module, tmp_ctx, &res, conflict_dn,
5822                                     attrs,
5823                                     DSDB_FLAG_NEXT_MODULE |
5824                                     DSDB_SEARCH_SHOW_DELETED |
5825                                     DSDB_SEARCH_SHOW_RECYCLED, ar->req);
5826         if (ret != LDB_SUCCESS) {
5827                 DEBUG(0,(__location__ ": Unable to find object for conflicting record '%s'\n",
5828                          ldb_dn_get_linearized(conflict_dn)));
5829                 goto failed;
5830         }
5831
5832         omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
5833         if (omd_value == NULL) {
5834                 DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for conflicting record '%s'\n",
5835                          ldb_dn_get_linearized(conflict_dn)));
5836                 goto failed;
5837         }
5838
5839         ndr_err = ndr_pull_struct_blob(omd_value, res->msgs[0], &omd,
5840                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
5841         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5842                 DEBUG(0,(__location__ ": Failed to parse old replPropertyMetaData for %s\n",
5843                          ldb_dn_get_linearized(conflict_dn)));
5844                 goto failed;
5845         }
5846
5847         rmd = ar->objs->objects[ar->index_current].meta_data;
5848
5849         /*
5850          * we decide which is newer based on the RPMD on the name
5851          * attribute.  See [MS-DRSR] ResolveNameConflict.
5852          *
5853          * We expect omd_name to be present, as this is from a local
5854          * search, but while rmd_name should have been given to us by
5855          * the remote server, if it is missing we just prefer the
5856          * local name in
5857          * replmd_replPropertyMetaData1_new_should_be_taken()
5858          */
5859         rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
5860         omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
5861         if (!omd_name) {
5862                 DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
5863                          ldb_dn_get_linearized(conflict_dn)));
5864                 goto failed;
5865         }
5866
5867         /*
5868          * Should we preserve the current record, and so rename the
5869          * incoming record to be a conflict?
5870          */
5871         rename_incoming_record =
5872                 !replmd_replPropertyMetaData1_new_should_be_taken(
5873                         ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
5874                         omd_name, rmd_name);
5875
5876         if (rename_incoming_record) {
5877
5878                 new_dn = replmd_conflict_dn(msg,
5879                                             ldb_module_get_ctx(ar->module),
5880                                             msg->dn,
5881                                             &ar->objs->objects[ar->index_current].object_guid);
5882                 if (new_dn == NULL) {
5883                         ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5884                                                                   "Failed to form conflict DN for %s\n",
5885                                                                   ldb_dn_get_linearized(msg->dn));
5886
5887                         return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
5888                 }
5889
5890                 ret = dsdb_module_rename(ar->module, ar->search_msg->dn, new_dn,
5891                                          DSDB_FLAG_NEXT_MODULE, ar->req);
5892                 if (ret != LDB_SUCCESS) {
5893                         ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5894                                                "Failed to rename incoming conflicting dn '%s' (was '%s') to '%s' - %s\n",
5895                                                ldb_dn_get_linearized(conflict_dn),
5896                                                ldb_dn_get_linearized(ar->search_msg->dn),
5897                                                ldb_dn_get_linearized(new_dn),
5898                                                ldb_errstring(ldb_module_get_ctx(ar->module)));
5899                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
5900                 }
5901
5902                 msg->dn = new_dn;
5903                 *renamed = true;
5904                 return LDB_SUCCESS;
5905         }
5906
5907         /* we are renaming the existing record */
5908
5909         guid = samdb_result_guid(res->msgs[0], "objectGUID");
5910         if (GUID_all_zero(&guid)) {
5911                 DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
5912                          ldb_dn_get_linearized(conflict_dn)));
5913                 goto failed;
5914         }
5915
5916         new_dn = replmd_conflict_dn(tmp_ctx,
5917                                     ldb_module_get_ctx(ar->module),
5918                                     conflict_dn, &guid);
5919         if (new_dn == NULL) {
5920                 DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
5921                          ldb_dn_get_linearized(conflict_dn)));
5922                 goto failed;
5923         }
5924
5925         DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
5926                  ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
5927
5928         ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
5929                                  DSDB_FLAG_OWN_MODULE, ar->req);
5930         if (ret != LDB_SUCCESS) {
5931                 DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
5932                          ldb_dn_get_linearized(conflict_dn),
5933                          ldb_dn_get_linearized(new_dn),
5934                          ldb_errstring(ldb_module_get_ctx(ar->module))));
5935                 goto failed;
5936         }
5937
5938         /*
5939          * now we need to ensure that the rename is seen as an
5940          * originating update. We do that with a modify.
5941          */
5942         ret = replmd_name_modify(ar, ar->req, new_dn);
5943         if (ret != LDB_SUCCESS) {
5944                 goto failed;
5945         }
5946
5947         DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated rename '%s' -> '%s'\n",
5948                  ldb_dn_get_linearized(ar->search_msg->dn),
5949                  ldb_dn_get_linearized(msg->dn)));
5950
5951
5952         ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
5953                                  DSDB_FLAG_NEXT_MODULE, ar->req);
5954         if (ret != LDB_SUCCESS) {
5955                 DEBUG(0,(__location__ ": After conflict resolution, failed to rename dn '%s' to '%s' - %s\n",
5956                          ldb_dn_get_linearized(ar->search_msg->dn),
5957                          ldb_dn_get_linearized(msg->dn),
5958                          ldb_errstring(ldb_module_get_ctx(ar->module))));
5959                         goto failed;
5960         }
5961
5962         talloc_free(tmp_ctx);
5963         return ret;
5964 failed:
5965         /*
5966          * On failure make the caller get the error
5967          * This means replication will stop with an error,
5968          * but there is not much else we can do.  In the
5969          * LDB_ERR_ENTRY_ALREADY_EXISTS case this is exactly what is
5970          * needed.
5971          */
5972         if (ret == LDB_SUCCESS) {
5973                 ret = LDB_ERR_OPERATIONS_ERROR;
5974         }
5975
5976         talloc_free(tmp_ctx);
5977         return ret;
5978 }
5979
5980
5981 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
5982 {
5983         struct ldb_context *ldb;
5984         struct ldb_request *change_req;
5985         enum ndr_err_code ndr_err;
5986         struct ldb_message *msg;
5987         struct replPropertyMetaDataBlob *rmd;
5988         struct replPropertyMetaDataBlob omd;
5989         const struct ldb_val *omd_value;
5990         struct replPropertyMetaDataBlob nmd;
5991         struct ldb_val nmd_value;
5992         struct GUID remote_parent_guid;
5993         unsigned int i;
5994         uint32_t j,ni=0;
5995         unsigned int removed_attrs = 0;
5996         int ret;
5997         int (*callback)(struct ldb_request *req, struct ldb_reply *ares) = replmd_op_callback;
5998         bool isDeleted = false;
5999         bool local_isDeleted = false;
6000         bool remote_isDeleted = false;
6001         bool take_remote_isDeleted = false;
6002         bool sd_updated = false;
6003         bool renamed = false;
6004         bool is_schema_nc = false;
6005         NTSTATUS nt_status;
6006         const struct ldb_val *old_rdn, *new_rdn;
6007         struct replmd_private *replmd_private =
6008                 talloc_get_type(ldb_module_get_private(ar->module),
6009                                 struct replmd_private);
6010         NTTIME now;
6011         time_t t = time(NULL);
6012         unix_to_nt_time(&now, t);
6013
6014         ldb = ldb_module_get_ctx(ar->module);
6015         msg = ar->objs->objects[ar->index_current].msg;
6016
6017         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
6018
6019         rmd = ar->objs->objects[ar->index_current].meta_data;
6020         ZERO_STRUCT(omd);
6021         omd.version = 1;
6022
6023         /* find existing meta data */
6024         omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData");
6025         if (omd_value) {
6026                 ndr_err = ndr_pull_struct_blob(omd_value, ar, &omd,
6027                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
6028                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6029                         nt_status = ndr_map_error2ntstatus(ndr_err);
6030                         return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6031                 }
6032
6033                 if (omd.version != 1) {
6034                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6035                 }
6036         }
6037
6038         if (DEBUGLVL(8)) {
6039                 struct GUID_txt_buf guid_txt;
6040
6041                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
6042                                                            LDB_CHANGETYPE_MODIFY, msg);
6043                 DEBUG(8, ("Initial DRS replication modify message of %s is:\n%s\n"
6044                           "%s\n"
6045                           "%s\n",
6046                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
6047                           s,
6048                           ndr_print_struct_string(s,
6049                                                   (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
6050                                                   "existing replPropertyMetaData",
6051                                                   &omd),
6052                           ndr_print_struct_string(s,
6053                                                   (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
6054                                                   "incoming replPropertyMetaData",
6055                                                   rmd)));
6056                 talloc_free(s);
6057         } else if (DEBUGLVL(4)) {
6058                 struct GUID_txt_buf guid_txt;
6059
6060                 DEBUG(4, ("Initial DRS replication modify DN of %s is: %s\n",
6061                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
6062                                           &guid_txt),
6063                           ldb_dn_get_linearized(msg->dn)));
6064         }
6065                 
6066         local_isDeleted = ldb_msg_find_attr_as_bool(ar->search_msg,
6067                                                     "isDeleted", false);
6068         remote_isDeleted = ldb_msg_find_attr_as_bool(msg,
6069                                                      "isDeleted", false);
6070
6071         /*
6072          * Fill in the remote_parent_guid with the GUID or an all-zero
6073          * GUID.
6074          */
6075         if (ar->objs->objects[ar->index_current].parent_guid != NULL) {
6076                 remote_parent_guid = *ar->objs->objects[ar->index_current].parent_guid;
6077         } else {
6078                 remote_parent_guid = GUID_zero();
6079         }
6080
6081         /*
6082          * To ensure we follow a complex rename chain around, we have
6083          * to confirm that the DN is the same (mostly to confirm the
6084          * RDN) and the parentGUID is the same.
6085          *
6086          * This ensures we keep things under the correct parent, which
6087          * replmd_replicated_handle_rename() will do.
6088          */
6089
6090         if (strcmp(ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(ar->search_msg->dn)) == 0
6091             && GUID_equal(&remote_parent_guid, &ar->local_parent_guid)) {
6092                 ret = LDB_SUCCESS;
6093         } else {
6094                 /*
6095                  * handle renames, even just by case that come in over
6096                  * DRS.  Changes in the parent DN don't hit us here,
6097                  * because the search for a parent will clean up those
6098                  * components.
6099                  *
6100                  * We also have already filtered out the case where
6101                  * the peer has an older name to what we have (see
6102                  * replmd_replicated_apply_search_callback())
6103                  */
6104                 ret = replmd_replicated_handle_rename(ar, msg, ar->req, &renamed);
6105         }
6106
6107         if (ret != LDB_SUCCESS) {
6108                 ldb_debug(ldb, LDB_DEBUG_FATAL,
6109                           "replmd_replicated_request rename %s => %s failed - %s\n",
6110                           ldb_dn_get_linearized(ar->search_msg->dn),
6111                           ldb_dn_get_linearized(msg->dn),
6112                           ldb_errstring(ldb));
6113                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
6114         }
6115
6116         if (renamed == true) {
6117                 /*
6118                  * Set the callback to one that will fix up the name
6119                  * metadata on the new conflict DN
6120                  */
6121                 callback = replmd_op_name_modify_callback;
6122         }
6123
6124         ZERO_STRUCT(nmd);
6125         nmd.version = 1;
6126         nmd.ctr.ctr1.count = omd.ctr.ctr1.count + rmd->ctr.ctr1.count;
6127         nmd.ctr.ctr1.array = talloc_array(ar,
6128                                           struct replPropertyMetaData1,
6129                                           nmd.ctr.ctr1.count);
6130         if (!nmd.ctr.ctr1.array) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6131
6132         /* first copy the old meta data */
6133         for (i=0; i < omd.ctr.ctr1.count; i++) {
6134                 nmd.ctr.ctr1.array[ni]  = omd.ctr.ctr1.array[i];
6135                 ni++;
6136         }
6137
6138         ar->seq_num = 0;
6139         /* now merge in the new meta data */
6140         for (i=0; i < rmd->ctr.ctr1.count; i++) {
6141                 bool found = false;
6142
6143                 for (j=0; j < ni; j++) {
6144                         bool cmp;
6145
6146                         if (rmd->ctr.ctr1.array[i].attid != nmd.ctr.ctr1.array[j].attid) {
6147                                 continue;
6148                         }
6149
6150                         cmp = replmd_replPropertyMetaData1_new_should_be_taken(
6151                                 ar->objs->dsdb_repl_flags,
6152                                 &nmd.ctr.ctr1.array[j],
6153                                 &rmd->ctr.ctr1.array[i]);
6154                         if (cmp) {
6155                                 /* replace the entry */
6156                                 nmd.ctr.ctr1.array[j] = rmd->ctr.ctr1.array[i];
6157                                 if (ar->seq_num == 0) {
6158                                         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
6159                                         if (ret != LDB_SUCCESS) {
6160                                                 return replmd_replicated_request_error(ar, ret);
6161                                         }
6162                                 }
6163                                 nmd.ctr.ctr1.array[j].local_usn = ar->seq_num;
6164                                 switch (nmd.ctr.ctr1.array[j].attid) {
6165                                 case DRSUAPI_ATTID_ntSecurityDescriptor:
6166                                         sd_updated = true;
6167                                         break;
6168                                 case DRSUAPI_ATTID_isDeleted:
6169                                         take_remote_isDeleted = true;
6170                                         break;
6171                                 default:
6172                                         break;
6173                                 }
6174                                 found = true;
6175                                 break;
6176                         }
6177
6178                         if (rmd->ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType) {
6179                                 DEBUG(3,("Discarding older DRS attribute update to %s on %s from %s\n",
6180                                          msg->elements[i-removed_attrs].name,
6181                                          ldb_dn_get_linearized(msg->dn),
6182                                          GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
6183                         }
6184
6185                         /* we don't want to apply this change so remove the attribute */
6186                         ldb_msg_remove_element(msg, &msg->elements[i-removed_attrs]);
6187                         removed_attrs++;
6188
6189                         found = true;
6190                         break;
6191                 }
6192
6193                 if (found) continue;
6194
6195                 nmd.ctr.ctr1.array[ni] = rmd->ctr.ctr1.array[i];
6196                 if (ar->seq_num == 0) {
6197                         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
6198                         if (ret != LDB_SUCCESS) {
6199                                 return replmd_replicated_request_error(ar, ret);
6200                         }
6201                 }
6202                 nmd.ctr.ctr1.array[ni].local_usn = ar->seq_num;
6203                 switch (nmd.ctr.ctr1.array[ni].attid) {
6204                 case DRSUAPI_ATTID_ntSecurityDescriptor:
6205                         sd_updated = true;
6206                         break;
6207                 case DRSUAPI_ATTID_isDeleted:
6208                         take_remote_isDeleted = true;
6209                         break;
6210                 default:
6211                         break;
6212                 }
6213                 ni++;
6214         }
6215
6216         /*
6217          * finally correct the size of the meta_data array
6218          */
6219         nmd.ctr.ctr1.count = ni;
6220
6221         new_rdn = ldb_dn_get_rdn_val(msg->dn);
6222         old_rdn = ldb_dn_get_rdn_val(ar->search_msg->dn);
6223
6224         if (renamed) {
6225                 ret = replmd_update_rpmd_rdn_attr(ldb, msg, new_rdn, old_rdn,
6226                                                   &nmd, ar, now, is_schema_nc,
6227                                                   false);
6228                 if (ret != LDB_SUCCESS) {
6229                         ldb_asprintf_errstring(ldb, "%s: error during DRS repl merge: %s", __func__, ldb_errstring(ldb));
6230                         return replmd_replicated_request_error(ar, ret);
6231                 }
6232         }
6233         /*
6234          * sort the new meta data array
6235          */
6236         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, msg->dn);
6237         if (ret != LDB_SUCCESS) {
6238                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl merge: %s", __func__, ldb_errstring(ldb));
6239                 return ret;
6240         }
6241
6242         /*
6243          * Work out if this object is deleted, so we can prune any extra attributes.  See MS-DRSR 4.1.10.6.9
6244          * UpdateObject.
6245          *
6246          * This also controls SD propagation below
6247          */
6248         if (take_remote_isDeleted) {
6249                 isDeleted = remote_isDeleted;
6250         } else {
6251                 isDeleted = local_isDeleted;
6252         }
6253
6254         ar->isDeleted = isDeleted;
6255
6256         /*
6257          * check if some replicated attributes left, otherwise skip the ldb_modify() call
6258          */
6259         if (msg->num_elements == 0) {
6260                 ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_apply_merge[%u]: skip replace\n",
6261                           ar->index_current);
6262
6263                 return replmd_replicated_apply_isDeleted(ar);
6264         }
6265
6266         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_apply_merge[%u]: replace %u attributes\n",
6267                   ar->index_current, msg->num_elements);
6268
6269         if (renamed) {
6270                 sd_updated = true;
6271         }
6272
6273         if (sd_updated && !isDeleted) {
6274                 ret = dsdb_module_schedule_sd_propagation(ar->module,
6275                                                           ar->objs->partition_dn,
6276                                                           msg->dn, true);
6277                 if (ret != LDB_SUCCESS) {
6278                         return ldb_operr(ldb);
6279                 }
6280         }
6281
6282         /* create the meta data value */
6283         ndr_err = ndr_push_struct_blob(&nmd_value, msg, &nmd,
6284                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
6285         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6286                 nt_status = ndr_map_error2ntstatus(ndr_err);
6287                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6288         }
6289
6290         /*
6291          * when we know that we'll modify the record, add the whenChanged, uSNChanged
6292          * and replPopertyMetaData attributes
6293          */
6294         ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed);
6295         if (ret != LDB_SUCCESS) {
6296                 return replmd_replicated_request_error(ar, ret);
6297         }
6298         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num);
6299         if (ret != LDB_SUCCESS) {
6300                 return replmd_replicated_request_error(ar, ret);
6301         }
6302         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
6303         if (ret != LDB_SUCCESS) {
6304                 return replmd_replicated_request_error(ar, ret);
6305         }
6306
6307         replmd_ldb_message_sort(msg, ar->schema);
6308
6309         /* we want to replace the old values */
6310         for (i=0; i < msg->num_elements; i++) {
6311                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
6312                 if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) {
6313                         if (msg->elements[i].num_values == 0) {
6314                                 ldb_asprintf_errstring(ldb, __location__
6315                                                        ": objectClass removed on %s, aborting replication\n",
6316                                                        ldb_dn_get_linearized(msg->dn));
6317                                 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION);
6318                         }
6319                 }
6320         }
6321
6322         if (DEBUGLVL(8)) {
6323                 struct GUID_txt_buf guid_txt;
6324
6325                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
6326                                                            LDB_CHANGETYPE_MODIFY,
6327                                                            msg);
6328                 DEBUG(8, ("Final DRS replication modify message of %s:\n%s\n",
6329                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
6330                                           &guid_txt),
6331                           s));
6332                 talloc_free(s);
6333         } else if (DEBUGLVL(4)) {
6334                 struct GUID_txt_buf guid_txt;
6335
6336                 DEBUG(4, ("Final DRS replication modify DN of %s is %s\n",
6337                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
6338                                           &guid_txt),
6339                           ldb_dn_get_linearized(msg->dn)));
6340         }
6341
6342         ret = ldb_build_mod_req(&change_req,
6343                                 ldb,
6344                                 ar,
6345                                 msg,
6346                                 ar->controls,
6347                                 ar,
6348                                 callback,
6349                                 ar->req);
6350         LDB_REQ_SET_LOCATION(change_req);
6351         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6352
6353         /* current partition control needed by "repmd_op_callback" */
6354         ret = ldb_request_add_control(change_req,
6355                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
6356                                       false, NULL);
6357         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6358
6359         return ldb_next_request(ar->module, change_req);
6360 }
6361
6362 static int replmd_replicated_apply_search_callback(struct ldb_request *req,
6363                                                    struct ldb_reply *ares)
6364 {
6365         struct replmd_replicated_request *ar = talloc_get_type(req->context,
6366                                                struct replmd_replicated_request);
6367         int ret;
6368
6369         if (!ares) {
6370                 return ldb_module_done(ar->req, NULL, NULL,
6371                                         LDB_ERR_OPERATIONS_ERROR);
6372         }
6373         if (ares->error != LDB_SUCCESS &&
6374             ares->error != LDB_ERR_NO_SUCH_OBJECT) {
6375                 return ldb_module_done(ar->req, ares->controls,
6376                                         ares->response, ares->error);
6377         }
6378
6379         switch (ares->type) {
6380         case LDB_REPLY_ENTRY:
6381                 ar->search_msg = talloc_steal(ar, ares->message);
6382                 break;
6383
6384         case LDB_REPLY_REFERRAL:
6385                 /* we ignore referrals */
6386                 break;
6387
6388         case LDB_REPLY_DONE:
6389         {
6390                 struct replPropertyMetaData1 *md_remote;
6391                 struct replPropertyMetaData1 *md_local;
6392
6393                 struct replPropertyMetaDataBlob omd;
6394                 const struct ldb_val *omd_value;
6395                 struct replPropertyMetaDataBlob *rmd;
6396                 struct ldb_message *msg;
6397                 int instanceType;
6398                 ar->objs->objects[ar->index_current].local_parent_dn = NULL;
6399                 ar->objs->objects[ar->index_current].last_known_parent = NULL;
6400
6401                 /*
6402                  * This is the ADD case, find the appropriate parent,
6403                  * as this object doesn't exist locally:
6404                  */
6405                 if (ar->search_msg == NULL) {
6406                         ret = replmd_replicated_apply_search_for_parent(ar);
6407                         if (ret != LDB_SUCCESS) {
6408                                 return ldb_module_done(ar->req, NULL, NULL, ret);
6409                         }
6410                         talloc_free(ares);
6411                         return LDB_SUCCESS;
6412                 }
6413
6414                 /*
6415                  * Otherwise, in the MERGE case, work out if we are
6416                  * attempting a rename, and if so find the parent the
6417                  * newly renamed object wants to belong under (which
6418                  * may not be the parent in it's attached string DN
6419                  */
6420                 rmd = ar->objs->objects[ar->index_current].meta_data;
6421                 ZERO_STRUCT(omd);
6422                 omd.version = 1;
6423
6424                 /* find existing meta data */
6425                 omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData");
6426                 if (omd_value) {
6427                         enum ndr_err_code ndr_err;
6428                         ndr_err = ndr_pull_struct_blob(omd_value, ar, &omd,
6429                                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
6430                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6431                                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6432                                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6433                         }
6434
6435                         if (omd.version != 1) {
6436                                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6437                         }
6438                 }
6439
6440                 ar->local_parent_guid = samdb_result_guid(ar->search_msg, "parentGUID");
6441
6442                 instanceType = ldb_msg_find_attr_as_int(ar->search_msg, "instanceType", 0);
6443                 if (((instanceType & INSTANCE_TYPE_IS_NC_HEAD) == 0)
6444                     && GUID_all_zero(&ar->local_parent_guid)) {
6445                         DEBUG(0, ("Refusing to replicate new version of %s "
6446                                   "as local object has an all-zero parentGUID attribute, "
6447                                   "despite not being an NC root\n",
6448                                   ldb_dn_get_linearized(ar->search_msg->dn)));
6449                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6450                 }
6451
6452                 /*
6453                  * now we need to check for double renames. We could have a
6454                  * local rename pending which our replication partner hasn't
6455                  * received yet. We choose which one wins by looking at the
6456                  * attribute stamps on the two objects, the newer one wins.
6457                  *
6458                  * This also simply applies the correct algorithms for
6459                  * determining if a change was made to name at all, or
6460                  * if the object has just been renamed under the same
6461                  * parent.
6462                  */
6463                 md_remote = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
6464                 md_local = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
6465                 if (!md_local) {
6466                         DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
6467                                  ldb_dn_get_linearized(ar->search_msg->dn)));
6468                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
6469                 }
6470
6471                 /*
6472                  * if there is no name attribute given then we have to assume the
6473                  *  object we've received has the older name
6474                  */
6475                 if (replmd_replPropertyMetaData1_new_should_be_taken(
6476                             ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
6477                             md_local, md_remote)) {
6478                         struct GUID_txt_buf p_guid_local;
6479                         struct GUID_txt_buf p_guid_remote;
6480                         msg = ar->objs->objects[ar->index_current].msg;
6481
6482                         /* Merge on the existing object, with rename */
6483
6484                         DEBUG(4,(__location__ ": Looking for new parent for object %s currently under %s "
6485                                  "as incoming object changing to %s under %s\n",
6486                                  ldb_dn_get_linearized(ar->search_msg->dn),
6487                                  GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6488                                  ldb_dn_get_linearized(msg->dn),
6489                                  GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6490                                                  &p_guid_remote)));
6491                         ret = replmd_replicated_apply_search_for_parent(ar);
6492                 } else {
6493                         struct GUID_txt_buf p_guid_local;
6494                         struct GUID_txt_buf p_guid_remote;
6495                         msg = ar->objs->objects[ar->index_current].msg;
6496
6497                         /*
6498                          * Merge on the existing object, force no
6499                          * rename (code below just to explain why in
6500                          * the DEBUG() logs)
6501                          */
6502
6503                         if (strcmp(ldb_dn_get_linearized(ar->search_msg->dn),
6504                                    ldb_dn_get_linearized(msg->dn)) == 0) {
6505                                 if (ar->objs->objects[ar->index_current].parent_guid != NULL &&
6506                                     GUID_equal(&ar->local_parent_guid,
6507                                                ar->objs->objects[ar->index_current].parent_guid)
6508                                     == false) {
6509                                         DEBUG(4,(__location__ ": Keeping object %s at under %s "
6510                                                  "despite incoming object changing parent to %s\n",
6511                                                  ldb_dn_get_linearized(ar->search_msg->dn),
6512                                                  GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6513                                                  GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6514                                                                  &p_guid_remote)));
6515                                 }
6516                         } else {
6517                                 DEBUG(4,(__location__ ": Keeping object %s at under %s "
6518                                          " and rejecting older rename to %s under %s\n",
6519                                          ldb_dn_get_linearized(ar->search_msg->dn),
6520                                          GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6521                                          ldb_dn_get_linearized(msg->dn),
6522                                          GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6523                                                          &p_guid_remote)));
6524                         }
6525                         /*
6526                          * This assignment ensures that the strcmp()
6527                          * and GUID_equal() calls in
6528                          * replmd_replicated_apply_merge() avoids the
6529                          * rename call
6530                          */
6531                         ar->objs->objects[ar->index_current].parent_guid =
6532                                 &ar->local_parent_guid;
6533
6534                         msg->dn = ar->search_msg->dn;
6535                         ret = replmd_replicated_apply_merge(ar);
6536                 }
6537                 if (ret != LDB_SUCCESS) {
6538                         return ldb_module_done(ar->req, NULL, NULL, ret);
6539                 }
6540         }
6541         }
6542
6543         talloc_free(ares);
6544         return LDB_SUCCESS;
6545 }
6546
6547 /**
6548  * Returns true if we can group together processing this link attribute,
6549  * i.e. it has the same source-object and attribute ID as other links
6550  * already in the group
6551  */
6552 static bool la_entry_matches_group(struct la_entry *la_entry,
6553                                    struct la_group *la_group)
6554 {
6555         struct la_entry *prev = la_group->la_entries;
6556
6557         return (la_entry->la->attid == prev->la->attid &&
6558                 GUID_equal(&la_entry->la->identifier->guid,
6559                            &prev->la->identifier->guid));
6560 }
6561
6562 /**
6563  * Stores the linked attributes received in the replication chunk - these get
6564  * applied at the end of the transaction. We also check that each linked
6565  * attribute is valid, i.e. source and target objects are known.
6566  */
6567 static int replmd_store_linked_attributes(struct replmd_replicated_request *ar)
6568 {
6569         int ret = LDB_SUCCESS;
6570         uint32_t i;
6571         struct ldb_module *module = ar->module;
6572         struct replmd_private *replmd_private =
6573                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
6574         struct la_group *la_group = NULL;
6575         struct ldb_context *ldb;
6576
6577         ldb = ldb_module_get_ctx(module);
6578
6579         DEBUG(4,("linked_attributes_count=%u\n", ar->objs->linked_attributes_count));
6580
6581         /* save away the linked attributes for the end of the transaction */
6582         for (i = 0; i < ar->objs->linked_attributes_count; i++) {
6583                 struct la_entry *la_entry;
6584
6585                 if (replmd_private->la_ctx == NULL) {
6586                         replmd_private->la_ctx = talloc_new(replmd_private);
6587                 }
6588                 la_entry = talloc(replmd_private->la_ctx, struct la_entry);
6589                 if (la_entry == NULL) {
6590                         ldb_oom(ldb);
6591                         return LDB_ERR_OPERATIONS_ERROR;
6592                 }
6593                 la_entry->la = talloc(la_entry, struct drsuapi_DsReplicaLinkedAttribute);
6594                 if (la_entry->la == NULL) {
6595                         talloc_free(la_entry);
6596                         ldb_oom(ldb);
6597                         return LDB_ERR_OPERATIONS_ERROR;
6598                 }
6599                 *la_entry->la = ar->objs->linked_attributes[i];
6600                 la_entry->dsdb_repl_flags = ar->objs->dsdb_repl_flags;
6601
6602                 /* we need to steal the non-scalars so they stay
6603                    around until the end of the transaction */
6604                 talloc_steal(la_entry->la, la_entry->la->identifier);
6605                 talloc_steal(la_entry->la, la_entry->la->value.blob);
6606
6607                 ret = replmd_verify_linked_attribute(ar, la_entry);
6608
6609                 if (ret != LDB_SUCCESS) {
6610                         break;
6611                 }
6612
6613                 /* group the links together by source-object for efficiency */
6614                 if (la_group == NULL ||
6615                     !la_entry_matches_group(la_entry, la_group)) {
6616
6617                         la_group = talloc_zero(replmd_private->la_ctx,
6618                                                struct la_group);
6619                         if (la_group == NULL) {
6620                                 ldb_oom(ldb);
6621                                 return LDB_ERR_OPERATIONS_ERROR;
6622                         }
6623                         DLIST_ADD(replmd_private->la_list, la_group);
6624                 }
6625                 DLIST_ADD(la_group->la_entries, la_entry);
6626                 replmd_private->total_links++;
6627         }
6628
6629         return ret;
6630 }
6631
6632 static int replmd_replicated_uptodate_vector(struct replmd_replicated_request *ar);
6633
6634 static int replmd_replicated_apply_next(struct replmd_replicated_request *ar)
6635 {
6636         struct ldb_context *ldb;
6637         int ret;
6638         char *tmp_str;
6639         char *filter;
6640         struct ldb_request *search_req;
6641         static const char *attrs[] = { "repsFrom", "replUpToDateVector",
6642                                        "parentGUID", "instanceType",
6643                                        "replPropertyMetaData", "nTSecurityDescriptor",
6644                                        "isDeleted", NULL };
6645         struct GUID_txt_buf guid_str_buf;
6646
6647         if (ar->index_current >= ar->objs->num_objects) {
6648
6649                 /*
6650                  * Now that we've applied all the objects, check the new linked
6651                  * attributes and store them (we apply them in .prepare_commit)
6652                  */
6653                 ret = replmd_store_linked_attributes(ar);
6654
6655                 if (ret != LDB_SUCCESS) {
6656                         return ret;
6657                 }
6658
6659                 /* done applying objects, move on to the next stage */
6660                 return replmd_replicated_uptodate_vector(ar);
6661         }
6662
6663         ldb = ldb_module_get_ctx(ar->module);
6664         ar->search_msg = NULL;
6665         ar->isDeleted = false;
6666
6667         tmp_str = GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
6668                                   &guid_str_buf);
6669
6670         filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
6671         if (!filter) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6672
6673         ret = ldb_build_search_req(&search_req,
6674                                    ldb,
6675                                    ar,
6676                                    ar->objs->partition_dn,
6677                                    LDB_SCOPE_SUBTREE,
6678                                    filter,
6679                                    attrs,
6680                                    NULL,
6681                                    ar,
6682                                    replmd_replicated_apply_search_callback,
6683                                    ar->req);
6684         LDB_REQ_SET_LOCATION(search_req);
6685
6686         ret = dsdb_request_add_controls(search_req, DSDB_SEARCH_SHOW_RECYCLED);
6687
6688         if (ret != LDB_SUCCESS) {
6689                 return ret;
6690         }
6691
6692         return ldb_next_request(ar->module, search_req);
6693 }
6694
6695 /*
6696  * This is essentially a wrapper for replmd_replicated_apply_next()
6697  *
6698  * This is needed to ensure that both codepaths call this handler.
6699  */
6700 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar)
6701 {
6702         struct ldb_dn *deleted_objects_dn;
6703         struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
6704         int ret = dsdb_get_deleted_objects_dn(ldb_module_get_ctx(ar->module), msg, msg->dn,
6705                                               &deleted_objects_dn);
6706         if (ar->isDeleted && (ret != LDB_SUCCESS || ldb_dn_compare(msg->dn, deleted_objects_dn) != 0)) {
6707                 /*
6708                  * Do a delete here again, so that if there is
6709                  * anything local that conflicts with this
6710                  * object being deleted, it is removed.  This
6711                  * includes links.  See MS-DRSR 4.1.10.6.9
6712                  * UpdateObject.
6713                  *
6714                  * If the object is already deleted, and there
6715                  * is no more work required, it doesn't do
6716                  * anything.
6717                  */
6718
6719                 /* This has been updated to point to the DN we eventually did the modify on */
6720
6721                 struct ldb_request *del_req;
6722                 struct ldb_result *res;
6723
6724                 TALLOC_CTX *tmp_ctx = talloc_new(ar);
6725                 if (!tmp_ctx) {
6726                         ret = ldb_oom(ldb_module_get_ctx(ar->module));
6727                         return ret;
6728                 }
6729
6730                 res = talloc_zero(tmp_ctx, struct ldb_result);
6731                 if (!res) {
6732                         ret = ldb_oom(ldb_module_get_ctx(ar->module));
6733                         talloc_free(tmp_ctx);
6734                         return ret;
6735                 }
6736
6737                 /* Build a delete request, which hopefully will artually turn into nothing */
6738                 ret = ldb_build_del_req(&del_req, ldb_module_get_ctx(ar->module), tmp_ctx,
6739                                         msg->dn,
6740                                         NULL,
6741                                         res,
6742                                         ldb_modify_default_callback,
6743                                         ar->req);
6744                 LDB_REQ_SET_LOCATION(del_req);
6745                 if (ret != LDB_SUCCESS) {
6746                         talloc_free(tmp_ctx);
6747                         return ret;
6748                 }
6749
6750                 /*
6751                  * This is the guts of the call, call back
6752                  * into our delete code, but setting the
6753                  * re_delete flag so we delete anything that
6754                  * shouldn't be there on a deleted or recycled
6755                  * object
6756                  */
6757                 ret = replmd_delete_internals(ar->module, del_req, true);
6758                 if (ret == LDB_SUCCESS) {
6759                         ret = ldb_wait(del_req->handle, LDB_WAIT_ALL);
6760                 }
6761
6762                 talloc_free(tmp_ctx);
6763                 if (ret != LDB_SUCCESS) {
6764                         return ret;
6765                 }
6766         }
6767
6768         ar->index_current++;
6769         return replmd_replicated_apply_next(ar);
6770 }
6771
6772 static int replmd_replicated_uptodate_modify_callback(struct ldb_request *req,
6773                                                       struct ldb_reply *ares)
6774 {
6775         struct ldb_context *ldb;
6776         struct replmd_replicated_request *ar = talloc_get_type(req->context,
6777                                                struct replmd_replicated_request);
6778         ldb = ldb_module_get_ctx(ar->module);
6779
6780         if (!ares) {
6781                 return ldb_module_done(ar->req, NULL, NULL,
6782                                         LDB_ERR_OPERATIONS_ERROR);
6783         }
6784         if (ares->error != LDB_SUCCESS) {
6785                 return ldb_module_done(ar->req, ares->controls,
6786                                         ares->response, ares->error);
6787         }
6788
6789         if (ares->type != LDB_REPLY_DONE) {
6790                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
6791                 return ldb_module_done(ar->req, NULL, NULL,
6792                                         LDB_ERR_OPERATIONS_ERROR);
6793         }
6794
6795         talloc_free(ares);
6796
6797         return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6798 }
6799
6800 static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *ar)
6801 {
6802         struct ldb_context *ldb;
6803         struct ldb_request *change_req;
6804         enum ndr_err_code ndr_err;
6805         struct ldb_message *msg;
6806         struct replUpToDateVectorBlob ouv;
6807         const struct ldb_val *ouv_value;
6808         const struct drsuapi_DsReplicaCursor2CtrEx *ruv;
6809         struct replUpToDateVectorBlob nuv;
6810         struct ldb_val nuv_value;
6811         struct ldb_message_element *nuv_el = NULL;
6812         struct ldb_message_element *orf_el = NULL;
6813         struct repsFromToBlob nrf;
6814         struct ldb_val *nrf_value = NULL;
6815         struct ldb_message_element *nrf_el = NULL;
6816         unsigned int i;
6817         uint32_t j,ni=0;
6818         bool found = false;
6819         time_t t = time(NULL);
6820         NTTIME now;
6821         int ret;
6822         uint32_t instanceType;
6823
6824         ldb = ldb_module_get_ctx(ar->module);
6825         ruv = ar->objs->uptodateness_vector;
6826         ZERO_STRUCT(ouv);
6827         ouv.version = 2;
6828         ZERO_STRUCT(nuv);
6829         nuv.version = 2;
6830
6831         unix_to_nt_time(&now, t);
6832
6833         if (ar->search_msg == NULL) {
6834                 /* this happens for a REPL_OBJ call where we are
6835                    creating the target object by replicating it. The
6836                    subdomain join code does this for the partition DN
6837                 */
6838                 DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n"));
6839                 return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6840         }
6841
6842         instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
6843         if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
6844                 DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as not NC root: %s\n",
6845                          ldb_dn_get_linearized(ar->search_msg->dn)));
6846                 return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6847         }
6848
6849         /*
6850          * first create the new replUpToDateVector
6851          */
6852         ouv_value = ldb_msg_find_ldb_val(ar->search_msg, "replUpToDateVector");
6853         if (ouv_value) {
6854                 ndr_err = ndr_pull_struct_blob(ouv_value, ar, &ouv,
6855                                                (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
6856                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6857                         NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6858                         return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6859                 }
6860
6861                 if (ouv.version != 2) {
6862                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6863                 }
6864         }
6865
6866         /*
6867          * the new uptodateness vector will at least
6868          * contain 1 entry, one for the source_dsa
6869          *
6870          * plus optional values from our old vector and the one from the source_dsa
6871          */
6872         nuv.ctr.ctr2.count = ouv.ctr.ctr2.count;
6873         if (ruv) nuv.ctr.ctr2.count += ruv->count;
6874         nuv.ctr.ctr2.cursors = talloc_array(ar,
6875                                             struct drsuapi_DsReplicaCursor2,
6876                                             nuv.ctr.ctr2.count);
6877         if (!nuv.ctr.ctr2.cursors) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6878
6879         /* first copy the old vector */
6880         for (i=0; i < ouv.ctr.ctr2.count; i++) {
6881                 nuv.ctr.ctr2.cursors[ni] = ouv.ctr.ctr2.cursors[i];
6882                 ni++;
6883         }
6884
6885         /* merge in the source_dsa vector is available */
6886         for (i=0; (ruv && i < ruv->count); i++) {
6887                 found = false;
6888
6889                 if (GUID_equal(&ruv->cursors[i].source_dsa_invocation_id,
6890                                &ar->our_invocation_id)) {
6891                         continue;
6892                 }
6893
6894                 for (j=0; j < ni; j++) {
6895                         if (!GUID_equal(&ruv->cursors[i].source_dsa_invocation_id,
6896                                         &nuv.ctr.ctr2.cursors[j].source_dsa_invocation_id)) {
6897                                 continue;
6898                         }
6899
6900                         found = true;
6901
6902                         if (ruv->cursors[i].highest_usn > nuv.ctr.ctr2.cursors[j].highest_usn) {
6903                                 nuv.ctr.ctr2.cursors[j] = ruv->cursors[i];
6904                         }
6905                         break;
6906                 }
6907
6908                 if (found) continue;
6909
6910                 /* if it's not there yet, add it */
6911                 nuv.ctr.ctr2.cursors[ni] = ruv->cursors[i];
6912                 ni++;
6913         }
6914
6915         /*
6916          * finally correct the size of the cursors array
6917          */
6918         nuv.ctr.ctr2.count = ni;
6919
6920         /*
6921          * sort the cursors
6922          */
6923         TYPESAFE_QSORT(nuv.ctr.ctr2.cursors, nuv.ctr.ctr2.count, drsuapi_DsReplicaCursor2_compare);
6924
6925         /*
6926          * create the change ldb_message
6927          */
6928         msg = ldb_msg_new(ar);
6929         if (!msg) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6930         msg->dn = ar->search_msg->dn;
6931
6932         ndr_err = ndr_push_struct_blob(&nuv_value, msg, &nuv,
6933                                        (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob);
6934         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6935                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6936                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6937         }
6938         ret = ldb_msg_add_value(msg, "replUpToDateVector", &nuv_value, &nuv_el);
6939         if (ret != LDB_SUCCESS) {
6940                 return replmd_replicated_request_error(ar, ret);
6941         }
6942         nuv_el->flags = LDB_FLAG_MOD_REPLACE;
6943
6944         /*
6945          * now create the new repsFrom value from the given repsFromTo1 structure
6946          */
6947         ZERO_STRUCT(nrf);
6948         nrf.version                                     = 1;
6949         nrf.ctr.ctr1                                    = *ar->objs->source_dsa;
6950         nrf.ctr.ctr1.last_attempt                       = now;
6951         nrf.ctr.ctr1.last_success                       = now;
6952         nrf.ctr.ctr1.result_last_attempt                = WERR_OK;
6953
6954         /*
6955          * first see if we already have a repsFrom value for the current source dsa
6956          * if so we'll later replace this value
6957          */
6958         orf_el = ldb_msg_find_element(ar->search_msg, "repsFrom");
6959         if (orf_el) {
6960                 for (i=0; i < orf_el->num_values; i++) {
6961                         struct repsFromToBlob *trf;
6962
6963                         trf = talloc(ar, struct repsFromToBlob);
6964                         if (!trf) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6965
6966                         ndr_err = ndr_pull_struct_blob(&orf_el->values[i], trf, trf,
6967                                                        (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
6968                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6969                                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6970                                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6971                         }
6972
6973                         if (trf->version != 1) {
6974                                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6975                         }
6976
6977                         /*
6978                          * we compare the source dsa objectGUID not the invocation_id
6979                          * because we want only one repsFrom value per source dsa
6980                          * and when the invocation_id of the source dsa has changed we don't need
6981                          * the old repsFrom with the old invocation_id
6982                          */
6983                         if (!GUID_equal(&trf->ctr.ctr1.source_dsa_obj_guid,
6984                                         &ar->objs->source_dsa->source_dsa_obj_guid)) {
6985                                 talloc_free(trf);
6986                                 continue;
6987                         }
6988
6989                         talloc_free(trf);
6990                         nrf_value = &orf_el->values[i];
6991                         break;
6992                 }
6993
6994                 /*
6995                  * copy over all old values to the new ldb_message
6996                  */
6997                 ret = ldb_msg_add_empty(msg, "repsFrom", 0, &nrf_el);
6998                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6999                 *nrf_el = *orf_el;
7000         }
7001
7002         /*
7003          * if we haven't found an old repsFrom value for the current source dsa
7004          * we'll add a new value
7005          */
7006         if (!nrf_value) {
7007                 struct ldb_val zero_value;
7008                 ZERO_STRUCT(zero_value);
7009                 ret = ldb_msg_add_value(msg, "repsFrom", &zero_value, &nrf_el);
7010                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
7011
7012                 nrf_value = &nrf_el->values[nrf_el->num_values - 1];
7013         }
7014
7015         /* we now fill the value which is already attached to ldb_message */
7016         ndr_err = ndr_push_struct_blob(nrf_value, msg,
7017                                        &nrf,
7018                                        (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
7019         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
7020                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
7021                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
7022         }
7023
7024         /*
7025          * the ldb_message_element for the attribute, has all the old values and the new one
7026          * so we'll replace the whole attribute with all values
7027          */
7028         nrf_el->flags = LDB_FLAG_MOD_REPLACE;
7029
7030         if (CHECK_DEBUGLVL(4)) {
7031                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
7032                                                            LDB_CHANGETYPE_MODIFY,
7033                                                            msg);
7034                 DEBUG(4, ("DRS replication uptodate modify message:\n%s\n", s));
7035                 talloc_free(s);
7036         }
7037
7038         /* prepare the ldb_modify() request */
7039         ret = ldb_build_mod_req(&change_req,
7040                                 ldb,
7041                                 ar,
7042                                 msg,
7043                                 ar->controls,
7044                                 ar,
7045                                 replmd_replicated_uptodate_modify_callback,
7046                                 ar->req);
7047         LDB_REQ_SET_LOCATION(change_req);
7048         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
7049
7050         return ldb_next_request(ar->module, change_req);
7051 }
7052
7053 static int replmd_replicated_uptodate_search_callback(struct ldb_request *req,
7054                                                       struct ldb_reply *ares)
7055 {
7056         struct replmd_replicated_request *ar = talloc_get_type(req->context,
7057                                                struct replmd_replicated_request);
7058         int ret;
7059
7060         if (!ares) {
7061                 return ldb_module_done(ar->req, NULL, NULL,
7062                                         LDB_ERR_OPERATIONS_ERROR);
7063         }
7064         if (ares->error != LDB_SUCCESS &&
7065             ares->error != LDB_ERR_NO_SUCH_OBJECT) {
7066                 return ldb_module_done(ar->req, ares->controls,
7067                                         ares->response, ares->error);
7068         }
7069
7070         switch (ares->type) {
7071         case LDB_REPLY_ENTRY:
7072                 ar->search_msg = talloc_steal(ar, ares->message);
7073                 break;
7074
7075         case LDB_REPLY_REFERRAL:
7076                 /* we ignore referrals */
7077                 break;
7078
7079         case LDB_REPLY_DONE:
7080                 ret = replmd_replicated_uptodate_modify(ar);
7081                 if (ret != LDB_SUCCESS) {
7082                         return ldb_module_done(ar->req, NULL, NULL, ret);
7083                 }
7084         }
7085
7086         talloc_free(ares);
7087         return LDB_SUCCESS;
7088 }
7089
7090
7091 static int replmd_replicated_uptodate_vector(struct replmd_replicated_request *ar)
7092 {
7093         struct ldb_context *ldb = ldb_module_get_ctx(ar->module);
7094         struct replmd_private *replmd_private =
7095                 talloc_get_type_abort(ldb_module_get_private(ar->module),
7096                 struct replmd_private);
7097         int ret;
7098         static const char *attrs[] = {
7099                 "replUpToDateVector",
7100                 "repsFrom",
7101                 "instanceType",
7102                 NULL
7103         };
7104         struct ldb_request *search_req;
7105
7106         ar->search_msg = NULL;
7107
7108         /*
7109          * Let the caller know that we did an originating updates
7110          */
7111         ar->objs->originating_updates = replmd_private->originating_updates;
7112
7113         ret = ldb_build_search_req(&search_req,
7114                                    ldb,
7115                                    ar,
7116                                    ar->objs->partition_dn,
7117                                    LDB_SCOPE_BASE,
7118                                    "(objectClass=*)",
7119                                    attrs,
7120                                    NULL,
7121                                    ar,
7122                                    replmd_replicated_uptodate_search_callback,
7123                                    ar->req);
7124         LDB_REQ_SET_LOCATION(search_req);
7125         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
7126
7127         return ldb_next_request(ar->module, search_req);
7128 }
7129
7130
7131
7132 static int replmd_extended_replicated_objects(struct ldb_module *module, struct ldb_request *req)
7133 {
7134         struct ldb_context *ldb;
7135         struct dsdb_extended_replicated_objects *objs;
7136         struct replmd_replicated_request *ar;
7137         struct ldb_control **ctrls;
7138         int ret;
7139
7140         ldb = ldb_module_get_ctx(module);
7141
7142         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_extended_replicated_objects\n");
7143
7144         objs = talloc_get_type(req->op.extended.data, struct dsdb_extended_replicated_objects);
7145         if (!objs) {
7146                 ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_extended_replicated_objects: invalid extended data\n");
7147                 return LDB_ERR_PROTOCOL_ERROR;
7148         }
7149
7150         if (objs->version != DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION) {
7151                 ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_extended_replicated_objects: extended data invalid version [%u != %u]\n",
7152                           objs->version, DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION);
7153                 return LDB_ERR_PROTOCOL_ERROR;
7154         }
7155
7156         ar = replmd_ctx_init(module, req);
7157         if (!ar)
7158                 return LDB_ERR_OPERATIONS_ERROR;
7159
7160         /* Set the flags to have the replmd_op_callback run over the full set of objects */
7161         ar->apply_mode = true;
7162         ar->objs = objs;
7163         ar->schema = dsdb_get_schema(ldb, ar);
7164         if (!ar->schema) {
7165                 ldb_debug_set(ldb, LDB_DEBUG_FATAL, "replmd_ctx_init: no loaded schema found\n");
7166                 talloc_free(ar);
7167                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
7168                 return LDB_ERR_CONSTRAINT_VIOLATION;
7169         }
7170
7171         ctrls = req->controls;
7172
7173         if (req->controls) {
7174                 req->controls = talloc_memdup(ar, req->controls,
7175                                               talloc_get_size(req->controls));
7176                 if (!req->controls) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
7177         }
7178
7179         ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, NULL);
7180         if (ret != LDB_SUCCESS) {
7181                 return ret;
7182         }
7183
7184         /* If this change contained linked attributes in the body
7185          * (rather than in the links section) we need to update
7186          * backlinks in linked_attributes */
7187         ret = ldb_request_add_control(req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
7188         if (ret != LDB_SUCCESS) {
7189                 return ret;
7190         }
7191
7192         ar->controls = req->controls;
7193         req->controls = ctrls;
7194
7195         return replmd_replicated_apply_next(ar);
7196 }
7197
7198 /**
7199  * Checks how to handle an missing target - either we need to fail the
7200  * replication and retry with GET_TGT, ignore the link and continue, or try to
7201  * add a partial link to an unknown target.
7202  */
7203 static int replmd_allow_missing_target(struct ldb_module *module,
7204                                        TALLOC_CTX *mem_ctx,
7205                                        struct ldb_dn *target_dn,
7206                                        struct ldb_dn *source_dn,
7207                                        bool is_obj_commit,
7208                                        struct GUID *guid,
7209                                        uint32_t dsdb_repl_flags,
7210                                        bool *ignore_link,
7211                                        const char * missing_str)
7212 {
7213         struct ldb_context *ldb = ldb_module_get_ctx(module);
7214         bool is_in_same_nc;
7215
7216         /*
7217          * we may not be able to resolve link targets properly when
7218          * dealing with subsets of objects, e.g. the source is a
7219          * critical object and the target isn't
7220          *
7221          * TODO:
7222          * When we implement Trusted Domains we need to consider
7223          * whether they get treated as an incomplete replica here or not
7224          */
7225         if (dsdb_repl_flags & DSDB_REPL_FLAG_OBJECT_SUBSET) {
7226
7227                 /*
7228                  * Ignore the link. We don't increase the highwater-mark in
7229                  * the object subset cases, so subsequent replications should
7230                  * resolve any missing links
7231                  */
7232                 DEBUG(2, ("%s target %s linked from %s\n", missing_str,
7233                           ldb_dn_get_linearized(target_dn),
7234                           ldb_dn_get_linearized(source_dn)));
7235                 *ignore_link = true;
7236                 return LDB_SUCCESS;
7237         }
7238
7239         if (dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
7240
7241                 /*
7242                  * target should already be up-to-date so there's no point in
7243                  * retrying. This could be due to bad timing, or if a target
7244                  * on a one-way link was deleted. We ignore the link rather
7245                  * than failing the replication cycle completely
7246                  */
7247                 *ignore_link = true;
7248                 DBG_WARNING("%s is %s but up to date. Ignoring link from %s\n",
7249                             ldb_dn_get_linearized(target_dn), missing_str,
7250                             ldb_dn_get_linearized(source_dn));
7251                 return LDB_SUCCESS;
7252         }
7253         
7254         is_in_same_nc = dsdb_objects_have_same_nc(ldb,
7255                                                   mem_ctx,
7256                                                   source_dn,
7257                                                   target_dn);
7258         if (is_in_same_nc) {
7259                 /* fail the replication and retry with GET_TGT */
7260                 ldb_asprintf_errstring(ldb, "%s target %s GUID %s linked from %s\n",
7261                                        missing_str,
7262                                        ldb_dn_get_linearized(target_dn),
7263                                        GUID_string(mem_ctx, guid),
7264                                        ldb_dn_get_linearized(source_dn));
7265                 return LDB_ERR_NO_SUCH_OBJECT;
7266         }
7267
7268         /*
7269          * The target of the cross-partition link is missing. Continue
7270          * and try to at least add the forward-link. This isn't great,
7271          * but a partial link can be fixed by dbcheck, so it's better
7272          * than dropping the link completely.
7273          */
7274         *ignore_link = false;
7275
7276         if (is_obj_commit) {
7277
7278                 /*
7279                  * Only log this when we're actually committing the objects.
7280                  * This avoids spurious logs, i.e. if we're just verifying the
7281                  * received link during a join.
7282                  */
7283                 DBG_WARNING("%s cross-partition target %s linked from %s\n",
7284                             missing_str, ldb_dn_get_linearized(target_dn),
7285                             ldb_dn_get_linearized(source_dn));
7286         }
7287         
7288         return LDB_SUCCESS;
7289 }
7290
7291 /**
7292  * Checks that the target object for a linked attribute exists.
7293  * @param guid returns the target object's GUID (is returned)if it exists)
7294  * @param ignore_link set to true if the linked attribute should be ignored
7295  * (i.e. the target doesn't exist, but that it's OK to skip the link)
7296  */
7297 static int replmd_check_target_exists(struct ldb_module *module,
7298                                       struct dsdb_dn *dsdb_dn,
7299                                       struct la_entry *la_entry,
7300                                       struct ldb_dn *source_dn,
7301                                       bool is_obj_commit,
7302                                       struct GUID *guid,
7303                                       bool *ignore_link)
7304 {
7305         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
7306         struct ldb_context *ldb = ldb_module_get_ctx(module);
7307         struct ldb_result *target_res;
7308         TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
7309         const char *attrs[] = { "isDeleted", "isRecycled", NULL };
7310         NTSTATUS ntstatus;
7311         int ret;
7312         enum deletion_state target_deletion_state = OBJECT_REMOVED;
7313         bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) ? true : false;
7314
7315         *ignore_link = false;
7316         ntstatus = dsdb_get_extended_dn_guid(dsdb_dn->dn, guid, "GUID");
7317
7318         if (!NT_STATUS_IS_OK(ntstatus) && !active) {
7319
7320                 /*
7321                  * This strange behaviour (allowing a NULL/missing
7322                  * GUID) originally comes from:
7323                  *
7324                  * commit e3054ce0fe0f8f62d2f5b2a77893e7a1479128bd
7325                  * Author: Andrew Tridgell <tridge@samba.org>
7326                  * Date:   Mon Dec 21 21:21:55 2009 +1100
7327                  *
7328                  *  s4-drs: cope better with NULL GUIDS from DRS
7329                  *
7330                  *  It is valid to get a NULL GUID over DRS for a deleted forward link. We
7331                  *  need to match by DN if possible when seeing if we should update an
7332                  *  existing link.
7333                  *
7334                  *  Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
7335                  */
7336                 ret = dsdb_module_search_dn(module, tmp_ctx, &target_res,
7337                                             dsdb_dn->dn, attrs,
7338                                             DSDB_FLAG_NEXT_MODULE |
7339                                             DSDB_SEARCH_SHOW_RECYCLED |
7340                                             DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
7341                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
7342                                             NULL);
7343         } else if (!NT_STATUS_IS_OK(ntstatus)) {
7344                 ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute 0x%x blob for %s from %s",
7345                                        la->attid,
7346                                        ldb_dn_get_linearized(dsdb_dn->dn),
7347                                        ldb_dn_get_linearized(source_dn));
7348                 talloc_free(tmp_ctx);
7349                 return LDB_ERR_OPERATIONS_ERROR;
7350         } else {
7351                 ret = dsdb_module_search(module, tmp_ctx, &target_res,
7352                                          NULL, LDB_SCOPE_SUBTREE,
7353                                          attrs,
7354                                          DSDB_FLAG_NEXT_MODULE |
7355                                          DSDB_SEARCH_SHOW_RECYCLED |
7356                                          DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
7357                                          DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
7358                                          NULL,
7359                                          "objectGUID=%s",
7360                                          GUID_string(tmp_ctx, guid));
7361         }
7362
7363         if (ret != LDB_SUCCESS) {
7364                 ldb_asprintf_errstring(ldb, "Failed to re-resolve GUID %s: %s\n",
7365                                        GUID_string(tmp_ctx, guid),
7366                                        ldb_errstring(ldb));
7367                 talloc_free(tmp_ctx);
7368                 return ret;
7369         }
7370
7371         if (target_res->count == 0) {
7372
7373                 /*
7374                  * target object is unknown. Check whether to ignore the link,
7375                  * fail the replication, or add a partial link
7376                  */
7377                 ret = replmd_allow_missing_target(module, tmp_ctx, dsdb_dn->dn,
7378                                                   source_dn, is_obj_commit, guid,
7379                                                   la_entry->dsdb_repl_flags,
7380                                                   ignore_link, "Unknown");
7381
7382         } else if (target_res->count != 1) {
7383                 ldb_asprintf_errstring(ldb, "More than one object found matching objectGUID %s\n",
7384                                        GUID_string(tmp_ctx, guid));
7385                 ret = LDB_ERR_OPERATIONS_ERROR;
7386         } else {
7387                 struct ldb_message *target_msg = target_res->msgs[0];
7388
7389                 dsdb_dn->dn = talloc_steal(dsdb_dn, target_msg->dn);
7390
7391                 /* Get the object's state (i.e. Not Deleted, Tombstone, etc) */
7392                 replmd_deletion_state(module, target_msg,
7393                                       &target_deletion_state, NULL);
7394
7395                 /*
7396                  * Check for deleted objects as per MS-DRSR 4.1.10.6.14
7397                  * ProcessLinkValue(). Link updates should not be sent for
7398                  * recycled and tombstone objects (deleting the links should
7399                  * happen when we delete the object). This probably means our
7400                  * copy of the target object isn't up to date.
7401                  */
7402                 if (target_deletion_state >= OBJECT_RECYCLED) {
7403
7404                         /*
7405                          * target object is deleted. Check whether to ignore the
7406                          * link, fail the replication, or add a partial link
7407                          */
7408                         ret = replmd_allow_missing_target(module, tmp_ctx,
7409                                                           dsdb_dn->dn, source_dn,
7410                                                           is_obj_commit, guid,
7411                                                           la_entry->dsdb_repl_flags,
7412                                                           ignore_link, "Deleted");
7413                 }
7414         }
7415
7416         talloc_free(tmp_ctx);
7417         return ret;
7418 }
7419
7420 /**
7421  * Extracts the key details about the source object for a
7422  * linked-attribute entry.
7423  * This returns the following details:
7424  * @param ret_attr the schema details for the linked attribute
7425  * @param source_msg the search result for the source object
7426  */
7427 static int replmd_get_la_entry_source(struct ldb_module *module,
7428                                       struct la_entry *la_entry,
7429                                       TALLOC_CTX *mem_ctx,
7430                                       const struct dsdb_attribute **ret_attr,
7431                                       struct ldb_message **source_msg)
7432 {
7433         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
7434         struct ldb_context *ldb = ldb_module_get_ctx(module);
7435         const struct dsdb_schema *schema = dsdb_get_schema(ldb, mem_ctx);
7436         int ret;
7437         const struct dsdb_attribute *attr;
7438         struct ldb_result *res;
7439         const char *attrs[4];
7440
7441 /*
7442 linked_attributes[0]:
7443      &objs->linked_attributes[i]: struct drsuapi_DsReplicaLinkedAttribute
7444         identifier               : *
7445             identifier: struct drsuapi_DsReplicaObjectIdentifier
7446                 __ndr_size               : 0x0000003a (58)
7447                 __ndr_size_sid           : 0x00000000 (0)
7448                 guid                     : 8e95b6a9-13dd-4158-89db-3220a5be5cc7
7449                 sid                      : S-0-0
7450                 __ndr_size_dn            : 0x00000000 (0)
7451                 dn                       : ''
7452         attid                    : DRSUAPI_ATTID_member (0x1F)
7453         value: struct drsuapi_DsAttributeValue
7454             __ndr_size               : 0x0000007e (126)
7455             blob                     : *
7456                 blob                     : DATA_BLOB length=126
7457         flags                    : 0x00000001 (1)
7458                1: DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
7459         originating_add_time     : Wed Sep  2 22:20:01 2009 EST
7460         meta_data: struct drsuapi_DsReplicaMetaData
7461             version                  : 0x00000015 (21)
7462             originating_change_time  : Wed Sep  2 23:39:07 2009 EST
7463             originating_invocation_id: 794640f3-18cf-40ee-a211-a93992b67a64
7464             originating_usn          : 0x000000000001e19c (123292)
7465
7466 (for cases where the link is to a normal DN)
7467      &target: struct drsuapi_DsReplicaObjectIdentifier3
7468         __ndr_size               : 0x0000007e (126)
7469         __ndr_size_sid           : 0x0000001c (28)
7470         guid                     : 7639e594-db75-4086-b0d4-67890ae46031
7471         sid                      : S-1-5-21-2848215498-2472035911-1947525656-19924
7472         __ndr_size_dn            : 0x00000022 (34)
7473         dn                       : 'CN=UOne,OU=TestOU,DC=vsofs8,DC=com'
7474  */
7475
7476         /* find the attribute being modified */
7477         attr = dsdb_attribute_by_attributeID_id(schema, la->attid);
7478         if (attr == NULL) {
7479                 struct GUID_txt_buf guid_str;
7480                 ldb_asprintf_errstring(ldb, "Unable to find attributeID 0x%x for link on <GUID=%s>",
7481                                        la->attid,
7482                                        GUID_buf_string(&la->identifier->guid,
7483                                                        &guid_str));
7484                 return LDB_ERR_OPERATIONS_ERROR;
7485         }
7486
7487         /*
7488          * All attributes listed here must be dealt with in some way
7489          * by replmd_process_linked_attribute() otherwise in the case
7490          * of isDeleted: FALSE the modify will fail with:
7491          *
7492          * Failed to apply linked attribute change 'attribute 'isDeleted':
7493          * invalid modify flags on
7494          * 'CN=g1_1527570609273,CN=Users,DC=samba,DC=example,DC=com':
7495          * 0x0'
7496          *
7497          * This is becaue isDeleted is a Boolean, so FALSE is a
7498          * legitimate value (set by Samba's deletetest.py)
7499          */
7500         attrs[0] = attr->lDAPDisplayName;
7501         attrs[1] = "isDeleted";
7502         attrs[2] = "isRecycled";
7503         attrs[3] = NULL;
7504
7505         /*
7506          * get the existing message from the db for the object with
7507          * this GUID, returning attribute being modified. We will then
7508          * use this msg as the basis for a modify call
7509          */
7510         ret = dsdb_module_search(module, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
7511                                  DSDB_FLAG_NEXT_MODULE |
7512                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
7513                                  DSDB_SEARCH_SHOW_RECYCLED |
7514                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
7515                                  DSDB_SEARCH_REVEAL_INTERNALS,
7516                                  NULL,
7517                                  "objectGUID=%s", GUID_string(mem_ctx, &la->identifier->guid));
7518         if (ret != LDB_SUCCESS) {
7519                 return ret;
7520         }
7521         if (res->count != 1) {
7522                 ldb_asprintf_errstring(ldb, "DRS linked attribute for GUID %s - DN not found",
7523                                        GUID_string(mem_ctx, &la->identifier->guid));
7524                 return LDB_ERR_NO_SUCH_OBJECT;
7525         }
7526
7527         *source_msg = res->msgs[0];
7528         *ret_attr = attr;
7529
7530         return LDB_SUCCESS;
7531 }
7532
7533 /**
7534  * Verifies the source and target objects are known for a linked attribute
7535  */
7536 static int replmd_verify_linked_attribute(struct replmd_replicated_request *ar,
7537                                           struct la_entry *la_entry)
7538 {
7539         int ret = LDB_SUCCESS;
7540         TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
7541         struct ldb_module *module = ar->module;
7542         struct ldb_message *src_msg;
7543         const struct dsdb_attribute *attr;
7544         struct dsdb_dn *tgt_dsdb_dn = NULL;
7545         struct GUID guid = GUID_zero();
7546         bool dummy;
7547         WERROR status;
7548         struct ldb_context *ldb = ldb_module_get_ctx(module);
7549         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
7550         const struct dsdb_schema *schema = dsdb_get_schema(ldb, tmp_ctx);
7551
7552         ret = replmd_get_la_entry_source(module, la_entry, tmp_ctx, &attr,
7553                                          &src_msg);
7554
7555         /*
7556          * When we fail to find the source object, the error code we pass
7557          * back here is really important. It flags back to the callers to
7558          * retry this request with DRSUAPI_DRS_GET_ANC. This case should
7559          * never happen if we're replicating from a Samba DC, but it is
7560          * needed to talk to a Windows DC
7561          */
7562         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
7563                 ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_MISSING_PARENT);
7564         }
7565
7566         if (ret != LDB_SUCCESS) {
7567                 talloc_free(tmp_ctx);
7568                 return ret;
7569         }
7570
7571         /* the value blob for the attribute holds the target object DN */
7572         status = dsdb_dn_la_from_blob(ldb, attr, schema, tmp_ctx,
7573                                       la->value.blob, &tgt_dsdb_dn);
7574         if (!W_ERROR_IS_OK(status)) {
7575                 ldb_asprintf_errstring(ldb, "Failed to parsed linked attribute blob for %s on %s - %s\n",
7576                                        attr->lDAPDisplayName,
7577                                        ldb_dn_get_linearized(src_msg->dn),
7578                                        win_errstr(status));
7579                 return LDB_ERR_OPERATIONS_ERROR;
7580         }
7581
7582         /*
7583          * We can skip the target object checks if we're only syncing critical
7584          * objects, or we know the target is up-to-date. If either case, we
7585          * still continue even if the target doesn't exist
7586          */
7587         if ((la_entry->dsdb_repl_flags & (DSDB_REPL_FLAG_OBJECT_SUBSET |
7588                                           DSDB_REPL_FLAG_TARGETS_UPTODATE)) == 0) {
7589
7590                 ret = replmd_check_target_exists(module, tgt_dsdb_dn, la_entry,
7591                                                  src_msg->dn, false, &guid,
7592                                                  &dummy);
7593         }
7594
7595         /*
7596          * When we fail to find the target object, the error code we pass
7597          * back here is really important. It flags back to the callers to
7598          * retry this request with DRSUAPI_DRS_GET_TGT
7599          */
7600         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
7601                 ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_RECYCLED_TARGET);
7602         }
7603
7604         talloc_free(tmp_ctx);
7605         return ret;
7606 }
7607
7608 /**
7609  * Finds the current active Parsed-DN value for a single-valued linked
7610  * attribute, if one exists.
7611  * @param ret_pdn assigned the active Parsed-DN, or NULL if none was found
7612  * @returns LDB_SUCCESS (regardless of whether a match was found), unless
7613  * an error occurred
7614  */
7615 static int replmd_get_active_singleval_link(struct ldb_module *module,
7616                                             TALLOC_CTX *mem_ctx,
7617                                             struct parsed_dn pdn_list[],
7618                                             unsigned int count,
7619                                             const struct dsdb_attribute *attr,
7620                                             struct parsed_dn **ret_pdn)
7621 {
7622         unsigned int i;
7623
7624         *ret_pdn = NULL;
7625
7626         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE)) {
7627
7628                 /* nothing to do for multi-valued linked attributes */
7629                 return LDB_SUCCESS;
7630         }
7631
7632         for (i = 0; i < count; i++) {
7633                 int ret = LDB_SUCCESS;
7634                 struct parsed_dn *pdn = &pdn_list[i];
7635
7636                 /* skip any inactive links */
7637                 if (dsdb_dn_is_deleted_val(pdn->v)) {
7638                         continue;
7639                 }
7640
7641                 /* we've found an active value for this attribute */
7642                 *ret_pdn = pdn;
7643
7644                 if (pdn->dsdb_dn == NULL) {
7645                         struct ldb_context *ldb = ldb_module_get_ctx(module);
7646
7647                         ret = really_parse_trusted_dn(mem_ctx, ldb, pdn,
7648                                                       attr->syntax->ldap_oid);
7649                 }
7650
7651                 return ret;
7652         }
7653
7654         /* no active link found */
7655         return LDB_SUCCESS;
7656 }
7657
7658 /**
7659  * @returns true if the replication linked attribute info is newer than we
7660  * already have in our DB
7661  * @param pdn the existing linked attribute info in our DB
7662  * @param la the new linked attribute info received during replication
7663  */
7664 static bool replmd_link_update_is_newer(struct parsed_dn *pdn,
7665                                         struct drsuapi_DsReplicaLinkedAttribute *la)
7666 {
7667         /* see if this update is newer than what we have already */
7668         struct GUID invocation_id = GUID_zero();
7669         uint32_t version = 0;
7670         NTTIME change_time = 0;
7671
7672         if (pdn == NULL) {
7673
7674                 /* no existing info so update is newer */
7675                 return true;
7676         }
7677
7678         dsdb_get_extended_dn_guid(pdn->dsdb_dn->dn, &invocation_id, "RMD_INVOCID");
7679         dsdb_get_extended_dn_uint32(pdn->dsdb_dn->dn, &version, "RMD_VERSION");
7680         dsdb_get_extended_dn_nttime(pdn->dsdb_dn->dn, &change_time, "RMD_CHANGETIME");
7681
7682         return replmd_update_is_newer(&invocation_id,
7683                                       &la->meta_data.originating_invocation_id,
7684                                       version,
7685                                       la->meta_data.version,
7686                                       change_time,
7687                                       la->meta_data.originating_change_time);
7688 }
7689
7690 /**
7691  * Marks an existing linked attribute value as deleted in the DB
7692  * @param pdn the parsed-DN of the target-value to delete
7693  */
7694 static int replmd_delete_link_value(struct ldb_module *module,
7695                                     struct replmd_private *replmd_private,
7696                                     TALLOC_CTX *mem_ctx,
7697                                     struct ldb_dn *src_obj_dn,
7698                                     const struct dsdb_schema *schema,
7699                                     const struct dsdb_attribute *attr,
7700                                     uint64_t seq_num,
7701                                     bool is_active,
7702                                     struct GUID *target_guid,
7703                                     struct dsdb_dn *target_dsdb_dn,
7704                                     struct ldb_val *output_val)
7705 {
7706         struct ldb_context *ldb = ldb_module_get_ctx(module);
7707         time_t t;
7708         NTTIME now;
7709         const struct GUID *invocation_id = NULL;
7710         int ret;
7711
7712         t = time(NULL);
7713         unix_to_nt_time(&now, t);
7714
7715         invocation_id = samdb_ntds_invocation_id(ldb);
7716         if (invocation_id == NULL) {
7717                 return LDB_ERR_OPERATIONS_ERROR;
7718         }
7719
7720         /* if the existing link is active, remove its backlink */
7721         if (is_active) {
7722
7723                 /*
7724                  * NOTE WELL: After this we will never (at runtime) be
7725                  * able to find this forward link (for instant
7726                  * removal) if/when the link target is deleted.
7727                  *
7728                  * We have dbcheck rules to cover this and cope otherwise
7729                  * by filtering at runtime (i.e. in the extended_dn module).
7730                  */
7731                 ret = replmd_add_backlink(module, replmd_private, schema,
7732                                           src_obj_dn, target_guid, false,
7733                                           attr, NULL);
7734                 if (ret != LDB_SUCCESS) {
7735                         return ret;
7736                 }
7737         }
7738
7739         /* mark the existing value as deleted */
7740         ret = replmd_update_la_val(mem_ctx, output_val, target_dsdb_dn,
7741                                    target_dsdb_dn, invocation_id, seq_num,
7742                                    seq_num, now, true);
7743         return ret;
7744 }
7745
7746 /**
7747  * Checks for a conflict in single-valued link attributes, and tries to
7748  * resolve the problem if possible.
7749  *
7750  * Single-valued links should only ever have one active value. If we already
7751  * have an active link value, and during replication we receive an active link
7752  * value for a different target DN, then we need to resolve this inconsistency
7753  * and determine which value should be active. If the received info is better/
7754  * newer than the existing link attribute, then we need to set our existing
7755  * link as deleted. If the received info is worse/older, then we should continue
7756  * to add it, but set it as an inactive link.
7757  *
7758  * Note that this is a corner-case that is unlikely to happen (but if it does
7759  * happen, we don't want it to break replication completely).
7760  *
7761  * @param pdn_being_modified the parsed DN corresponding to the received link
7762  * target (note this is NULL if the link does not already exist in our DB)
7763  * @param pdn_list all the source object's Parsed-DNs for this attribute, i.e.
7764  * any existing active or inactive values for the attribute in our DB.
7765  * @param dsdb_dn the target DN for the received link attribute
7766  * @param add_as_inactive gets set to true if the received link is worse than
7767  * the existing link - it should still be added, but as an inactive link.
7768  */
7769 static int replmd_check_singleval_la_conflict(struct ldb_module *module,
7770                                               struct replmd_private *replmd_private,
7771                                               TALLOC_CTX *mem_ctx,
7772                                               struct ldb_dn *src_obj_dn,
7773                                               struct drsuapi_DsReplicaLinkedAttribute *la,
7774                                               struct dsdb_dn *dsdb_dn,
7775                                               struct parsed_dn *pdn_being_modified,
7776                                               struct parsed_dn *pdn_list,
7777                                               struct ldb_message_element *old_el,
7778                                               const struct dsdb_schema *schema,
7779                                               const struct dsdb_attribute *attr,
7780                                               uint64_t seq_num,
7781                                               bool *add_as_inactive)
7782 {
7783         struct parsed_dn *active_pdn = NULL;
7784         bool update_is_newer = false;
7785         int ret;
7786
7787         /*
7788          * check if there's a conflict for single-valued links, i.e. an active
7789          * linked attribute already exists, but it has a different target value
7790          */
7791         ret = replmd_get_active_singleval_link(module, mem_ctx, pdn_list,
7792                                                old_el->num_values, attr,
7793                                                &active_pdn);
7794
7795         if (ret != LDB_SUCCESS) {
7796                 return ret;
7797         }
7798
7799         /*
7800          * If no active value exists (or the received info is for the currently
7801          * active value), then no conflict exists
7802          */
7803         if (active_pdn == NULL || active_pdn == pdn_being_modified) {
7804                 return LDB_SUCCESS;
7805         }
7806
7807         DBG_WARNING("Link conflict for %s attribute on %s\n",
7808                     attr->lDAPDisplayName, ldb_dn_get_linearized(src_obj_dn));
7809
7810         /* Work out how to resolve the conflict based on which info is better */
7811         update_is_newer = replmd_link_update_is_newer(active_pdn, la);
7812
7813         if (update_is_newer) {
7814                 DBG_WARNING("Using received value %s, over existing target %s\n",
7815                             ldb_dn_get_linearized(dsdb_dn->dn),
7816                             ldb_dn_get_linearized(active_pdn->dsdb_dn->dn));
7817
7818                 /*
7819                  * Delete our existing active link. The received info will then
7820                  * be added (through normal link processing) as the active value
7821                  */
7822                 ret = replmd_delete_link_value(module, replmd_private, old_el,
7823                                                src_obj_dn, schema, attr,
7824                                                seq_num, true, &active_pdn->guid,
7825                                                active_pdn->dsdb_dn,
7826                                                active_pdn->v);
7827
7828                 if (ret != LDB_SUCCESS) {
7829                         return ret;
7830                 }
7831         } else {
7832                 DBG_WARNING("Using existing target %s, over received value %s\n",
7833                             ldb_dn_get_linearized(active_pdn->dsdb_dn->dn),
7834                             ldb_dn_get_linearized(dsdb_dn->dn));
7835
7836                 /*
7837                  * we want to keep our existing active link and add the
7838                  * received link as inactive
7839                  */
7840                 *add_as_inactive = true;
7841         }
7842
7843         return LDB_SUCCESS;
7844 }
7845
7846 /*
7847   process one linked attribute structure
7848  */
7849 static int replmd_process_linked_attribute(struct ldb_module *module,
7850                                            TALLOC_CTX *mem_ctx,
7851                                            struct replmd_private *replmd_private,
7852                                            struct ldb_message *msg,
7853                                            const struct dsdb_attribute *attr,
7854                                            struct la_entry *la_entry,
7855                                            struct ldb_request *parent)
7856 {
7857         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
7858         struct ldb_context *ldb = ldb_module_get_ctx(module);
7859         const struct dsdb_schema *schema = dsdb_get_schema(ldb, mem_ctx);
7860         int ret;
7861         struct dsdb_dn *dsdb_dn = NULL;
7862         uint64_t seq_num = 0;
7863         struct ldb_message_element *old_el;
7864         time_t t = time(NULL);
7865         struct parsed_dn *pdn_list, *pdn, *next;
7866         struct GUID guid = GUID_zero();
7867         bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)?true:false;
7868         bool ignore_link;
7869         struct dsdb_dn *old_dsdb_dn = NULL;
7870         struct ldb_val *val_to_update = NULL;
7871         bool add_as_inactive = false;
7872         WERROR status;
7873
7874         /* the value blob for the attribute holds the target object DN */
7875         status = dsdb_dn_la_from_blob(ldb, attr, schema, mem_ctx,
7876                                       la->value.blob, &dsdb_dn);
7877         if (!W_ERROR_IS_OK(status)) {
7878                 ldb_asprintf_errstring(ldb, "Failed to parsed linked attribute blob for %s on %s - %s\n",
7879                                        attr->lDAPDisplayName,
7880                                        ldb_dn_get_linearized(msg->dn),
7881                                        win_errstr(status));
7882                 return LDB_ERR_OPERATIONS_ERROR;
7883         }
7884
7885         old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName);
7886         if (old_el == NULL) {
7887                 ret = ldb_msg_add_empty(msg, attr->lDAPDisplayName, LDB_FLAG_MOD_REPLACE, &old_el);
7888                 if (ret != LDB_SUCCESS) {
7889                         ldb_module_oom(module);
7890                         return LDB_ERR_OPERATIONS_ERROR;
7891                 }
7892         } else {
7893                 old_el->flags = LDB_FLAG_MOD_REPLACE;
7894         }
7895
7896         /* parse the existing links */
7897         ret = get_parsed_dns_trusted(module, replmd_private, mem_ctx, old_el, &pdn_list,
7898                                      attr->syntax->ldap_oid, parent);
7899
7900         if (ret != LDB_SUCCESS) {
7901                 return ret;
7902         }
7903
7904         ret = replmd_check_target_exists(module, dsdb_dn, la_entry, msg->dn,
7905                                          true, &guid, &ignore_link);
7906
7907         if (ret != LDB_SUCCESS) {
7908                 return ret;
7909         }
7910
7911         /*
7912          * there are some cases where the target object doesn't exist, but it's
7913          * OK to ignore the linked attribute
7914          */
7915         if (ignore_link) {
7916                 return ret;
7917         }
7918
7919         /* see if this link already exists */
7920         ret = parsed_dn_find(ldb, pdn_list, old_el->num_values,
7921                              &guid,
7922                              dsdb_dn->dn,
7923                              dsdb_dn->extra_part, 0,
7924                              &pdn, &next,
7925                              attr->syntax->ldap_oid,
7926                              true);
7927         if (ret != LDB_SUCCESS) {
7928                 return ret;
7929         }
7930
7931         if (!replmd_link_update_is_newer(pdn, la)) {
7932                 DEBUG(3,("Discarding older DRS linked attribute update to %s on %s from %s\n",
7933                          old_el->name, ldb_dn_get_linearized(msg->dn),
7934                          GUID_string(mem_ctx, &la->meta_data.originating_invocation_id)));
7935                 return LDB_SUCCESS;
7936         }
7937
7938         /* get a seq_num for this change */
7939         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
7940         if (ret != LDB_SUCCESS) {
7941                 return ret;
7942         }
7943
7944         /*
7945          * check for single-valued link conflicts, i.e. an active linked
7946          * attribute already exists, but it has a different target value
7947          */
7948         if (active) {
7949                 ret = replmd_check_singleval_la_conflict(module, replmd_private,
7950                                                          mem_ctx, msg->dn, la,
7951                                                          dsdb_dn, pdn, pdn_list,
7952                                                          old_el, schema, attr,
7953                                                          seq_num,
7954                                                          &add_as_inactive);
7955                 if (ret != LDB_SUCCESS) {
7956                         return ret;
7957                 }
7958         }
7959
7960         if (pdn != NULL) {
7961                 uint32_t rmd_flags = dsdb_dn_rmd_flags(pdn->dsdb_dn->dn);
7962
7963                 if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
7964                         /* remove the existing backlink */
7965                         ret = replmd_add_backlink(module, replmd_private,
7966                                                   schema, 
7967                                                   msg->dn,
7968                                                   &pdn->guid, false, attr,
7969                                                   parent);
7970                         if (ret != LDB_SUCCESS) {
7971                                 return ret;
7972                         }
7973                 }
7974
7975                 val_to_update = pdn->v;
7976                 old_dsdb_dn = pdn->dsdb_dn;
7977
7978         } else {
7979                 unsigned offset;
7980
7981                 /*
7982                  * We know where the new one needs to be, from the *next
7983                  * pointer into pdn_list.
7984                  */
7985                 if (next == NULL) {
7986                         offset = old_el->num_values;
7987                 } else {
7988                         if (next->dsdb_dn == NULL) {
7989                                 ret = really_parse_trusted_dn(mem_ctx, ldb, next,
7990                                                               attr->syntax->ldap_oid);
7991                                 if (ret != LDB_SUCCESS) {
7992                                         return ret;
7993                                 }
7994                         }
7995                         offset = next - pdn_list;
7996                         if (offset > old_el->num_values) {
7997                                 return LDB_ERR_OPERATIONS_ERROR;
7998                         }
7999                 }
8000
8001                 old_el->values = talloc_realloc(msg->elements, old_el->values,
8002                                                 struct ldb_val, old_el->num_values+1);
8003                 if (!old_el->values) {
8004                         ldb_module_oom(module);
8005                         return LDB_ERR_OPERATIONS_ERROR;
8006                 }
8007
8008                 if (offset != old_el->num_values) {
8009                         memmove(&old_el->values[offset + 1], &old_el->values[offset],
8010                                 (old_el->num_values - offset) * sizeof(old_el->values[0]));
8011                 }
8012
8013                 old_el->num_values++;
8014
8015                 val_to_update = &old_el->values[offset];
8016                 old_dsdb_dn = NULL;
8017         }
8018
8019         /* set the link attribute's value to the info that was received */
8020         ret = replmd_set_la_val(mem_ctx, val_to_update, dsdb_dn, old_dsdb_dn,
8021                                 &la->meta_data.originating_invocation_id,
8022                                 la->meta_data.originating_usn, seq_num,
8023                                 la->meta_data.originating_change_time,
8024                                 la->meta_data.version,
8025                                 !active);
8026         if (ret != LDB_SUCCESS) {
8027                 return ret;
8028         }
8029
8030         if (add_as_inactive) {
8031
8032                 /* Set the new link as inactive/deleted to avoid conflicts */
8033                 ret = replmd_delete_link_value(module, replmd_private, old_el,
8034                                                msg->dn, schema, attr, seq_num,
8035                                                false, &guid, dsdb_dn,
8036                                                val_to_update);
8037
8038                 if (ret != LDB_SUCCESS) {
8039                         return ret;
8040                 }
8041
8042         } else if (active) {
8043
8044                 /* if the new link is active, then add the new backlink */
8045                 ret = replmd_add_backlink(module, replmd_private,
8046                                           schema,
8047                                           msg->dn,
8048                                           &guid, true, attr,
8049                                           parent);
8050                 if (ret != LDB_SUCCESS) {
8051                         return ret;
8052                 }
8053         }
8054
8055         /* we only change whenChanged and uSNChanged if the seq_num
8056            has changed */
8057         ldb_msg_remove_attr(msg, "whenChanged");
8058         ldb_msg_remove_attr(msg, "uSNChanged");
8059         ret = add_time_element(msg, "whenChanged", t);
8060         if (ret != LDB_SUCCESS) {
8061                 ldb_operr(ldb);
8062                 return ret;
8063         }
8064
8065         ret = add_uint64_element(ldb, msg, "uSNChanged", seq_num);
8066         if (ret != LDB_SUCCESS) {
8067                 ldb_operr(ldb);
8068                 return ret;
8069         }
8070
8071         old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName);
8072         if (old_el == NULL) {
8073                 return ldb_operr(ldb);
8074         }
8075
8076         ret = dsdb_check_single_valued_link(attr, old_el);
8077         if (ret != LDB_SUCCESS) {
8078                 return ret;
8079         }
8080
8081         old_el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
8082
8083         return ret;
8084 }
8085
8086 static int replmd_extended(struct ldb_module *module, struct ldb_request *req)
8087 {
8088         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) {
8089                 return replmd_extended_replicated_objects(module, req);
8090         }
8091
8092         return ldb_next_request(module, req);
8093 }
8094
8095
8096 /*
8097   we hook into the transaction operations to allow us to
8098   perform the linked attribute updates at the end of the whole
8099   transaction. This allows a forward linked attribute to be created
8100   before the object is created. During a vampire, w2k8 sends us linked
8101   attributes before the objects they are part of.
8102  */
8103 static int replmd_start_transaction(struct ldb_module *module)
8104 {
8105         /* create our private structure for this transaction */
8106         struct replmd_private *replmd_private = talloc_get_type(ldb_module_get_private(module),
8107                                                                 struct replmd_private);
8108         replmd_txn_cleanup(replmd_private);
8109
8110         /* free any leftover mod_usn records from cancelled
8111            transactions */
8112         while (replmd_private->ncs) {
8113                 struct nc_entry *e = replmd_private->ncs;
8114                 DLIST_REMOVE(replmd_private->ncs, e);
8115                 talloc_free(e);
8116         }
8117
8118         replmd_private->originating_updates = false;
8119
8120         return ldb_next_start_trans(module);
8121 }
8122
8123 /**
8124  * Processes a group of linked attributes that apply to the same source-object
8125  * and attribute-ID
8126  */
8127 static int replmd_process_la_group(struct ldb_module *module,
8128                                    struct replmd_private *replmd_private,
8129                                    struct la_group *la_group)
8130 {
8131         struct la_entry *la = NULL;
8132         struct la_entry *prev = NULL;
8133         int ret;
8134         TALLOC_CTX *tmp_ctx = talloc_new(la_group);
8135         struct la_entry *first_la = DLIST_TAIL(la_group->la_entries);
8136         struct ldb_message *msg = NULL;
8137         enum deletion_state deletion_state = OBJECT_NOT_DELETED;
8138         struct ldb_context *ldb = ldb_module_get_ctx(module);
8139         const struct dsdb_attribute *attr = NULL;
8140
8141         /*
8142          * get the attribute being modified and the search result for the
8143          * source object
8144          */
8145         ret = replmd_get_la_entry_source(module, first_la, tmp_ctx, &attr,
8146                                          &msg);
8147
8148         if (ret != LDB_SUCCESS) {
8149                 return ret;
8150         }
8151
8152         /*
8153          * Check for deleted objects per MS-DRSR 4.1.10.6.14
8154          * ProcessLinkValue, because link updates are not applied to
8155          * recycled and tombstone objects.  We don't have to delete
8156          * any existing link, that should have happened when the
8157          * object deletion was replicated or initiated.
8158          *
8159          * This needs isDeleted and isRecycled to be included as
8160          * attributes in the search and so in msg if set.
8161          */
8162         replmd_deletion_state(module, msg, &deletion_state, NULL);
8163
8164         if (deletion_state >= OBJECT_RECYCLED) {
8165                 TALLOC_FREE(tmp_ctx);
8166                 return LDB_SUCCESS;
8167         }
8168
8169         /*
8170          * Now that we know the deletion_state, remove the extra
8171          * attributes added for that purpose.  We need to do this
8172          * otherwise in the case of isDeleted: FALSE the modify will
8173          * fail with:
8174          *
8175          * Failed to apply linked attribute change 'attribute 'isDeleted':
8176          * invalid modify flags on
8177          * 'CN=g1_1527570609273,CN=Users,DC=samba,DC=example,DC=com':
8178          * 0x0'
8179          *
8180          * This is becaue isDeleted is a Boolean, so FALSE is a
8181          * legitimate value (set by Samba's deletetest.py)
8182          */
8183         ldb_msg_remove_attr(msg, "isDeleted");
8184         ldb_msg_remove_attr(msg, "isRecycled");
8185
8186         /* go through and process the link targets for this source object */
8187         for (la = DLIST_TAIL(la_group->la_entries); la; la=prev) {
8188                 prev = DLIST_PREV(la);
8189                 DLIST_REMOVE(la_group->la_entries, la);
8190                 ret = replmd_process_linked_attribute(module, tmp_ctx,
8191                                                       replmd_private,
8192                                                       msg, attr, la, NULL);
8193                 if (ret != LDB_SUCCESS) {
8194                         replmd_txn_cleanup(replmd_private);
8195                         return ret;
8196                 }
8197
8198                 if ((++replmd_private->num_processed % 8192) == 0) {
8199                         DBG_NOTICE("Processed %u/%u linked attributes\n",
8200                                    replmd_private->num_processed,
8201                                    replmd_private->total_links);
8202                 }
8203         }
8204
8205         /* apply the link changes to the source object */
8206         ret = linked_attr_modify(module, msg, NULL);
8207         if (ret != LDB_SUCCESS) {
8208                 ldb_debug(ldb, LDB_DEBUG_WARNING,
8209                           "Failed to apply linked attribute change '%s'\n%s\n",
8210                           ldb_errstring(ldb),
8211                           ldb_ldif_message_redacted_string(ldb,
8212                                                            tmp_ctx,
8213                                                            LDB_CHANGETYPE_MODIFY,
8214                                                            msg));
8215                 TALLOC_FREE(tmp_ctx);
8216                 return ret;
8217         }
8218
8219         TALLOC_FREE(tmp_ctx);
8220         return LDB_SUCCESS;
8221 }
8222
8223 /*
8224   on prepare commit we loop over our queued la_context structures and
8225   apply each of them
8226  */
8227 static int replmd_prepare_commit(struct ldb_module *module)
8228 {
8229         struct replmd_private *replmd_private =
8230                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
8231         struct la_group *la_group, *prev;
8232         int ret;
8233
8234         if (replmd_private->la_list != NULL) {
8235                 DBG_NOTICE("Processing linked attributes\n");
8236         }
8237
8238         /*
8239          * Walk the list of linked attributes from DRS replication.
8240          *
8241          * We walk backwards, to do the first entry first, as we
8242          * added the entries with DLIST_ADD() which puts them at the
8243          * start of the list
8244          *
8245          * Links are grouped together so we process links for the same
8246          * source object in one go.
8247          */
8248         for (la_group = DLIST_TAIL(replmd_private->la_list);
8249              la_group != NULL;
8250              la_group = prev) {
8251
8252                 prev = DLIST_PREV(la_group);
8253                 DLIST_REMOVE(replmd_private->la_list, la_group);
8254                 ret = replmd_process_la_group(module, replmd_private,
8255                                               la_group);
8256                 if (ret != LDB_SUCCESS) {
8257                         replmd_txn_cleanup(replmd_private);
8258                         return ret;
8259                 }
8260         }
8261
8262         replmd_txn_cleanup(replmd_private);
8263
8264         /* possibly change @REPLCHANGED */
8265         ret = replmd_notify_store(module, NULL);
8266         if (ret != LDB_SUCCESS) {
8267                 return ret;
8268         }
8269
8270         return ldb_next_prepare_commit(module);
8271 }
8272
8273 static int replmd_del_transaction(struct ldb_module *module)
8274 {
8275         struct replmd_private *replmd_private =
8276                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
8277         replmd_txn_cleanup(replmd_private);
8278
8279         return ldb_next_del_trans(module);
8280 }
8281
8282
8283 static const struct ldb_module_ops ldb_repl_meta_data_module_ops = {
8284         .name          = "repl_meta_data",
8285         .init_context      = replmd_init,
8286         .add               = replmd_add,
8287         .modify            = replmd_modify,
8288         .rename            = replmd_rename,
8289         .del               = replmd_delete,
8290         .extended          = replmd_extended,
8291         .start_transaction = replmd_start_transaction,
8292         .prepare_commit    = replmd_prepare_commit,
8293         .del_transaction   = replmd_del_transaction,
8294 };
8295
8296 int ldb_repl_meta_data_module_init(const char *version)
8297 {
8298         LDB_MODULE_CHECK_VERSION(version);
8299         return ldb_register_module(&ldb_repl_meta_data_module_ops);
8300 }