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