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