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