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