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