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