replmd: Avoid duplicated debug/warnings
[sfrench/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / repl_meta_data.c
1 /*
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004-2008
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2013
6    Copyright (C) Andrew Tridgell 2005-2009
7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
8    Copyright (C) Matthieu Patou <mat@samba.org> 2010-2011
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb repl_meta_data module
28  *
29  *  Description: - add a unique objectGUID onto every new record,
30  *               - handle whenCreated, whenChanged timestamps
31  *               - handle uSNCreated, uSNChanged numbers
32  *               - handle replPropertyMetaData attribute
33  *
34  *  Author: Simo Sorce
35  *  Author: Stefan Metzmacher
36  */
37
38 #include "includes.h"
39 #include "ldb_module.h"
40 #include "dsdb/samdb/samdb.h"
41 #include "dsdb/common/proto.h"
42 #include "dsdb/common/util.h"
43 #include "../libds/common/flags.h"
44 #include "librpc/gen_ndr/irpc.h"
45 #include "librpc/gen_ndr/ndr_misc.h"
46 #include "librpc/gen_ndr/ndr_drsuapi.h"
47 #include "librpc/gen_ndr/ndr_drsblobs.h"
48 #include "param/param.h"
49 #include "libcli/security/security.h"
50 #include "lib/util/dlinklist.h"
51 #include "dsdb/samdb/ldb_modules/util.h"
52 #include "lib/util/tsort.h"
53
54 #undef DBGC_CLASS
55 #define DBGC_CLASS            DBGC_DRS_REPL
56
57 /*
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                                 uint32_t version, 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, 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   update an extended DN, including all meta data fields
2294
2295   see replmd_build_la_val for value names
2296  */
2297 static int replmd_update_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         uint32_t old_version;
2310         NTSTATUS status;
2311         int ret;
2312         const char *dnstring;
2313         char *vstring;
2314         uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
2315
2316         tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
2317         if (!tstring) {
2318                 return LDB_ERR_OPERATIONS_ERROR;
2319         }
2320         tval = data_blob_string_const(tstring);
2321
2322         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)usn);
2323         if (!usn_string) {
2324                 return LDB_ERR_OPERATIONS_ERROR;
2325         }
2326         usnv = data_blob_string_const(usn_string);
2327
2328         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)local_usn);
2329         if (!usn_string) {
2330                 return LDB_ERR_OPERATIONS_ERROR;
2331         }
2332         local_usnv = data_blob_string_const(usn_string);
2333
2334         status = GUID_to_ndr_blob(invocation_id, dn, &iid);
2335         if (!NT_STATUS_IS_OK(status)) {
2336                 return LDB_ERR_OPERATIONS_ERROR;
2337         }
2338
2339         flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
2340         if (!flags_string) {
2341                 return LDB_ERR_OPERATIONS_ERROR;
2342         }
2343         flagsv = data_blob_string_const(flags_string);
2344
2345         ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
2346         if (ret != LDB_SUCCESS) return ret;
2347
2348         /* get the ADDTIME from the original */
2349         old_addtime = ldb_dn_get_extended_component(old_dsdb_dn->dn, "RMD_ADDTIME");
2350         if (old_addtime == NULL) {
2351                 old_addtime = &tval;
2352         }
2353         if (dsdb_dn != old_dsdb_dn ||
2354             ldb_dn_get_extended_component(dn, "RMD_ADDTIME") == NULL) {
2355                 ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime);
2356                 if (ret != LDB_SUCCESS) return ret;
2357         }
2358
2359         /* use our invocation id */
2360         ret = ldb_dn_set_extended_component(dn, "RMD_INVOCID", &iid);
2361         if (ret != LDB_SUCCESS) return ret;
2362
2363         /* changetime is the current time */
2364         ret = ldb_dn_set_extended_component(dn, "RMD_CHANGETIME", &tval);
2365         if (ret != LDB_SUCCESS) return ret;
2366
2367         /* update the USN */
2368         ret = ldb_dn_set_extended_component(dn, "RMD_ORIGINATING_USN", &usnv);
2369         if (ret != LDB_SUCCESS) return ret;
2370
2371         ret = ldb_dn_set_extended_component(dn, "RMD_LOCAL_USN", &local_usnv);
2372         if (ret != LDB_SUCCESS) return ret;
2373
2374         /* increase the version by 1 */
2375         status = dsdb_get_extended_dn_uint32(old_dsdb_dn->dn, &old_version, "RMD_VERSION");
2376         if (NT_STATUS_IS_OK(status) && old_version >= version) {
2377                 version = old_version+1;
2378         }
2379         vstring = talloc_asprintf(dn, "%lu", (unsigned long)version);
2380         vers = data_blob_string_const(vstring);
2381         ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
2382         if (ret != LDB_SUCCESS) return ret;
2383
2384         dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
2385         if (dnstring == NULL) {
2386                 return LDB_ERR_OPERATIONS_ERROR;
2387         }
2388         *v = data_blob_string_const(dnstring);
2389
2390         return LDB_SUCCESS;
2391 }
2392
2393 /*
2394   handle adding a linked attribute
2395  */
2396 static int replmd_modify_la_add(struct ldb_module *module,
2397                                 struct replmd_private *replmd_private,
2398                                 const struct dsdb_schema *schema,
2399                                 struct ldb_message *msg,
2400                                 struct ldb_message_element *el,
2401                                 struct ldb_message_element *old_el,
2402                                 const struct dsdb_attribute *schema_attr,
2403                                 uint64_t seq_num,
2404                                 time_t t,
2405                                 struct ldb_dn *msg_dn,
2406                                 struct ldb_request *parent)
2407 {
2408         unsigned int i, j;
2409         struct parsed_dn *dns, *old_dns;
2410         TALLOC_CTX *tmp_ctx = talloc_new(msg);
2411         int ret;
2412         struct ldb_val *new_values = NULL;
2413         unsigned old_num_values = old_el ? old_el->num_values : 0;
2414         unsigned num_values = 0;
2415         unsigned max_num_values;
2416         const struct GUID *invocation_id;
2417         struct ldb_context *ldb = ldb_module_get_ctx(module);
2418         NTTIME now;
2419         unix_to_nt_time(&now, t);
2420
2421         invocation_id = samdb_ntds_invocation_id(ldb);
2422         if (!invocation_id) {
2423                 talloc_free(tmp_ctx);
2424                 return LDB_ERR_OPERATIONS_ERROR;
2425         }
2426
2427         /* get the DNs to be added, fully parsed.
2428          *
2429          * We need full parsing because they came off the wire and we don't
2430          * trust them, besides which we need their details to know where to put
2431          * them.
2432          */
2433         ret = get_parsed_dns(module, tmp_ctx, el, &dns,
2434                              schema_attr->syntax->ldap_oid, parent);
2435         if (ret != LDB_SUCCESS) {
2436                 talloc_free(tmp_ctx);
2437                 return ret;
2438         }
2439
2440         /* get the existing DNs, lazily parsed */
2441         ret = get_parsed_dns_trusted(module, replmd_private,
2442                                      tmp_ctx, old_el, &old_dns,
2443                                      schema_attr->syntax->ldap_oid, parent);
2444
2445         if (ret != LDB_SUCCESS) {
2446                 talloc_free(tmp_ctx);
2447                 return ret;
2448         }
2449
2450         max_num_values = old_num_values + el->num_values;
2451         if (max_num_values < old_num_values) {
2452                 DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. "
2453                           "old values: %u, new values: %u, sum: %u",
2454                           old_num_values, el->num_values, max_num_values));
2455                 talloc_free(tmp_ctx);
2456                 return LDB_ERR_OPERATIONS_ERROR;
2457         }
2458
2459         new_values = talloc_zero_array(tmp_ctx, struct ldb_val, max_num_values);
2460
2461         if (new_values == NULL) {
2462                 ldb_module_oom(module);
2463                 talloc_free(tmp_ctx);
2464                 return LDB_ERR_OPERATIONS_ERROR;
2465         }
2466
2467         /*
2468          * For each new value, find where it would go in the list. If there is
2469          * a matching GUID there, we update the existing value; otherwise we
2470          * put it in place.
2471          */
2472         j = 0;
2473         for (i = 0; i < el->num_values; i++) {
2474                 struct parsed_dn *exact;
2475                 struct parsed_dn *next;
2476                 unsigned offset;
2477                 int err = parsed_dn_find(ldb, old_dns, old_num_values,
2478                                          &dns[i].guid,
2479                                          dns[i].dsdb_dn->dn,
2480                                          dns[i].dsdb_dn->extra_part, 0,
2481                                          &exact, &next,
2482                                          schema_attr->syntax->ldap_oid,
2483                                          true);
2484                 if (err != LDB_SUCCESS) {
2485                         talloc_free(tmp_ctx);
2486                         return err;
2487                 }
2488
2489                 if (exact != NULL) {
2490                         /*
2491                          * We are trying to add one that exists, which is only
2492                          * allowed if it was previously deleted.
2493                          *
2494                          * When we do undelete a link we change it in place.
2495                          * It will be copied across into the right spot in due
2496                          * course.
2497                          */
2498                         uint32_t rmd_flags;
2499                         rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2500
2501                         if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
2502                                 struct GUID_txt_buf guid_str;
2503                                 ldb_asprintf_errstring(ldb,
2504                                                        "Attribute %s already "
2505                                                        "exists for target GUID %s",
2506                                                        el->name,
2507                                                        GUID_buf_string(&exact->guid,
2508                                                                        &guid_str));
2509                                 talloc_free(tmp_ctx);
2510                                 /* error codes for 'member' need to be
2511                                    special cased */
2512                                 if (ldb_attr_cmp(el->name, "member") == 0) {
2513                                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
2514                                 } else {
2515                                         return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2516                                 }
2517                         }
2518
2519                         ret = replmd_update_la_val(new_values, exact->v,
2520                                                    dns[i].dsdb_dn,
2521                                                    exact->dsdb_dn,
2522                                                    invocation_id, seq_num,
2523                                                    seq_num, now, 0, false);
2524                         if (ret != LDB_SUCCESS) {
2525                                 talloc_free(tmp_ctx);
2526                                 return ret;
2527                         }
2528
2529                         ret = replmd_add_backlink(module, replmd_private,
2530                                                   schema,
2531                                                   msg_dn,
2532                                                   &dns[i].guid, 
2533                                                   true,
2534                                                   schema_attr,
2535                                                   parent);
2536                         if (ret != LDB_SUCCESS) {
2537                                 talloc_free(tmp_ctx);
2538                                 return ret;
2539                                 }
2540                         continue;
2541                 }
2542                 /*
2543                  * Here we don't have an exact match.
2544                  *
2545                  * If next is NULL, this one goes beyond the end of the
2546                  * existing list, so we need to add all of those ones first.
2547                  *
2548                  * If next is not NULL, we need to add all the ones before
2549                  * next.
2550                  */
2551                 if (next == NULL) {
2552                         offset = old_num_values;
2553                 } else {
2554                         /* next should have been parsed, but let's make sure */
2555                         if (next->dsdb_dn == NULL) {
2556                                 ret = really_parse_trusted_dn(tmp_ctx, ldb, next,
2557                                                               schema_attr->syntax->ldap_oid);
2558                                 if (ret != LDB_SUCCESS) {
2559                                         return ret;
2560                                 }
2561                         }
2562                         offset = MIN(next - old_dns, old_num_values);
2563                 }
2564
2565                 /* put all the old ones before next on the list */
2566                 for (; j < offset; j++) {
2567                         new_values[num_values] = *old_dns[j].v;
2568                         num_values++;
2569                 }
2570
2571                 ret = replmd_add_backlink(module, replmd_private,
2572                                           schema, msg_dn,
2573                                           &dns[i].guid,
2574                                           true, schema_attr,
2575                                           parent);
2576                 /* Make the new linked attribute ldb_val. */
2577                 ret = replmd_build_la_val(new_values, &new_values[num_values],
2578                                           dns[i].dsdb_dn, invocation_id,
2579                                           seq_num, seq_num,
2580                                           now, 0, false);
2581                 if (ret != LDB_SUCCESS) {
2582                         talloc_free(tmp_ctx);
2583                         return ret;
2584                 }
2585                 num_values++;
2586                 if (ret != LDB_SUCCESS) {
2587                         talloc_free(tmp_ctx);
2588                         return ret;
2589                 }
2590         }
2591         /* copy the rest of the old ones (if any) */
2592         for (; j < old_num_values; j++) {
2593                 new_values[num_values] = *old_dns[j].v;
2594                 num_values++;
2595         }
2596
2597         talloc_steal(msg->elements, new_values);
2598         if (old_el != NULL) {
2599                 talloc_steal(msg->elements, old_el->values);
2600         }
2601         el->values = new_values;
2602         el->num_values = num_values;
2603
2604         talloc_free(tmp_ctx);
2605
2606         /* we now tell the backend to replace all existing values
2607            with the one we have constructed */
2608         el->flags = LDB_FLAG_MOD_REPLACE;
2609
2610         return LDB_SUCCESS;
2611 }
2612
2613
2614 /*
2615   handle deleting all active linked attributes
2616  */
2617 static int replmd_modify_la_delete(struct ldb_module *module,
2618                                    struct replmd_private *replmd_private,
2619                                    const struct dsdb_schema *schema,
2620                                    struct ldb_message *msg,
2621                                    struct ldb_message_element *el,
2622                                    struct ldb_message_element *old_el,
2623                                    const struct dsdb_attribute *schema_attr,
2624                                    uint64_t seq_num,
2625                                    time_t t,
2626                                    struct ldb_dn *msg_dn,
2627                                    struct ldb_request *parent)
2628 {
2629         unsigned int i;
2630         struct parsed_dn *dns, *old_dns;
2631         TALLOC_CTX *tmp_ctx = NULL;
2632         int ret;
2633         struct ldb_context *ldb = ldb_module_get_ctx(module);
2634         struct ldb_control *vanish_links_ctrl = NULL;
2635         bool vanish_links = false;
2636         unsigned int num_to_delete = el->num_values;
2637         uint32_t rmd_flags;
2638         const struct GUID *invocation_id;
2639         NTTIME now;
2640
2641         unix_to_nt_time(&now, t);
2642
2643         invocation_id = samdb_ntds_invocation_id(ldb);
2644         if (!invocation_id) {
2645                 return LDB_ERR_OPERATIONS_ERROR;
2646         }
2647
2648         if (old_el == NULL || old_el->num_values == 0) {
2649                 /* there is nothing to delete... */
2650                 if (num_to_delete == 0) {
2651                         /* and we're deleting nothing, so that's OK */
2652                         return LDB_SUCCESS;
2653                 }
2654                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2655         }
2656
2657         tmp_ctx = talloc_new(msg);
2658         if (tmp_ctx == NULL) {
2659                 return LDB_ERR_OPERATIONS_ERROR;
2660         }
2661
2662         ret = get_parsed_dns(module, tmp_ctx, el, &dns,
2663                              schema_attr->syntax->ldap_oid, parent);
2664         if (ret != LDB_SUCCESS) {
2665                 talloc_free(tmp_ctx);
2666                 return ret;
2667         }
2668
2669         ret = get_parsed_dns_trusted(module, replmd_private,
2670                                      tmp_ctx, old_el, &old_dns,
2671                                      schema_attr->syntax->ldap_oid, parent);
2672
2673         if (ret != LDB_SUCCESS) {
2674                 talloc_free(tmp_ctx);
2675                 return ret;
2676         }
2677
2678         if (parent) {
2679                 vanish_links_ctrl = ldb_request_get_control(parent, DSDB_CONTROL_REPLMD_VANISH_LINKS);
2680                 if (vanish_links_ctrl) {
2681                         vanish_links = true;
2682                         vanish_links_ctrl->critical = false;
2683                 }
2684         }
2685
2686         /* we empty out el->values here to avoid damage if we return early. */
2687         el->num_values = 0;
2688         el->values = NULL;
2689
2690         /*
2691          * If vanish links is set, we are actually removing members of
2692          *  old_el->values; otherwise we are just marking them deleted.
2693          *
2694          * There is a special case when no values are given: we remove them
2695          * all. When we have the vanish_links control we just have to remove
2696          * the backlinks and change our element to replace the existing values
2697          * with the empty list.
2698          */
2699
2700         if (num_to_delete == 0) {
2701                 for (i = 0; i < old_el->num_values; i++) {
2702                         struct parsed_dn *p = &old_dns[i];
2703                         if (p->dsdb_dn == NULL) {
2704                                 ret = really_parse_trusted_dn(tmp_ctx, ldb, p,
2705                                                               schema_attr->syntax->ldap_oid);
2706                                 if (ret != LDB_SUCCESS) {
2707                                         return ret;
2708                                 }
2709                         }
2710                         ret = replmd_add_backlink(module, replmd_private,
2711                                                   schema, msg_dn, &p->guid,
2712                                                   false, schema_attr,
2713                                                   parent);
2714                         if (ret != LDB_SUCCESS) {
2715                                 talloc_free(tmp_ctx);
2716                                 return ret;
2717                         }
2718                         if (vanish_links) {
2719                                 continue;
2720                         }
2721
2722                         rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
2723                         if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
2724                                 continue;
2725                         }
2726
2727                         ret = replmd_update_la_val(old_el->values, p->v,
2728                                                    p->dsdb_dn, p->dsdb_dn,
2729                                                    invocation_id, seq_num,
2730                                                    seq_num, now, 0, true);
2731                         if (ret != LDB_SUCCESS) {
2732                                 talloc_free(tmp_ctx);
2733                                 return ret;
2734                         }
2735                 }
2736
2737                 if (vanish_links) {
2738                         el->flags = LDB_FLAG_MOD_REPLACE;
2739                         talloc_free(tmp_ctx);
2740                         return LDB_SUCCESS;
2741                 }
2742         }
2743
2744
2745         for (i = 0; i < num_to_delete; i++) {
2746                 struct parsed_dn *p = &dns[i];
2747                 struct parsed_dn *exact = NULL;
2748                 struct parsed_dn *next = NULL;
2749                 ret = parsed_dn_find(ldb, old_dns, old_el->num_values,
2750                                      &p->guid,
2751                                      NULL,
2752                                      p->dsdb_dn->extra_part, 0,
2753                                      &exact, &next,
2754                                      schema_attr->syntax->ldap_oid,
2755                                      true);
2756                 if (ret != LDB_SUCCESS) {
2757                         talloc_free(tmp_ctx);
2758                         return ret;
2759                 }
2760                 if (exact == NULL) {
2761                         struct GUID_txt_buf buf;
2762                         ldb_asprintf_errstring(ldb, "Attribute %s doesn't "
2763                                                "exist for target GUID %s",
2764                                                el->name,
2765                                                GUID_buf_string(&p->guid, &buf));
2766                         if (ldb_attr_cmp(el->name, "member") == 0) {
2767                                 talloc_free(tmp_ctx);
2768                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2769                         } else {
2770                                 talloc_free(tmp_ctx);
2771                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2772                         }
2773                 }
2774
2775                 if (vanish_links) {
2776                         if (CHECK_DEBUGLVL(5)) {
2777                                 rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2778                                 if ((rmd_flags & DSDB_RMD_FLAG_DELETED)) {
2779                                         struct GUID_txt_buf buf;
2780                                         const char *guid_str = \
2781                                                 GUID_buf_string(&p->guid, &buf);
2782                                         DEBUG(5, ("Deleting deleted linked "
2783                                                   "attribute %s to %s, because "
2784                                                   "vanish_links control is set\n",
2785                                                   el->name, guid_str));
2786                                 }
2787                         }
2788
2789                         /* remove the backlink */
2790                         ret = replmd_add_backlink(module,
2791                                                   replmd_private,
2792                                                   schema, 
2793                                                   msg_dn,
2794                                                   &p->guid,
2795                                                   false, schema_attr,
2796                                                   parent);
2797                         if (ret != LDB_SUCCESS) {
2798                                 talloc_free(tmp_ctx);
2799                                 return ret;
2800                         }
2801
2802                         /* We flag the deletion and tidy it up later. */
2803                         exact->v = NULL;
2804                         continue;
2805                 }
2806
2807                 rmd_flags = dsdb_dn_rmd_flags(exact->dsdb_dn->dn);
2808
2809                 if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
2810                         struct GUID_txt_buf buf;
2811                         const char *guid_str = GUID_buf_string(&p->guid, &buf);
2812                         ldb_asprintf_errstring(ldb, "Attribute %s already "
2813                                                "deleted for target GUID %s",
2814                                                el->name, guid_str);
2815                         if (ldb_attr_cmp(el->name, "member") == 0) {
2816                                 talloc_free(tmp_ctx);
2817                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2818                         } else {
2819                                 talloc_free(tmp_ctx);
2820                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2821                         }
2822                 }
2823
2824                 ret = replmd_update_la_val(old_el->values, exact->v,
2825                                            exact->dsdb_dn, exact->dsdb_dn,
2826                                            invocation_id, seq_num, seq_num,
2827                                            now, 0, true);
2828                 if (ret != LDB_SUCCESS) {
2829                         talloc_free(tmp_ctx);
2830                         return ret;
2831                 }
2832                 ret = replmd_add_backlink(module, replmd_private,
2833                                           schema, msg_dn,
2834                                           &p->guid,
2835                                           false, schema_attr,
2836                                           parent);
2837                 if (ret != LDB_SUCCESS) {
2838                         talloc_free(tmp_ctx);
2839                         return ret;
2840                 }
2841         }
2842
2843         if (vanish_links) {
2844                 unsigned j = 0;
2845                 for (i = 0; i < old_el->num_values; i++) {
2846                         if (old_dns[i].v != NULL) {
2847                                 old_el->values[j] = *old_dns[i].v;
2848                                 j++;
2849                         }
2850                 }
2851                 old_el->num_values = j;
2852         }
2853
2854         el->values = talloc_steal(msg->elements, old_el->values);
2855         el->num_values = old_el->num_values;
2856
2857         talloc_free(tmp_ctx);
2858
2859         /* we now tell the backend to replace all existing values
2860            with the one we have constructed */
2861         el->flags = LDB_FLAG_MOD_REPLACE;
2862
2863         return LDB_SUCCESS;
2864 }
2865
2866 /*
2867   handle replacing a linked attribute
2868  */
2869 static int replmd_modify_la_replace(struct ldb_module *module,
2870                                     struct replmd_private *replmd_private,
2871                                     const struct dsdb_schema *schema,
2872                                     struct ldb_message *msg,
2873                                     struct ldb_message_element *el,
2874                                     struct ldb_message_element *old_el,
2875                                     const struct dsdb_attribute *schema_attr,
2876                                     uint64_t seq_num,
2877                                     time_t t,
2878                                     struct ldb_dn *msg_dn,
2879                                     struct ldb_request *parent)
2880 {
2881         unsigned int i, old_i, new_i;
2882         struct parsed_dn *dns, *old_dns;
2883         TALLOC_CTX *tmp_ctx = talloc_new(msg);
2884         int ret;
2885         const struct GUID *invocation_id;
2886         struct ldb_context *ldb = ldb_module_get_ctx(module);
2887         struct ldb_val *new_values = NULL;
2888         const char *ldap_oid = schema_attr->syntax->ldap_oid;
2889         unsigned int old_num_values;
2890         unsigned int repl_num_values;
2891         unsigned int max_num_values;
2892         NTTIME now;
2893
2894         unix_to_nt_time(&now, t);
2895
2896         invocation_id = samdb_ntds_invocation_id(ldb);
2897         if (!invocation_id) {
2898                 return LDB_ERR_OPERATIONS_ERROR;
2899         }
2900
2901         /*
2902          * The replace operation is unlike the replace and delete cases in that
2903          * we need to look at every existing link to see whether it is being
2904          * retained or deleted. In other words, we can't avoid parsing the GUIDs.
2905          *
2906          * As we are trying to combine two sorted lists, the algorithm we use
2907          * is akin to the merge phase of a merge sort. We interleave the two
2908          * lists, doing different things depending on which side the current
2909          * item came from.
2910          *
2911          * There are three main cases, with some sub-cases.
2912          *
2913          *  - a DN is in the old list but not the new one. It needs to be
2914          *    marked as deleted (but left in the list).
2915          *     - maybe it is already deleted, and we have less to do.
2916          *
2917          *  - a DN is in both lists. The old data gets replaced by the new,
2918          *    and the list doesn't grow. The old link may have been marked as
2919          *    deleted, in which case we undelete it.
2920          *
2921          *  - a DN is in the new list only. We add it in the right place.
2922          */
2923
2924         old_num_values = old_el ? old_el->num_values : 0;
2925         repl_num_values = el->num_values;
2926         max_num_values = old_num_values + repl_num_values;
2927
2928         if (max_num_values == 0) {
2929                 /* There is nothing to do! */
2930                 return LDB_SUCCESS;
2931         }
2932
2933         ret = get_parsed_dns(module, tmp_ctx, el, &dns, ldap_oid, parent);
2934         if (ret != LDB_SUCCESS) {
2935                 talloc_free(tmp_ctx);
2936                 return ret;
2937         }
2938
2939         ret = get_parsed_dns(module, tmp_ctx, old_el, &old_dns,
2940                              ldap_oid, parent);
2941         if (ret != LDB_SUCCESS) {
2942                 talloc_free(tmp_ctx);
2943                 return ret;
2944         }
2945
2946         ret = replmd_check_upgrade_links(ldb, old_dns, old_num_values,
2947                                          old_el, ldap_oid);
2948         if (ret != LDB_SUCCESS) {
2949                 talloc_free(tmp_ctx);
2950                 return ret;
2951         }
2952
2953         new_values = talloc_array(tmp_ctx, struct ldb_val, max_num_values);
2954         if (new_values == NULL) {
2955                 ldb_module_oom(module);
2956                 talloc_free(tmp_ctx);
2957                 return LDB_ERR_OPERATIONS_ERROR;
2958         }
2959
2960         old_i = 0;
2961         new_i = 0;
2962         for (i = 0; i < max_num_values; i++) {
2963                 int cmp;
2964                 struct parsed_dn *old_p, *new_p;
2965                 if (old_i < old_num_values && new_i < repl_num_values) {
2966                         old_p = &old_dns[old_i];
2967                         new_p = &dns[new_i];
2968                         cmp = parsed_dn_compare(old_p, new_p);
2969                 } else if (old_i < old_num_values) {
2970                         /* the new list is empty, read the old list */
2971                         old_p = &old_dns[old_i];
2972                         new_p = NULL;
2973                         cmp = -1;
2974                 } else if (new_i < repl_num_values) {
2975                         /* the old list is empty, read new list */
2976                         old_p = NULL;
2977                         new_p = &dns[new_i];
2978                         cmp = 1;
2979                 } else {
2980                         break;
2981                 }
2982
2983                 if (cmp < 0) {
2984                         /*
2985                          * An old ones that come before the next replacement
2986                          * (if any). We mark it as deleted and add it to the
2987                          * final list.
2988                          */
2989                         uint32_t rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
2990                         if ((rmd_flags & DSDB_RMD_FLAG_DELETED) == 0) {
2991                                 ret = replmd_update_la_val(new_values, old_p->v,
2992                                                            old_p->dsdb_dn,
2993                                                            old_p->dsdb_dn,
2994                                                            invocation_id,
2995                                                            seq_num, seq_num,
2996                                                            now, 0, true);
2997                                 if (ret != LDB_SUCCESS) {
2998                                         talloc_free(tmp_ctx);
2999                                         return ret;
3000                                 }
3001
3002                                 ret = replmd_add_backlink(module, replmd_private,
3003                                                           schema, 
3004                                                           msg_dn,
3005                                                           &old_p->guid, false,
3006                                                           schema_attr,
3007                                                           parent);
3008                                 if (ret != LDB_SUCCESS) {
3009                                         talloc_free(tmp_ctx);
3010                                         return ret;
3011                                 }
3012                         }
3013                         new_values[i] = *old_p->v;
3014                         old_i++;
3015                 } else if (cmp == 0) {
3016                         /*
3017                          * We are overwriting one. If it was previously
3018                          * deleted, we need to add a backlink.
3019                          *
3020                          * Note that if any RMD_FLAGs in an extended new DN
3021                          * will be ignored.
3022                          */
3023                         uint32_t rmd_flags;
3024
3025                         ret = replmd_update_la_val(new_values, old_p->v,
3026                                                    new_p->dsdb_dn,
3027                                                    old_p->dsdb_dn,
3028                                                    invocation_id,
3029                                                    seq_num, seq_num,
3030                                                    now, 0, false);
3031                         if (ret != LDB_SUCCESS) {
3032                                 talloc_free(tmp_ctx);
3033                                 return ret;
3034                         }
3035
3036                         rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
3037                         if ((rmd_flags & DSDB_RMD_FLAG_DELETED) != 0) {
3038                                 ret = replmd_add_backlink(module, replmd_private,
3039                                                           schema, 
3040                                                           msg_dn,
3041                                                           &new_p->guid, true,
3042                                                           schema_attr,
3043                                                           parent);
3044                                 if (ret != LDB_SUCCESS) {
3045                                         talloc_free(tmp_ctx);
3046                                         return ret;
3047                                 }
3048                         }
3049
3050                         new_values[i] = *old_p->v;
3051                         old_i++;
3052                         new_i++;
3053                 } else {
3054                         /*
3055                          * Replacements that don't match an existing one. We
3056                          * just add them to the final list.
3057                          */
3058                         ret = replmd_build_la_val(new_values,
3059                                                   new_p->v,
3060                                                   new_p->dsdb_dn,
3061                                                   invocation_id,
3062                                                   seq_num, seq_num,
3063                                                   now, 0, false);
3064                         if (ret != LDB_SUCCESS) {
3065                                 talloc_free(tmp_ctx);
3066                                 return ret;
3067                         }
3068                         ret = replmd_add_backlink(module, replmd_private,
3069                                                   schema,
3070                                                   msg_dn,
3071                                                   &new_p->guid, true,
3072                                                   schema_attr,
3073                                                   parent);
3074                         if (ret != LDB_SUCCESS) {
3075                                 talloc_free(tmp_ctx);
3076                                 return ret;
3077                         }
3078                         new_values[i] = *new_p->v;
3079                         new_i++;
3080                 }
3081         }
3082         if (old_el != NULL) {
3083                 talloc_steal(msg->elements, old_el->values);
3084         }
3085         el->values = talloc_steal(msg->elements, new_values);
3086         el->num_values = i;
3087         talloc_free(tmp_ctx);
3088
3089         el->flags = LDB_FLAG_MOD_REPLACE;
3090
3091         return LDB_SUCCESS;
3092 }
3093
3094
3095 /*
3096   handle linked attributes in modify requests
3097  */
3098 static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
3099                                                struct replmd_private *replmd_private,
3100                                                struct ldb_message *msg,
3101                                                uint64_t seq_num, time_t t,
3102                                                struct ldb_request *parent)
3103 {
3104         struct ldb_result *res;
3105         unsigned int i;
3106         int ret;
3107         struct ldb_context *ldb = ldb_module_get_ctx(module);
3108         struct ldb_message *old_msg;
3109
3110         const struct dsdb_schema *schema;
3111
3112         if (dsdb_functional_level(ldb) == DS_DOMAIN_FUNCTION_2000) {
3113                 /*
3114                  * Nothing special is required for modifying or vanishing links
3115                  * in fl2000 since they are just strings in a multi-valued
3116                  * attribute.
3117                  */
3118                 struct ldb_control *ctrl = ldb_request_get_control(parent,
3119                                                                    DSDB_CONTROL_REPLMD_VANISH_LINKS);
3120                 if (ctrl) {
3121                         ctrl->critical = false;
3122                 }
3123                 return LDB_SUCCESS;
3124         }
3125
3126         /*
3127          * TODO:
3128          *
3129          * We should restrict this to the intersection of the list of
3130          * linked attributes in the schema and the list of attributes
3131          * being modified.
3132          *
3133          * This will help performance a little, as otherwise we have
3134          * to allocate the entire object value-by-value.
3135          */
3136         ret = dsdb_module_search_dn(module, msg, &res, msg->dn, NULL,
3137                                     DSDB_FLAG_NEXT_MODULE |
3138                                     DSDB_SEARCH_SHOW_RECYCLED |
3139                                     DSDB_SEARCH_REVEAL_INTERNALS |
3140                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
3141                                     parent);
3142         if (ret != LDB_SUCCESS) {
3143                 return ret;
3144         }
3145         schema = dsdb_get_schema(ldb, res);
3146         if (!schema) {
3147                 return LDB_ERR_OPERATIONS_ERROR;
3148         }
3149
3150         old_msg = res->msgs[0];
3151
3152         for (i=0; i<msg->num_elements; i++) {
3153                 struct ldb_message_element *el = &msg->elements[i];
3154                 struct ldb_message_element *old_el, *new_el;
3155                 unsigned int mod_type = LDB_FLAG_MOD_TYPE(el->flags);
3156                 const struct dsdb_attribute *schema_attr
3157                         = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
3158                 if (!schema_attr) {
3159                         ldb_asprintf_errstring(ldb,
3160                                                "%s: attribute %s is not a valid attribute in schema",
3161                                                __FUNCTION__, el->name);
3162                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
3163                 }
3164                 if (schema_attr->linkID == 0) {
3165                         continue;
3166                 }
3167                 if ((schema_attr->linkID & 1) == 1) {
3168                         if (parent && ldb_request_get_control(parent, DSDB_CONTROL_DBCHECK)) {
3169                                 continue;
3170                         }
3171                         /* Odd is for the target.  Illegal to modify */
3172                         ldb_asprintf_errstring(ldb,
3173                                                "attribute %s must not be modified directly, it is a linked attribute", el->name);
3174                         return LDB_ERR_UNWILLING_TO_PERFORM;
3175                 }
3176                 old_el = ldb_msg_find_element(old_msg, el->name);
3177                 switch (mod_type) {
3178                 case LDB_FLAG_MOD_REPLACE:
3179                         ret = replmd_modify_la_replace(module, replmd_private,
3180                                                        schema, msg, el, old_el,
3181                                                        schema_attr, seq_num, t,
3182                                                        old_msg->dn,
3183                                                        parent);
3184                         break;
3185                 case LDB_FLAG_MOD_DELETE:
3186                         ret = replmd_modify_la_delete(module, replmd_private,
3187                                                       schema, msg, el, old_el,
3188                                                       schema_attr, seq_num, t,
3189                                                       old_msg->dn,
3190                                                       parent);
3191                         break;
3192                 case LDB_FLAG_MOD_ADD:
3193                         ret = replmd_modify_la_add(module, replmd_private,
3194                                                    schema, msg, el, old_el,
3195                                                    schema_attr, seq_num, t,
3196                                                    old_msg->dn,
3197                                                    parent);
3198                         break;
3199                 default:
3200                         ldb_asprintf_errstring(ldb,
3201                                                "invalid flags 0x%x for %s linked attribute",
3202                                                el->flags, el->name);
3203                         return LDB_ERR_UNWILLING_TO_PERFORM;
3204                 }
3205                 if (dsdb_check_single_valued_link(schema_attr, el) != LDB_SUCCESS) {
3206                         ldb_asprintf_errstring(ldb,
3207                                                "Attribute %s is single valued but more than one value has been supplied",
3208                                                el->name);
3209                         /* Return codes as found on Windows 2012r2 */
3210                         if (mod_type == LDB_FLAG_MOD_REPLACE) {
3211                                 return LDB_ERR_CONSTRAINT_VIOLATION;
3212                         } else {
3213                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
3214                         }
3215                 } else {
3216                         el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
3217                 }
3218
3219                 if (ret != LDB_SUCCESS) {
3220                         return ret;
3221                 }
3222                 if (old_el) {
3223                         ldb_msg_remove_attr(old_msg, el->name);
3224                 }
3225                 ldb_msg_add_empty(old_msg, el->name, 0, &new_el);
3226                 new_el->num_values = el->num_values;
3227                 new_el->values = talloc_steal(msg->elements, el->values);
3228
3229                 /* TODO: this relises a bit too heavily on the exact
3230                    behaviour of ldb_msg_find_element and
3231                    ldb_msg_remove_element */
3232                 old_el = ldb_msg_find_element(msg, el->name);
3233                 if (old_el != el) {
3234                         ldb_msg_remove_element(msg, old_el);
3235                         i--;
3236                 }
3237         }
3238
3239         talloc_free(res);
3240         return ret;
3241 }
3242
3243
3244 static int send_rodc_referral(struct ldb_request *req,
3245                               struct ldb_context *ldb,
3246                               struct ldb_dn *dn)
3247 {
3248         char *referral = NULL;
3249         struct loadparm_context *lp_ctx = NULL;
3250         struct ldb_dn *fsmo_role_dn = NULL;
3251         struct ldb_dn *role_owner_dn = NULL;
3252         const char *domain = NULL;
3253         WERROR werr;
3254
3255         lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
3256                                  struct loadparm_context);
3257
3258         werr = dsdb_get_fsmo_role_info(req, ldb, DREPL_PDC_MASTER,
3259                                        &fsmo_role_dn, &role_owner_dn);
3260
3261         if (W_ERROR_IS_OK(werr)) {
3262                 struct ldb_dn *server_dn = ldb_dn_copy(req, role_owner_dn);
3263                 if (server_dn != NULL) {
3264                         ldb_dn_remove_child_components(server_dn, 1);
3265                         domain = samdb_dn_to_dnshostname(ldb, req,
3266                                                          server_dn);
3267                 }
3268         }
3269
3270         if (domain == NULL) {
3271                 domain = lpcfg_dnsdomain(lp_ctx);
3272         }
3273
3274         referral = talloc_asprintf(req, "ldap://%s/%s",
3275                                    domain,
3276                                    ldb_dn_get_linearized(dn));
3277         if (referral == NULL) {
3278                 ldb_oom(ldb);
3279                 return LDB_ERR_OPERATIONS_ERROR;
3280         }
3281
3282         return ldb_module_send_referral(req, referral);
3283 }
3284
3285
3286 static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
3287 {
3288         struct ldb_context *ldb;
3289         struct replmd_replicated_request *ac;
3290         struct ldb_request *down_req;
3291         struct ldb_message *msg;
3292         time_t t = time(NULL);
3293         int ret;
3294         bool is_urgent = false, rodc = false;
3295         bool is_schema_nc = false;
3296         unsigned int functional_level;
3297         const struct ldb_message_element *guid_el = NULL;
3298         struct ldb_control *sd_propagation_control;
3299         struct replmd_private *replmd_private =
3300                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
3301
3302         /* do not manipulate our control entries */
3303         if (ldb_dn_is_special(req->op.mod.message->dn)) {
3304                 return ldb_next_request(module, req);
3305         }
3306
3307         sd_propagation_control = ldb_request_get_control(req,
3308                                         DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
3309         if (sd_propagation_control != NULL) {
3310                 if (req->op.mod.message->num_elements != 1) {
3311                         return ldb_module_operr(module);
3312                 }
3313                 ret = strcmp(req->op.mod.message->elements[0].name,
3314                              "nTSecurityDescriptor");
3315                 if (ret != 0) {
3316                         return ldb_module_operr(module);
3317                 }
3318
3319                 return ldb_next_request(module, req);
3320         }
3321
3322         ldb = ldb_module_get_ctx(module);
3323
3324         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
3325
3326         guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
3327         if (guid_el != NULL) {
3328                 ldb_set_errstring(ldb,
3329                                   "replmd_modify: it's not allowed to change the objectGUID!");
3330                 return LDB_ERR_CONSTRAINT_VIOLATION;
3331         }
3332
3333         ac = replmd_ctx_init(module, req);
3334         if (ac == NULL) {
3335                 return ldb_module_oom(module);
3336         }
3337
3338         functional_level = dsdb_functional_level(ldb);
3339
3340         /* we have to copy the message as the caller might have it as a const */
3341         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
3342         if (msg == NULL) {
3343                 ldb_oom(ldb);
3344                 talloc_free(ac);
3345                 return LDB_ERR_OPERATIONS_ERROR;
3346         }
3347
3348         ldb_msg_remove_attr(msg, "whenChanged");
3349         ldb_msg_remove_attr(msg, "uSNChanged");
3350
3351         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
3352
3353         ret = replmd_update_rpmd(module, ac->schema, req, NULL,
3354                                  msg, &ac->seq_num, t, is_schema_nc,
3355                                  &is_urgent, &rodc);
3356         if (rodc && (ret == LDB_ERR_REFERRAL)) {
3357                 ret = send_rodc_referral(req, ldb, msg->dn);
3358                 talloc_free(ac);
3359                 return ret;
3360
3361         }
3362
3363         if (ret != LDB_SUCCESS) {
3364                 talloc_free(ac);
3365                 return ret;
3366         }
3367
3368         ret = replmd_modify_handle_linked_attribs(module, replmd_private,
3369                                                   msg, ac->seq_num, t, req);
3370         if (ret != LDB_SUCCESS) {
3371                 talloc_free(ac);
3372                 return ret;
3373         }
3374
3375         /* TODO:
3376          * - replace the old object with the newly constructed one
3377          */
3378
3379         ac->is_urgent = is_urgent;
3380
3381         ret = ldb_build_mod_req(&down_req, ldb, ac,
3382                                 msg,
3383                                 req->controls,
3384                                 ac, replmd_op_callback,
3385                                 req);
3386         LDB_REQ_SET_LOCATION(down_req);
3387         if (ret != LDB_SUCCESS) {
3388                 talloc_free(ac);
3389                 return ret;
3390         }
3391
3392         /* current partition control is needed by "replmd_op_callback" */
3393         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
3394                 ret = ldb_request_add_control(down_req,
3395                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
3396                                               false, NULL);
3397                 if (ret != LDB_SUCCESS) {
3398                         talloc_free(ac);
3399                         return ret;
3400                 }
3401         }
3402
3403         /* If we are in functional level 2000, then
3404          * replmd_modify_handle_linked_attribs will have done
3405          * nothing */
3406         if (functional_level == DS_DOMAIN_FUNCTION_2000) {
3407                 ret = ldb_request_add_control(down_req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
3408                 if (ret != LDB_SUCCESS) {
3409                         talloc_free(ac);
3410                         return ret;
3411                 }
3412         }
3413
3414         talloc_steal(down_req, msg);
3415
3416         /* we only change whenChanged and uSNChanged if the seq_num
3417            has changed */
3418         if (ac->seq_num != 0) {
3419                 ret = add_time_element(msg, "whenChanged", t);
3420                 if (ret != LDB_SUCCESS) {
3421                         talloc_free(ac);
3422                         ldb_operr(ldb);
3423                         return ret;
3424                 }
3425
3426                 ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
3427                 if (ret != LDB_SUCCESS) {
3428                         talloc_free(ac);
3429                         ldb_operr(ldb);
3430                         return ret;
3431                 }
3432         }
3433
3434         /* go on with the call chain */
3435         return ldb_next_request(module, down_req);
3436 }
3437
3438 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares);
3439
3440 /*
3441   handle a rename request
3442
3443   On a rename we need to do an extra ldb_modify which sets the
3444   whenChanged and uSNChanged attributes.  We do this in a callback after the success.
3445  */
3446 static int replmd_rename(struct ldb_module *module, struct ldb_request *req)
3447 {
3448         struct ldb_context *ldb;
3449         struct replmd_replicated_request *ac;
3450         int ret;
3451         struct ldb_request *down_req;
3452
3453         /* do not manipulate our control entries */
3454         if (ldb_dn_is_special(req->op.mod.message->dn)) {
3455                 return ldb_next_request(module, req);
3456         }
3457
3458         ldb = ldb_module_get_ctx(module);
3459
3460         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_rename\n");
3461
3462         ac = replmd_ctx_init(module, req);
3463         if (ac == NULL) {
3464                 return ldb_module_oom(module);
3465         }
3466
3467         ret = ldb_build_rename_req(&down_req, ldb, ac,
3468                                    ac->req->op.rename.olddn,
3469                                    ac->req->op.rename.newdn,
3470                                    ac->req->controls,
3471                                    ac, replmd_rename_callback,
3472                                    ac->req);
3473         LDB_REQ_SET_LOCATION(down_req);
3474         if (ret != LDB_SUCCESS) {
3475                 talloc_free(ac);
3476                 return ret;
3477         }
3478
3479         /* go on with the call chain */
3480         return ldb_next_request(module, down_req);
3481 }
3482
3483 /* After the rename is compleated, update the whenchanged etc */
3484 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
3485 {
3486         struct ldb_context *ldb;
3487         struct ldb_request *down_req;
3488         struct ldb_message *msg;
3489         const struct dsdb_attribute *rdn_attr;
3490         const char *rdn_name;
3491         const struct ldb_val *rdn_val;
3492         const char *attrs[5] = { NULL, };
3493         time_t t = time(NULL);
3494         int ret;
3495         bool is_urgent = false, rodc = false;
3496         bool is_schema_nc;
3497         struct replmd_replicated_request *ac =
3498                 talloc_get_type(req->context, struct replmd_replicated_request);
3499         struct replmd_private *replmd_private =
3500                 talloc_get_type(ldb_module_get_private(ac->module),
3501                                 struct replmd_private);
3502
3503         ldb = ldb_module_get_ctx(ac->module);
3504
3505         if (ares->error != LDB_SUCCESS) {
3506                 return ldb_module_done(ac->req, ares->controls,
3507                                         ares->response, ares->error);
3508         }
3509
3510         if (ares->type != LDB_REPLY_DONE) {
3511                 ldb_set_errstring(ldb,
3512                                   "invalid ldb_reply_type in callback");
3513                 talloc_free(ares);
3514                 return ldb_module_done(ac->req, NULL, NULL,
3515                                         LDB_ERR_OPERATIONS_ERROR);
3516         }
3517
3518         /* TODO:
3519          * - replace the old object with the newly constructed one
3520          */
3521
3522         msg = ldb_msg_new(ac);
3523         if (msg == NULL) {
3524                 ldb_oom(ldb);
3525                 return LDB_ERR_OPERATIONS_ERROR;
3526         }
3527
3528         msg->dn = ac->req->op.rename.newdn;
3529
3530         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
3531
3532         rdn_name = ldb_dn_get_rdn_name(msg->dn);
3533         if (rdn_name == NULL) {
3534                 talloc_free(ares);
3535                 return ldb_module_done(ac->req, NULL, NULL,
3536                                        ldb_operr(ldb));
3537         }
3538
3539         /* normalize the rdn attribute name */
3540         rdn_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rdn_name);
3541         if (rdn_attr == NULL) {
3542                 talloc_free(ares);
3543                 return ldb_module_done(ac->req, NULL, NULL,
3544                                        ldb_operr(ldb));
3545         }
3546         rdn_name = rdn_attr->lDAPDisplayName;
3547
3548         rdn_val = ldb_dn_get_rdn_val(msg->dn);
3549         if (rdn_val == NULL) {
3550                 talloc_free(ares);
3551                 return ldb_module_done(ac->req, NULL, NULL,
3552                                        ldb_operr(ldb));
3553         }
3554
3555         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
3556                 talloc_free(ares);
3557                 return ldb_module_done(ac->req, NULL, NULL,
3558                                        ldb_oom(ldb));
3559         }
3560         if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
3561                 talloc_free(ares);
3562                 return ldb_module_done(ac->req, NULL, NULL,
3563                                        ldb_oom(ldb));
3564         }
3565         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
3566                 talloc_free(ares);
3567                 return ldb_module_done(ac->req, NULL, NULL,
3568                                        ldb_oom(ldb));
3569         }
3570         if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
3571                 talloc_free(ares);
3572                 return ldb_module_done(ac->req, NULL, NULL,
3573                                        ldb_oom(ldb));
3574         }
3575
3576         /*
3577          * here we let replmd_update_rpmd() only search for
3578          * the existing "replPropertyMetaData" and rdn_name attributes.
3579          *
3580          * We do not want the existing "name" attribute as
3581          * the "name" attribute needs to get the version
3582          * updated on rename even if the rdn value hasn't changed.
3583          *
3584          * This is the diff of the meta data, for a moved user
3585          * on a w2k8r2 server:
3586          *
3587          * # record 1
3588          * -dn: CN=sdf df,CN=Users,DC=bla,DC=base
3589          * +dn: CN=sdf df,OU=TestOU,DC=bla,DC=base
3590          *  replPropertyMetaData:     NDR: struct replPropertyMetaDataBlob
3591          *         version                  : 0x00000001 (1)
3592          *         reserved                 : 0x00000000 (0)
3593          * @@ -66,11 +66,11 @@ replPropertyMetaData:     NDR: struct re
3594          *                      local_usn                : 0x00000000000037a5 (14245)
3595          *                 array: struct replPropertyMetaData1
3596          *                      attid                    : DRSUAPI_ATTID_name (0x90001)
3597          * -                    version                  : 0x00000001 (1)
3598          * -                    originating_change_time  : Wed Feb  9 17:20:49 2011 CET
3599          * +                    version                  : 0x00000002 (2)
3600          * +                    originating_change_time  : Wed Apr  6 15:21:01 2011 CEST
3601          *                      originating_invocation_id: 0d36ca05-5507-4e62-aca3-354bab0d39e1
3602          * -                    originating_usn          : 0x00000000000037a5 (14245)
3603          * -                    local_usn                : 0x00000000000037a5 (14245)
3604          * +                    originating_usn          : 0x0000000000003834 (14388)
3605          * +                    local_usn                : 0x0000000000003834 (14388)
3606          *                 array: struct replPropertyMetaData1
3607          *                      attid                    : DRSUAPI_ATTID_userAccountControl (0x90008)
3608          *                      version                  : 0x00000004 (4)
3609          */
3610         attrs[0] = "replPropertyMetaData";
3611         attrs[1] = "objectClass";
3612         attrs[2] = "instanceType";
3613         attrs[3] = rdn_name;
3614         attrs[4] = NULL;
3615
3616         ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
3617                                  msg, &ac->seq_num, t,
3618                                  is_schema_nc, &is_urgent, &rodc);
3619         if (rodc && (ret == LDB_ERR_REFERRAL)) {
3620                 ret = send_rodc_referral(req, ldb, ac->req->op.rename.olddn);
3621                 talloc_free(ares);
3622                 return ldb_module_done(req, NULL, NULL, ret);
3623         }
3624
3625         if (ret != LDB_SUCCESS) {
3626                 talloc_free(ares);
3627                 return ldb_module_done(ac->req, NULL, NULL, ret);
3628         }
3629
3630         if (ac->seq_num == 0) {
3631                 talloc_free(ares);
3632                 return ldb_module_done(ac->req, NULL, NULL,
3633                                        ldb_error(ldb, ret,
3634                                         "internal error seq_num == 0"));
3635         }
3636         ac->is_urgent = is_urgent;
3637
3638         ret = ldb_build_mod_req(&down_req, ldb, ac,
3639                                 msg,
3640                                 req->controls,
3641                                 ac, replmd_op_callback,
3642                                 req);
3643         LDB_REQ_SET_LOCATION(down_req);
3644         if (ret != LDB_SUCCESS) {
3645                 talloc_free(ac);
3646                 return ret;
3647         }
3648
3649         /* current partition control is needed by "replmd_op_callback" */
3650         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
3651                 ret = ldb_request_add_control(down_req,
3652                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
3653                                               false, NULL);
3654                 if (ret != LDB_SUCCESS) {
3655                         talloc_free(ac);
3656                         return ret;
3657                 }
3658         }
3659
3660         talloc_steal(down_req, msg);
3661
3662         ret = add_time_element(msg, "whenChanged", t);
3663         if (ret != LDB_SUCCESS) {
3664                 talloc_free(ac);
3665                 ldb_operr(ldb);
3666                 return ret;
3667         }
3668
3669         ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
3670         if (ret != LDB_SUCCESS) {
3671                 talloc_free(ac);
3672                 ldb_operr(ldb);
3673                 return ret;
3674         }
3675
3676         /* go on with the call chain - do the modify after the rename */
3677         return ldb_next_request(ac->module, down_req);
3678 }
3679
3680 /*
3681  * remove links from objects that point at this object when an object
3682  * is deleted.  We remove it from the NEXT module per MS-DRSR 5.160
3683  * RemoveObj which states that link removal due to the object being
3684  * deleted is NOT an originating update - they just go away!
3685  *
3686  */
3687 static int replmd_delete_remove_link(struct ldb_module *module,
3688                                      const struct dsdb_schema *schema,
3689                                      struct replmd_private *replmd_private,
3690                                      struct ldb_dn *dn,
3691                                      struct GUID *guid,
3692                                      struct ldb_message_element *el,
3693                                      const struct dsdb_attribute *sa,
3694                                      struct ldb_request *parent)
3695 {
3696         unsigned int i;
3697         TALLOC_CTX *tmp_ctx = talloc_new(module);
3698         struct ldb_context *ldb = ldb_module_get_ctx(module);
3699
3700         for (i=0; i<el->num_values; i++) {
3701                 struct dsdb_dn *dsdb_dn;
3702                 int ret;
3703                 struct ldb_message *msg;
3704                 const struct dsdb_attribute *target_attr;
3705                 struct ldb_message_element *el2;
3706                 const char *dn_str;
3707                 struct ldb_val dn_val;
3708                 uint32_t dsdb_flags = 0;
3709                 const char *attrs[] = { NULL, NULL };
3710                 struct ldb_result *link_res;
3711                 struct ldb_message *link_msg;
3712                 struct ldb_message_element *link_el;
3713                 struct parsed_dn *link_dns;
3714                 struct parsed_dn *p = NULL, *unused = NULL;
3715
3716                 if (dsdb_dn_is_deleted_val(&el->values[i])) {
3717                         continue;
3718                 }
3719
3720                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], sa->syntax->ldap_oid);
3721                 if (!dsdb_dn) {
3722                         talloc_free(tmp_ctx);
3723                         return LDB_ERR_OPERATIONS_ERROR;
3724                 }
3725
3726                 /* remove the link */
3727                 msg = ldb_msg_new(tmp_ctx);
3728                 if (!msg) {
3729                         ldb_module_oom(module);
3730                         talloc_free(tmp_ctx);
3731                         return LDB_ERR_OPERATIONS_ERROR;
3732                 }
3733
3734
3735                 msg->dn = dsdb_dn->dn;
3736
3737                 target_attr = dsdb_attribute_by_linkID(schema, sa->linkID ^ 1);
3738                 if (target_attr == NULL) {
3739                         continue;
3740                 }
3741                 attrs[0] = target_attr->lDAPDisplayName;
3742
3743                 ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName,
3744                                         LDB_FLAG_MOD_DELETE, &el2);
3745                 if (ret != LDB_SUCCESS) {
3746                         ldb_module_oom(module);
3747                         talloc_free(tmp_ctx);
3748                         return LDB_ERR_OPERATIONS_ERROR;
3749                 }
3750
3751                 ret = dsdb_module_search_dn(module, tmp_ctx, &link_res,
3752                                             msg->dn, attrs,
3753                                             DSDB_FLAG_NEXT_MODULE |
3754                                             DSDB_SEARCH_SHOW_EXTENDED_DN,
3755                                             parent);
3756
3757                 if (ret != LDB_SUCCESS) {
3758                         talloc_free(tmp_ctx);
3759                         return ret;
3760                 }
3761
3762                 link_msg = link_res->msgs[0];
3763                 link_el = ldb_msg_find_element(link_msg,
3764                                                target_attr->lDAPDisplayName);
3765                 if (link_el == NULL) {
3766                         talloc_free(tmp_ctx);
3767                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
3768                 }
3769
3770                 /*
3771                  * This call 'upgrades' the links in link_dns, but we
3772                  * do not commit the result back into the database, so
3773                  * this is safe to call in FL2000 or on databases that
3774                  * have been run at that level in the past.
3775                  */
3776                 ret = get_parsed_dns_trusted(module, replmd_private, tmp_ctx,
3777                                              link_el, &link_dns,
3778                                              target_attr->syntax->ldap_oid, parent);
3779                 if (ret != LDB_SUCCESS) {
3780                         talloc_free(tmp_ctx);
3781                         return ret;
3782                 }
3783
3784                 ret = parsed_dn_find(ldb, link_dns, link_el->num_values,
3785                                      guid, dn,
3786                                      data_blob_null, 0,
3787                                      &p, &unused,
3788                                      target_attr->syntax->ldap_oid, false);
3789                 if (ret != LDB_SUCCESS) {
3790                         talloc_free(tmp_ctx);
3791                         return ret;
3792                 }
3793
3794                 if (p == NULL) {
3795                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
3796                                                "Failed to find forward link on %s "
3797                                                "as %s to remove backlink %s on %s",
3798                                                ldb_dn_get_linearized(msg->dn),
3799                                                target_attr->lDAPDisplayName,
3800                                                sa->lDAPDisplayName,
3801                                                ldb_dn_get_linearized(dn));
3802                         talloc_free(tmp_ctx);
3803                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
3804                 }
3805
3806
3807                 /* This needs to get the Binary DN, by first searching */
3808                 dn_str = dsdb_dn_get_linearized(tmp_ctx,
3809                                                 p->dsdb_dn);
3810
3811                 dn_val = data_blob_string_const(dn_str);
3812                 el2->values = &dn_val;
3813                 el2->num_values = 1;
3814
3815                 /*
3816                  * Ensure that we tell the modification to vanish any linked
3817                  * attributes (not simply mark them as isDeleted = TRUE)
3818                  */
3819                 dsdb_flags |= DSDB_REPLMD_VANISH_LINKS;
3820
3821                 ret = dsdb_module_modify(module, msg, dsdb_flags|DSDB_FLAG_OWN_MODULE, parent);
3822                 if (ret != LDB_SUCCESS) {
3823                         talloc_free(tmp_ctx);
3824                         return ret;
3825                 }
3826         }
3827         talloc_free(tmp_ctx);
3828         return LDB_SUCCESS;
3829 }
3830
3831
3832 /*
3833   handle update of replication meta data for deletion of objects
3834
3835   This also handles the mapping of delete to a rename operation
3836   to allow deletes to be replicated.
3837
3838   It also handles the incoming deleted objects, to ensure they are
3839   fully deleted here.  In that case re_delete is true, and we do not
3840   use this as a signal to change the deleted state, just reinforce it.
3841
3842  */
3843 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete)
3844 {
3845         int ret = LDB_ERR_OTHER;
3846         bool retb, disallow_move_on_delete;
3847         struct ldb_dn *old_dn, *new_dn;
3848         const char *rdn_name;
3849         const struct ldb_val *rdn_value, *new_rdn_value;
3850         struct GUID guid;
3851         struct ldb_context *ldb = ldb_module_get_ctx(module);
3852         const struct dsdb_schema *schema;
3853         struct ldb_message *msg, *old_msg;
3854         struct ldb_message_element *el;
3855         TALLOC_CTX *tmp_ctx;
3856         struct ldb_result *res, *parent_res;
3857         static const char * const preserved_attrs[] = {
3858                 /* yes, this really is a hard coded list. See MS-ADTS
3859                    section 3.1.1.5.5.1.1 */
3860                 "attributeID",
3861                 "attributeSyntax",
3862                 "dNReferenceUpdate",
3863                 "dNSHostName",
3864                 "flatName",
3865                 "governsID",
3866                 "groupType",
3867                 "instanceType",
3868                 "lDAPDisplayName",
3869                 "legacyExchangeDN",
3870                 "isDeleted",
3871                 "isRecycled",
3872                 "lastKnownParent",
3873                 "msDS-LastKnownRDN",
3874                 "msDS-PortLDAP",
3875                 "mS-DS-CreatorSID",
3876                 "mSMQOwnerID",
3877                 "nCName",
3878                 "objectClass",
3879                 "distinguishedName",
3880                 "objectGUID",
3881                 "objectSid",
3882                 "oMSyntax",
3883                 "proxiedObjectName",
3884                 "name",
3885                 "nTSecurityDescriptor",
3886                 "replPropertyMetaData",
3887                 "sAMAccountName",
3888                 "securityIdentifier",
3889                 "sIDHistory",
3890                 "subClassOf",
3891                 "systemFlags",
3892                 "trustPartner",
3893                 "trustDirection",
3894                 "trustType",
3895                 "trustAttributes",
3896                 "userAccountControl",
3897                 "uSNChanged",
3898                 "uSNCreated",
3899                 "whenCreated",
3900                 "whenChanged",
3901                 NULL
3902         };
3903         static const char * const all_attrs[] = {
3904                 DSDB_SECRET_ATTRIBUTES,
3905                 "*",
3906                 NULL
3907         };
3908         unsigned int i, el_count = 0;
3909         uint32_t dsdb_flags = 0;
3910         struct replmd_private *replmd_private;
3911         enum deletion_state deletion_state, next_deletion_state;
3912
3913         if (ldb_dn_is_special(req->op.del.dn)) {
3914                 return ldb_next_request(module, req);
3915         }
3916
3917         /*
3918          * We have to allow dbcheck to remove an object that
3919          * is beyond repair, and to do so totally.  This could
3920          * mean we we can get a partial object from the other
3921          * DC, causing havoc, so dbcheck suggests
3922          * re-replication first.  dbcheck sets both DBCHECK
3923          * and RELAX in this situation.
3924          */
3925         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)
3926             && ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
3927                 /* really, really remove it */
3928                 return ldb_next_request(module, req);
3929         }
3930
3931         tmp_ctx = talloc_new(ldb);
3932         if (!tmp_ctx) {
3933                 ldb_oom(ldb);
3934                 return LDB_ERR_OPERATIONS_ERROR;
3935         }
3936
3937         schema = dsdb_get_schema(ldb, tmp_ctx);
3938         if (!schema) {
3939                 talloc_free(tmp_ctx);
3940                 return LDB_ERR_OPERATIONS_ERROR;
3941         }
3942
3943         old_dn = ldb_dn_copy(tmp_ctx, req->op.del.dn);
3944
3945         /* we need the complete msg off disk, so we can work out which
3946            attributes need to be removed */
3947         ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, all_attrs,
3948                                     DSDB_FLAG_NEXT_MODULE |
3949                                     DSDB_SEARCH_SHOW_RECYCLED |
3950                                     DSDB_SEARCH_REVEAL_INTERNALS |
3951                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req);
3952         if (ret != LDB_SUCCESS) {
3953                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
3954                                        "repmd_delete: Failed to %s %s, because we failed to find it: %s",
3955                                        re_delete ? "re-delete" : "delete",
3956                                        ldb_dn_get_linearized(old_dn),
3957                                        ldb_errstring(ldb_module_get_ctx(module)));
3958                 talloc_free(tmp_ctx);
3959                 return ret;
3960         }
3961         old_msg = res->msgs[0];
3962
3963         replmd_deletion_state(module, old_msg,
3964                               &deletion_state,
3965                               &next_deletion_state);
3966
3967         /* This supports us noticing an incoming isDeleted and acting on it */
3968         if (re_delete) {
3969                 SMB_ASSERT(deletion_state > OBJECT_NOT_DELETED);
3970                 next_deletion_state = deletion_state;
3971         }
3972
3973         if (next_deletion_state == OBJECT_REMOVED) {
3974                 /*
3975                  * We have to prevent objects being deleted, even if
3976                  * the administrator really wants them gone, as
3977                  * without the tombstone, we can get a partial object
3978                  * from the other DC, causing havoc.
3979                  *
3980                  * The only other valid case is when the 180 day
3981                  * timeout has expired, when relax is specified.
3982                  */
3983                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
3984                         /* it is already deleted - really remove it this time */
3985                         talloc_free(tmp_ctx);
3986                         return ldb_next_request(module, req);
3987                 }
3988
3989                 ldb_asprintf_errstring(ldb, "Refusing to delete tombstone object %s.  "
3990                                        "This check is to prevent corruption of the replicated state.",
3991                                        ldb_dn_get_linearized(old_msg->dn));
3992                 return LDB_ERR_UNWILLING_TO_PERFORM;
3993         }
3994
3995         rdn_name = ldb_dn_get_rdn_name(old_dn);
3996         rdn_value = ldb_dn_get_rdn_val(old_dn);
3997         if ((rdn_name == NULL) || (rdn_value == NULL)) {
3998                 talloc_free(tmp_ctx);
3999                 return ldb_operr(ldb);
4000         }
4001
4002         msg = ldb_msg_new(tmp_ctx);
4003         if (msg == NULL) {
4004                 ldb_module_oom(module);
4005                 talloc_free(tmp_ctx);
4006                 return LDB_ERR_OPERATIONS_ERROR;
4007         }
4008
4009         msg->dn = old_dn;
4010
4011         /* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */
4012         disallow_move_on_delete =
4013                 (ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0)
4014                  & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
4015
4016         /* work out where we will be renaming this object to */
4017         if (!disallow_move_on_delete) {
4018                 struct ldb_dn *deleted_objects_dn;
4019                 ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn,
4020                                                   &deleted_objects_dn);
4021
4022                 /*
4023                  * We should not move objects if we can't find the
4024                  * deleted objects DN.  Not moving (or otherwise
4025                  * harming) the Deleted Objects DN itself is handled
4026                  * in the caller.
4027                  */
4028                 if (re_delete && (ret != LDB_SUCCESS)) {
4029                         new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4030                         if (new_dn == NULL) {
4031                                 ldb_module_oom(module);
4032                                 talloc_free(tmp_ctx);
4033                                 return LDB_ERR_OPERATIONS_ERROR;
4034                         }
4035                 } else if (ret != LDB_SUCCESS) {
4036                         /* this is probably an attempted delete on a partition
4037                          * that doesn't allow delete operations, such as the
4038                          * schema partition */
4039                         ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s",
4040                                                ldb_dn_get_linearized(old_dn));
4041                         talloc_free(tmp_ctx);
4042                         return LDB_ERR_UNWILLING_TO_PERFORM;
4043                 } else {
4044                         new_dn = deleted_objects_dn;
4045                 }
4046         } else {
4047                 new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4048                 if (new_dn == NULL) {
4049                         ldb_module_oom(module);
4050                         talloc_free(tmp_ctx);
4051                         return LDB_ERR_OPERATIONS_ERROR;
4052                 }
4053         }
4054
4055         /* get the objects GUID from the search we just did */
4056         guid = samdb_result_guid(old_msg, "objectGUID");
4057
4058         if (deletion_state == OBJECT_NOT_DELETED) {
4059                 /* Add a formatted child */
4060                 retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s",
4061                                             rdn_name,
4062                                             ldb_dn_escape_value(tmp_ctx, *rdn_value),
4063                                             GUID_string(tmp_ctx, &guid));
4064                 if (!retb) {
4065                         ldb_asprintf_errstring(ldb, __location__
4066                                                ": Unable to add a formatted child to dn: %s",
4067                                                ldb_dn_get_linearized(new_dn));
4068                         talloc_free(tmp_ctx);
4069                         return LDB_ERR_OPERATIONS_ERROR;
4070                 }
4071
4072                 ret = ldb_msg_add_string(msg, "isDeleted", "TRUE");
4073                 if (ret != LDB_SUCCESS) {
4074                         ldb_asprintf_errstring(ldb, __location__
4075                                                ": Failed to add isDeleted string to the msg");
4076                         talloc_free(tmp_ctx);
4077                         return ret;
4078                 }
4079                 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
4080         } else {
4081                 /*
4082                  * No matter what has happened with other renames etc, try again to
4083                  * get this to be under the deleted DN. See MS-DRSR 5.160 RemoveObj
4084                  */
4085
4086                 struct ldb_dn *rdn = ldb_dn_copy(tmp_ctx, old_dn);
4087                 retb = ldb_dn_remove_base_components(rdn, ldb_dn_get_comp_num(rdn) - 1);
4088                 if (!retb) {
4089                         ldb_asprintf_errstring(ldb, __location__
4090                                                ": Unable to add a prepare rdn of %s",
4091                                                ldb_dn_get_linearized(rdn));
4092                         talloc_free(tmp_ctx);
4093                         return LDB_ERR_OPERATIONS_ERROR;
4094                 }
4095                 SMB_ASSERT(ldb_dn_get_comp_num(rdn) == 1);
4096
4097                 retb = ldb_dn_add_child(new_dn, rdn);
4098                 if (!retb) {
4099                         ldb_asprintf_errstring(ldb, __location__
4100                                                ": Unable to add rdn %s to base dn: %s",
4101                                                ldb_dn_get_linearized(rdn),
4102                                                ldb_dn_get_linearized(new_dn));
4103                         talloc_free(tmp_ctx);
4104                         return LDB_ERR_OPERATIONS_ERROR;
4105                 }
4106         }
4107
4108         /*
4109           now we need to modify the object in the following ways:
4110
4111           - add isDeleted=TRUE
4112           - update rDN and name, with new rDN
4113           - remove linked attributes
4114           - remove objectCategory and sAMAccountType
4115           - remove attribs not on the preserved list
4116              - preserved if in above list, or is rDN
4117           - remove all linked attribs from this object
4118           - remove all links from other objects to this object
4119           - add lastKnownParent
4120           - update replPropertyMetaData?
4121
4122           see MS-ADTS "Tombstone Requirements" section 3.1.1.5.5.1.1
4123          */
4124
4125         if (deletion_state == OBJECT_NOT_DELETED) {
4126                 struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
4127                 char *parent_dn_str = NULL;
4128
4129                 /* we need the storage form of the parent GUID */
4130                 ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
4131                                             parent_dn, NULL,
4132                                             DSDB_FLAG_NEXT_MODULE |
4133                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
4134                                             DSDB_SEARCH_REVEAL_INTERNALS|
4135                                             DSDB_SEARCH_SHOW_RECYCLED, req);
4136                 if (ret != LDB_SUCCESS) {
4137                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
4138                                                "repmd_delete: Failed to %s %s, "
4139                                                "because we failed to find it's parent (%s): %s",
4140                                                re_delete ? "re-delete" : "delete",
4141                                                ldb_dn_get_linearized(old_dn),
4142                                                ldb_dn_get_linearized(parent_dn),
4143                                                ldb_errstring(ldb_module_get_ctx(module)));
4144                         talloc_free(tmp_ctx);
4145                         return ret;
4146                 }
4147
4148                 /*
4149                  * Now we can use the DB version,
4150                  * it will have the extended DN info in it
4151                  */
4152                 parent_dn = parent_res->msgs[0]->dn;
4153                 parent_dn_str = ldb_dn_get_extended_linearized(tmp_ctx,
4154                                                                parent_dn,
4155                                                                1);
4156                 if (parent_dn_str == NULL) {
4157                         talloc_free(tmp_ctx);
4158                         return ldb_module_oom(module);
4159                 }
4160
4161                 ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
4162                                                parent_dn_str);
4163                 if (ret != LDB_SUCCESS) {
4164                         ldb_asprintf_errstring(ldb, __location__
4165                                                ": Failed to add lastKnownParent "
4166                                                "string when deleting %s",
4167                                                ldb_dn_get_linearized(old_dn));
4168                         talloc_free(tmp_ctx);
4169                         return ret;
4170                 }
4171                 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
4172
4173                 if (next_deletion_state == OBJECT_DELETED) {
4174                         ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL);
4175                         if (ret != LDB_SUCCESS) {
4176                                 ldb_asprintf_errstring(ldb, __location__
4177                                                        ": Failed to add msDS-LastKnownRDN "
4178                                                        "string when deleting %s",
4179                                                        ldb_dn_get_linearized(old_dn));
4180                                 talloc_free(tmp_ctx);
4181                                 return ret;
4182                         }
4183                         msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
4184                 }
4185         }
4186
4187         switch (next_deletion_state) {
4188
4189         case OBJECT_RECYCLED:
4190         case OBJECT_TOMBSTONE:
4191
4192                 /*
4193                  * MS-ADTS 3.1.1.5.5.1.1 Tombstone Requirements
4194                  * describes what must be removed from a tombstone
4195                  * object
4196                  *
4197                  * MS-ADTS 3.1.1.5.5.1.3 Recycled-Object Requirements
4198                  * describes what must be removed from a recycled
4199                  * object
4200                  *
4201                  */
4202
4203                 /*
4204                  * we also mark it as recycled, meaning this object can't be
4205                  * recovered (we are stripping its attributes).
4206                  * This is done only if we have this schema object of course ...
4207                  * This behavior is identical to the one of Windows 2008R2 which
4208                  * always set the isRecycled attribute, even if the recycle-bin is
4209                  * not activated and what ever the forest level is.
4210                  */
4211                 if (dsdb_attribute_by_lDAPDisplayName(schema, "isRecycled") != NULL) {
4212                         ret = ldb_msg_add_string(msg, "isRecycled", "TRUE");
4213                         if (ret != LDB_SUCCESS) {
4214                                 DEBUG(0,(__location__ ": Failed to add isRecycled string to the msg\n"));
4215                                 ldb_module_oom(module);
4216                                 talloc_free(tmp_ctx);
4217                                 return ret;
4218                         }
4219                         msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
4220                 }
4221
4222                 replmd_private = talloc_get_type(ldb_module_get_private(module),
4223                                                  struct replmd_private);
4224                 /* work out which of the old attributes we will be removing */
4225                 for (i=0; i<old_msg->num_elements; i++) {
4226                         const struct dsdb_attribute *sa;
4227                         el = &old_msg->elements[i];
4228                         sa = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
4229                         if (!sa) {
4230                                 talloc_free(tmp_ctx);
4231                                 return LDB_ERR_OPERATIONS_ERROR;
4232                         }
4233                         if (ldb_attr_cmp(el->name, rdn_name) == 0) {
4234                                 /* don't remove the rDN */
4235                                 continue;
4236                         }
4237                         if (sa->linkID & 1) {
4238                                 /*
4239                                   we have a backlink in this object
4240                                   that needs to be removed. We're not
4241                                   allowed to remove it directly
4242                                   however, so we instead setup a
4243                                   modify to delete the corresponding
4244                                   forward link
4245                                  */
4246                                 ret = replmd_delete_remove_link(module, schema,
4247                                                                 replmd_private,
4248                                                                 old_dn, &guid,
4249                                                                 el, sa, req);
4250                                 if (ret != LDB_SUCCESS) {
4251                                         const char *old_dn_str
4252                                                 = ldb_dn_get_linearized(old_dn);
4253                                         ldb_asprintf_errstring(ldb,
4254                                                                __location__
4255                                                                ": Failed to remove backlink of "
4256                                                                "%s when deleting %s: %s",
4257                                                                el->name,
4258                                                                old_dn_str,
4259                                                                ldb_errstring(ldb));
4260                                         talloc_free(tmp_ctx);
4261                                         return LDB_ERR_OPERATIONS_ERROR;
4262                                 }
4263                                 /* now we continue, which means we
4264                                    won't remove this backlink
4265                                    directly
4266                                 */
4267                                 continue;
4268                         } else if (sa->linkID == 0) {
4269                                 if (ldb_attr_in_list(preserved_attrs, el->name)) {
4270                                         continue;
4271                                 }
4272                                 if (sa->searchFlags & SEARCH_FLAG_PRESERVEONDELETE) {
4273                                         continue;
4274                                 }
4275                         } else {
4276                                 /*
4277                                  * Ensure that we tell the modification to vanish any linked
4278                                  * attributes (not simply mark them as isDeleted = TRUE)
4279                                  */
4280                                 dsdb_flags |= DSDB_REPLMD_VANISH_LINKS;
4281                         }
4282                         ret = ldb_msg_add_empty(msg, el->name, LDB_FLAG_MOD_DELETE, &el);
4283                         if (ret != LDB_SUCCESS) {
4284                                 talloc_free(tmp_ctx);
4285                                 ldb_module_oom(module);
4286                                 return ret;
4287                         }
4288                 }
4289
4290                 break;
4291
4292         case OBJECT_DELETED:
4293                 /*
4294                  * MS-ADTS 3.1.1.5.5.1.2 Deleted-Object Requirements
4295                  * describes what must be removed from a deleted
4296                  * object
4297                  */
4298
4299                 ret = ldb_msg_add_empty(msg, "objectCategory", LDB_FLAG_MOD_REPLACE, NULL);
4300                 if (ret != LDB_SUCCESS) {
4301                         talloc_free(tmp_ctx);
4302                         ldb_module_oom(module);
4303                         return ret;
4304                 }
4305
4306                 ret = ldb_msg_add_empty(msg, "sAMAccountType", LDB_FLAG_MOD_REPLACE, NULL);
4307                 if (ret != LDB_SUCCESS) {
4308                         talloc_free(tmp_ctx);
4309                         ldb_module_oom(module);
4310                         return ret;
4311                 }
4312
4313                 break;
4314
4315         default:
4316                 break;
4317         }
4318
4319         if (deletion_state == OBJECT_NOT_DELETED) {
4320                 const struct dsdb_attribute *sa;
4321
4322                 /* work out what the new rdn value is, for updating the
4323                    rDN and name fields */
4324                 new_rdn_value = ldb_dn_get_rdn_val(new_dn);
4325                 if (new_rdn_value == NULL) {
4326                         talloc_free(tmp_ctx);
4327                         return ldb_operr(ldb);
4328                 }
4329
4330                 sa = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
4331                 if (!sa) {
4332                         talloc_free(tmp_ctx);
4333                         return LDB_ERR_OPERATIONS_ERROR;
4334                 }
4335
4336                 ret = ldb_msg_add_value(msg, sa->lDAPDisplayName, new_rdn_value,
4337                                         &el);
4338                 if (ret != LDB_SUCCESS) {
4339                         talloc_free(tmp_ctx);
4340                         return ret;
4341                 }
4342                 el->flags = LDB_FLAG_MOD_REPLACE;
4343
4344                 el = ldb_msg_find_element(old_msg, "name");
4345                 if (el) {
4346                         ret = ldb_msg_add_value(msg, "name", new_rdn_value, &el);
4347                         if (ret != LDB_SUCCESS) {
4348                                 talloc_free(tmp_ctx);
4349                                 return ret;
4350                         }
4351                         el->flags = LDB_FLAG_MOD_REPLACE;
4352                 }
4353         }
4354
4355         /*
4356          * TODO: Per MS-DRSR 5.160 RemoveObj we should remove links directly, not as an originating update!
4357          *
4358          */
4359
4360         /*
4361          * No matter what has happned with other renames, try again to
4362          * get this to be under the deleted DN.
4363          */
4364         if (strcmp(ldb_dn_get_linearized(old_dn), ldb_dn_get_linearized(new_dn)) != 0) {
4365                 /* now rename onto the new DN */
4366                 ret = dsdb_module_rename(module, old_dn, new_dn, DSDB_FLAG_NEXT_MODULE, req);
4367                 if (ret != LDB_SUCCESS){
4368                         DEBUG(0,(__location__ ": Failed to rename object from '%s' to '%s' - %s\n",
4369                                  ldb_dn_get_linearized(old_dn),
4370                                  ldb_dn_get_linearized(new_dn),
4371                                  ldb_errstring(ldb)));
4372                         talloc_free(tmp_ctx);
4373                         return ret;
4374                 }
4375                 msg->dn = new_dn;
4376         }
4377
4378         ret = dsdb_module_modify(module, msg, dsdb_flags|DSDB_FLAG_OWN_MODULE, req);
4379         if (ret != LDB_SUCCESS) {
4380                 ldb_asprintf_errstring(ldb, "replmd_delete: Failed to modify object %s in delete - %s",
4381                                        ldb_dn_get_linearized(old_dn), ldb_errstring(ldb));
4382                 talloc_free(tmp_ctx);
4383                 return ret;
4384         }
4385
4386         talloc_free(tmp_ctx);
4387
4388         return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
4389 }
4390
4391 static int replmd_delete(struct ldb_module *module, struct ldb_request *req)
4392 {
4393         return replmd_delete_internals(module, req, false);
4394 }
4395
4396
4397 static int replmd_replicated_request_error(struct replmd_replicated_request *ar, int ret)
4398 {
4399         return ret;
4400 }
4401
4402 static int replmd_replicated_request_werror(struct replmd_replicated_request *ar, WERROR status)
4403 {
4404         int ret = LDB_ERR_OTHER;
4405         /* TODO: do some error mapping */
4406
4407         /* Let the caller know the full WERROR */
4408         ar->objs->error = status;
4409
4410         return ret;
4411 }
4412
4413
4414 static struct replPropertyMetaData1 *
4415 replmd_replPropertyMetaData1_find_attid(struct replPropertyMetaDataBlob *md_blob,
4416                                         enum drsuapi_DsAttributeId attid)
4417 {
4418         uint32_t i;
4419         struct replPropertyMetaDataCtr1 *rpmd_ctr = &md_blob->ctr.ctr1;
4420
4421         for (i = 0; i < rpmd_ctr->count; i++) {
4422                 if (rpmd_ctr->array[i].attid == attid) {
4423                         return &rpmd_ctr->array[i];
4424                 }
4425         }
4426         return NULL;
4427 }
4428
4429
4430 /*
4431    return true if an update is newer than an existing entry
4432    see section 5.11 of MS-ADTS
4433 */
4434 static bool replmd_update_is_newer(const struct GUID *current_invocation_id,
4435                                    const struct GUID *update_invocation_id,
4436                                    uint32_t current_version,
4437                                    uint32_t update_version,
4438                                    NTTIME current_change_time,
4439                                    NTTIME update_change_time)
4440 {
4441         if (update_version != current_version) {
4442                 return update_version > current_version;
4443         }
4444         if (update_change_time != current_change_time) {
4445                 return update_change_time > current_change_time;
4446         }
4447         return GUID_compare(update_invocation_id, current_invocation_id) > 0;
4448 }
4449
4450 static bool replmd_replPropertyMetaData1_is_newer(struct replPropertyMetaData1 *cur_m,
4451                                                   struct replPropertyMetaData1 *new_m)
4452 {
4453         return replmd_update_is_newer(&cur_m->originating_invocation_id,
4454                                       &new_m->originating_invocation_id,
4455                                       cur_m->version,
4456                                       new_m->version,
4457                                       cur_m->originating_change_time,
4458                                       new_m->originating_change_time);
4459 }
4460
4461 static bool replmd_replPropertyMetaData1_new_should_be_taken(uint32_t dsdb_repl_flags,
4462                                                              struct replPropertyMetaData1 *cur_m,
4463                                                              struct replPropertyMetaData1 *new_m)
4464 {
4465         bool cmp;
4466
4467         /*
4468          * If the new replPropertyMetaData entry for this attribute is
4469          * not provided (this happens in the case where we look for
4470          * ATTID_name, but the name was not changed), then the local
4471          * state is clearly still current, as the remote
4472          * server didn't send it due to being older the high watermark
4473          * USN we sent.
4474          */
4475         if (new_m == NULL) {
4476                 return false;
4477         }
4478
4479         if (dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING) {
4480                 /*
4481                  * if we compare equal then do an
4482                  * update. This is used when a client
4483                  * asks for a FULL_SYNC, and can be
4484                  * used to recover a corrupt
4485                  * replica.
4486                  *
4487                  * This call is a bit tricky, what we
4488                  * are doing it turning the 'is_newer'
4489                  * call into a 'not is older' by
4490                  * swapping cur_m and new_m, and negating the
4491                  * outcome.
4492                  */
4493                 cmp = !replmd_replPropertyMetaData1_is_newer(new_m,
4494                                                              cur_m);
4495         } else {
4496                 cmp = replmd_replPropertyMetaData1_is_newer(cur_m,
4497                                                             new_m);
4498         }
4499         return cmp;
4500 }
4501
4502
4503 /*
4504   form a conflict DN
4505  */
4506 static struct ldb_dn *replmd_conflict_dn(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, struct GUID *guid)
4507 {
4508         const struct ldb_val *rdn_val;
4509         const char *rdn_name;
4510         struct ldb_dn *new_dn;
4511
4512         rdn_val = ldb_dn_get_rdn_val(dn);
4513         rdn_name = ldb_dn_get_rdn_name(dn);
4514         if (!rdn_val || !rdn_name) {
4515                 return NULL;
4516         }
4517
4518         new_dn = ldb_dn_copy(mem_ctx, dn);
4519         if (!new_dn) {
4520                 return NULL;
4521         }
4522
4523         if (!ldb_dn_remove_child_components(new_dn, 1)) {
4524                 return NULL;
4525         }
4526
4527         if (!ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ACNF:%s",
4528                                   rdn_name,
4529                                   ldb_dn_escape_value(new_dn, *rdn_val),
4530                                   GUID_string(new_dn, guid))) {
4531                 return NULL;
4532         }
4533
4534         return new_dn;
4535 }
4536
4537
4538 /*
4539   perform a modify operation which sets the rDN and name attributes to
4540   their current values. This has the effect of changing these
4541   attributes to have been last updated by the current DC. This is
4542   needed to ensure that renames performed as part of conflict
4543   resolution are propogated to other DCs
4544  */
4545 static int replmd_name_modify(struct replmd_replicated_request *ar,
4546                               struct ldb_request *req, struct ldb_dn *dn)
4547 {
4548         struct ldb_message *msg;
4549         const char *rdn_name;
4550         const struct ldb_val *rdn_val;
4551         const struct dsdb_attribute *rdn_attr;
4552         int ret;
4553
4554         msg = ldb_msg_new(req);
4555         if (msg == NULL) {
4556                 goto failed;
4557         }
4558         msg->dn = dn;
4559
4560         rdn_name = ldb_dn_get_rdn_name(dn);
4561         if (rdn_name == NULL) {
4562                 goto failed;
4563         }
4564
4565         /* normalize the rdn attribute name */
4566         rdn_attr = dsdb_attribute_by_lDAPDisplayName(ar->schema, rdn_name);
4567         if (rdn_attr == NULL) {
4568                 goto failed;
4569         }
4570         rdn_name = rdn_attr->lDAPDisplayName;
4571
4572         rdn_val = ldb_dn_get_rdn_val(dn);
4573         if (rdn_val == NULL) {
4574                 goto failed;
4575         }
4576
4577         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
4578                 goto failed;
4579         }
4580         if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
4581                 goto failed;
4582         }
4583         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
4584                 goto failed;
4585         }
4586         if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
4587                 goto failed;
4588         }
4589
4590         /*
4591          * We have to mark this as a replicated update otherwise
4592          * schema_data may reject a rename in the schema partition
4593          */
4594
4595         ret = dsdb_module_modify(ar->module, msg,
4596                                  DSDB_FLAG_OWN_MODULE|DSDB_FLAG_REPLICATED_UPDATE,
4597                                  req);
4598         if (ret != LDB_SUCCESS) {
4599                 DEBUG(0,(__location__ ": Failed to modify rDN/name of DN being DRS renamed '%s' - %s",
4600                          ldb_dn_get_linearized(dn),
4601                          ldb_errstring(ldb_module_get_ctx(ar->module))));
4602                 return ret;
4603         }
4604
4605         talloc_free(msg);
4606
4607         return LDB_SUCCESS;
4608
4609 failed:
4610         talloc_free(msg);
4611         DEBUG(0,(__location__ ": Failed to setup modify rDN/name of DN being DRS renamed '%s'",
4612                  ldb_dn_get_linearized(dn)));
4613         return LDB_ERR_OPERATIONS_ERROR;
4614 }
4615
4616
4617 /*
4618   callback for conflict DN handling where we have renamed the incoming
4619   record. After renaming it, we need to ensure the change of name and
4620   rDN for the incoming record is seen as an originating update by this DC.
4621
4622   This also handles updating lastKnownParent for entries sent to lostAndFound
4623  */
4624 static int replmd_op_name_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
4625 {
4626         struct replmd_replicated_request *ar =
4627                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
4628         struct ldb_dn *conflict_dn = NULL;
4629         int ret;
4630
4631         if (ares->error != LDB_SUCCESS) {
4632                 /* call the normal callback for everything except success */
4633                 return replmd_op_callback(req, ares);
4634         }
4635
4636         switch (req->operation) {
4637         case LDB_ADD:
4638                 conflict_dn = req->op.add.message->dn;
4639                 break;
4640         case LDB_MODIFY:
4641                 conflict_dn = req->op.mod.message->dn;
4642                 break;
4643         default:
4644                 smb_panic("replmd_op_name_modify_callback called in unknown circumstances");
4645         }
4646
4647         /* perform a modify of the rDN and name of the record */
4648         ret = replmd_name_modify(ar, req, conflict_dn);
4649         if (ret != LDB_SUCCESS) {
4650                 ares->error = ret;
4651                 return replmd_op_callback(req, ares);
4652         }
4653
4654         if (ar->objs->objects[ar->index_current].last_known_parent) {
4655                 struct ldb_message *msg = ldb_msg_new(req);
4656                 if (msg == NULL) {
4657                         ldb_module_oom(ar->module);
4658                         return LDB_ERR_OPERATIONS_ERROR;
4659                 }
4660
4661                 msg->dn = req->op.add.message->dn;
4662
4663                 ret = ldb_msg_add_steal_string(msg, "lastKnownParent",
4664                                                ldb_dn_get_extended_linearized(msg, ar->objs->objects[ar->index_current].last_known_parent, 1));
4665                 if (ret != LDB_SUCCESS) {
4666                         DEBUG(0,(__location__ ": Failed to add lastKnownParent string to the msg\n"));
4667                         ldb_module_oom(ar->module);
4668                         return ret;
4669                 }
4670                 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
4671
4672                 ret = dsdb_module_modify(ar->module, msg, DSDB_FLAG_OWN_MODULE, req);
4673                 if (ret != LDB_SUCCESS) {
4674                         DEBUG(0,(__location__ ": Failed to modify lastKnownParent of lostAndFound DN '%s' - %s",
4675                                  ldb_dn_get_linearized(msg->dn),
4676                                  ldb_errstring(ldb_module_get_ctx(ar->module))));
4677                         return ret;
4678                 }
4679                 TALLOC_FREE(msg);
4680         }
4681
4682         return replmd_op_callback(req, ares);
4683 }
4684
4685 /*
4686   callback for replmd_replicated_apply_add()
4687   This copes with the creation of conflict records in the case where
4688   the DN exists, but with a different objectGUID
4689  */
4690 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))
4691 {
4692         struct ldb_dn *conflict_dn;
4693         struct replmd_replicated_request *ar =
4694                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
4695         struct ldb_result *res;
4696         const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
4697         int ret;
4698         const struct ldb_val *omd_value;
4699         struct replPropertyMetaDataBlob omd, *rmd;
4700         enum ndr_err_code ndr_err;
4701         bool rename_incoming_record, rodc;
4702         struct replPropertyMetaData1 *rmd_name, *omd_name;
4703         struct ldb_message *msg;
4704         struct ldb_request *down_req = NULL;
4705
4706         /* call the normal callback for success */
4707         if (ares->error == LDB_SUCCESS) {
4708                 return callback(req, ares);
4709         }
4710
4711         /*
4712          * we have a conflict, and need to decide if we will keep the
4713          * new record or the old record
4714          */
4715
4716         msg = ar->objs->objects[ar->index_current].msg;
4717         conflict_dn = msg->dn;
4718
4719         /* For failures other than conflicts, fail the whole operation here */
4720         if (ares->error != LDB_ERR_ENTRY_ALREADY_EXISTS) {
4721                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote add of %s: %s",
4722                                        ldb_dn_get_linearized(conflict_dn),
4723                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
4724
4725                 return ldb_module_done(ar->req, NULL, NULL,
4726                                        LDB_ERR_OPERATIONS_ERROR);
4727         }
4728
4729         ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
4730         if (ret != LDB_SUCCESS) {
4731                 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)));
4732                 return ldb_module_done(ar->req, NULL, NULL,
4733                                        LDB_ERR_OPERATIONS_ERROR);
4734
4735         }
4736
4737         if (rodc) {
4738                 /*
4739                  * We are on an RODC, or were a GC for this
4740                  * partition, so we have to fail this until
4741                  * someone who owns the partition sorts it
4742                  * out
4743                  */
4744                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
4745                                        "Conflict adding object '%s' from incoming replication as we are read only for the partition.  \n"
4746                                        " - We must fail the operation until a master for this partition resolves the conflict",
4747                                        ldb_dn_get_linearized(conflict_dn));
4748                 goto failed;
4749         }
4750
4751         /*
4752          * first we need the replPropertyMetaData attribute from the
4753          * local, conflicting record
4754          */
4755         ret = dsdb_module_search_dn(ar->module, req, &res, conflict_dn,
4756                                     attrs,
4757                                     DSDB_FLAG_NEXT_MODULE |
4758                                     DSDB_SEARCH_SHOW_DELETED |
4759                                     DSDB_SEARCH_SHOW_RECYCLED, req);
4760         if (ret != LDB_SUCCESS) {
4761                 DEBUG(0,(__location__ ": Unable to find object for conflicting record '%s'\n",
4762                          ldb_dn_get_linearized(conflict_dn)));
4763                 goto failed;
4764         }
4765
4766         omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
4767         if (omd_value == NULL) {
4768                 DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for conflicting record '%s'\n",
4769                          ldb_dn_get_linearized(conflict_dn)));
4770                 goto failed;
4771         }
4772
4773         ndr_err = ndr_pull_struct_blob(omd_value, res->msgs[0], &omd,
4774                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
4775         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4776                 DEBUG(0,(__location__ ": Failed to parse old replPropertyMetaData for %s\n",
4777                          ldb_dn_get_linearized(conflict_dn)));
4778                 goto failed;
4779         }
4780
4781         rmd = ar->objs->objects[ar->index_current].meta_data;
4782
4783         /*
4784          * we decide which is newer based on the RPMD on the name
4785          * attribute.  See [MS-DRSR] ResolveNameConflict.
4786          *
4787          * We expect omd_name to be present, as this is from a local
4788          * search, but while rmd_name should have been given to us by
4789          * the remote server, if it is missing we just prefer the
4790          * local name in
4791          * replmd_replPropertyMetaData1_new_should_be_taken()
4792          */
4793         rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
4794         omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
4795         if (!omd_name) {
4796                 DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
4797                          ldb_dn_get_linearized(conflict_dn)));
4798                 goto failed;
4799         }
4800
4801         /*
4802          * Should we preserve the current record, and so rename the
4803          * incoming record to be a conflict?
4804          */
4805         rename_incoming_record
4806                 = !replmd_replPropertyMetaData1_new_should_be_taken(ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
4807                                                                     omd_name, rmd_name);
4808
4809         if (rename_incoming_record) {
4810                 struct GUID guid;
4811                 struct ldb_dn *new_dn;
4812
4813                 guid = samdb_result_guid(msg, "objectGUID");
4814                 if (GUID_all_zero(&guid)) {
4815                         DEBUG(0,(__location__ ": Failed to find objectGUID for conflicting incoming record %s\n",
4816                                  ldb_dn_get_linearized(conflict_dn)));
4817                         goto failed;
4818                 }
4819                 new_dn = replmd_conflict_dn(req, conflict_dn, &guid);
4820                 if (new_dn == NULL) {
4821                         DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
4822                                  ldb_dn_get_linearized(conflict_dn)));
4823                         goto failed;
4824                 }
4825
4826                 DEBUG(2,(__location__ ": Resolving conflict record via incoming rename '%s' -> '%s'\n",
4827                          ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
4828
4829                 /* re-submit the request, but with the new DN */
4830                 callback = replmd_op_name_modify_callback;
4831                 msg->dn = new_dn;
4832         } else {
4833                 /* we are renaming the existing record */
4834                 struct GUID guid;
4835                 struct ldb_dn *new_dn;
4836
4837                 guid = samdb_result_guid(res->msgs[0], "objectGUID");
4838                 if (GUID_all_zero(&guid)) {
4839                         DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
4840                                  ldb_dn_get_linearized(conflict_dn)));
4841                         goto failed;
4842                 }
4843
4844                 new_dn = replmd_conflict_dn(req, conflict_dn, &guid);
4845                 if (new_dn == NULL) {
4846                         DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
4847                                  ldb_dn_get_linearized(conflict_dn)));
4848                         goto failed;
4849                 }
4850
4851                 DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
4852                          ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
4853
4854                 ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
4855                                          DSDB_FLAG_OWN_MODULE, req);
4856                 if (ret != LDB_SUCCESS) {
4857                         DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
4858                                  ldb_dn_get_linearized(conflict_dn),
4859                                  ldb_dn_get_linearized(new_dn),
4860                                  ldb_errstring(ldb_module_get_ctx(ar->module))));
4861                         goto failed;
4862                 }
4863
4864                 /*
4865                  * now we need to ensure that the rename is seen as an
4866                  * originating update. We do that with a modify.
4867                  */
4868                 ret = replmd_name_modify(ar, req, new_dn);
4869                 if (ret != LDB_SUCCESS) {
4870                         goto failed;
4871                 }
4872
4873                 DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated creation of '%s'\n",
4874                          ldb_dn_get_linearized(req->op.add.message->dn)));
4875         }
4876
4877         ret = ldb_build_add_req(&down_req,
4878                                 ldb_module_get_ctx(ar->module),
4879                                 req,
4880                                 msg,
4881                                 ar->controls,
4882                                 ar,
4883                                 callback,
4884                                 req);
4885         if (ret != LDB_SUCCESS) {
4886                 goto failed;
4887         }
4888         LDB_REQ_SET_LOCATION(down_req);
4889
4890         /* current partition control needed by "repmd_op_callback" */
4891         ret = ldb_request_add_control(down_req,
4892                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
4893                                       false, NULL);
4894         if (ret != LDB_SUCCESS) {
4895                 return replmd_replicated_request_error(ar, ret);
4896         }
4897
4898         if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
4899                 /* this tells the partition module to make it a
4900                    partial replica if creating an NC */
4901                 ret = ldb_request_add_control(down_req,
4902                                               DSDB_CONTROL_PARTIAL_REPLICA,
4903                                               false, NULL);
4904                 if (ret != LDB_SUCCESS) {
4905                         return replmd_replicated_request_error(ar, ret);
4906                 }
4907         }
4908
4909         /*
4910          * Finally we re-run the add, otherwise the new record won't
4911          * exist, as we are here because of that exact failure!
4912          */
4913         return ldb_next_request(ar->module, down_req);
4914 failed:
4915
4916         /* on failure make the caller get the error. This means
4917          * replication will stop with an error, but there is not much
4918          * else we can do.
4919          */
4920         return ldb_module_done(ar->req, NULL, NULL,
4921                                ret);
4922 }
4923
4924 /*
4925   callback for replmd_replicated_apply_add()
4926   This copes with the creation of conflict records in the case where
4927   the DN exists, but with a different objectGUID
4928  */
4929 static int replmd_op_add_callback(struct ldb_request *req, struct ldb_reply *ares)
4930 {
4931         struct replmd_replicated_request *ar =
4932                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
4933
4934         if (ar->objs->objects[ar->index_current].last_known_parent) {
4935                 /* This is like a conflict DN, where we put the object in LostAndFound
4936                    see MS-DRSR 4.1.10.6.10 FindBestParentObject */
4937                 return replmd_op_possible_conflict_callback(req, ares, replmd_op_name_modify_callback);
4938         }
4939
4940         return replmd_op_possible_conflict_callback(req, ares, replmd_op_callback);
4941 }
4942
4943 /*
4944   this is called when a new object comes in over DRS
4945  */
4946 static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
4947 {
4948         struct ldb_context *ldb;
4949         struct ldb_request *change_req;
4950         enum ndr_err_code ndr_err;
4951         struct ldb_message *msg;
4952         struct replPropertyMetaDataBlob *md;
4953         struct ldb_val md_value;
4954         unsigned int i;
4955         int ret;
4956         bool remote_isDeleted = false;
4957         bool is_schema_nc;
4958         NTTIME now;
4959         time_t t = time(NULL);
4960         const struct ldb_val *rdn_val;
4961         struct replmd_private *replmd_private =
4962                 talloc_get_type(ldb_module_get_private(ar->module),
4963                                 struct replmd_private);
4964         unix_to_nt_time(&now, t);
4965
4966         ldb = ldb_module_get_ctx(ar->module);
4967         msg = ar->objs->objects[ar->index_current].msg;
4968         md = ar->objs->objects[ar->index_current].meta_data;
4969         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
4970
4971         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
4972         if (ret != LDB_SUCCESS) {
4973                 return replmd_replicated_request_error(ar, ret);
4974         }
4975
4976         ret = dsdb_msg_add_guid(msg,
4977                                 &ar->objs->objects[ar->index_current].object_guid,
4978                                 "objectGUID");
4979         if (ret != LDB_SUCCESS) {
4980                 return replmd_replicated_request_error(ar, ret);
4981         }
4982
4983         ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed);
4984         if (ret != LDB_SUCCESS) {
4985                 return replmd_replicated_request_error(ar, ret);
4986         }
4987
4988         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ar->seq_num);
4989         if (ret != LDB_SUCCESS) {
4990                 return replmd_replicated_request_error(ar, ret);
4991         }
4992
4993         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num);
4994         if (ret != LDB_SUCCESS) {
4995                 return replmd_replicated_request_error(ar, ret);
4996         }
4997
4998         /* remove any message elements that have zero values */
4999         for (i=0; i<msg->num_elements; i++) {
5000                 struct ldb_message_element *el = &msg->elements[i];
5001
5002                 if (el->num_values == 0) {
5003                         if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) {
5004                                 ldb_asprintf_errstring(ldb, __location__
5005                                                        ": empty objectClass sent on %s, aborting replication\n",
5006                                                        ldb_dn_get_linearized(msg->dn));
5007                                 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION);
5008                         }
5009
5010                         DEBUG(4,(__location__ ": Removing attribute %s with num_values==0\n",
5011                                  el->name));
5012                         memmove(el, el+1, sizeof(*el)*(msg->num_elements - (i+1)));
5013                         msg->num_elements--;
5014                         i--;
5015                         continue;
5016                 }
5017         }
5018
5019         if (DEBUGLVL(8)) {
5020                 struct GUID_txt_buf guid_txt;
5021
5022                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
5023                                                            LDB_CHANGETYPE_ADD,
5024                                                            msg);
5025                 DEBUG(8, ("DRS replication add message of %s:\n%s\n",
5026                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
5027                           s));
5028                 talloc_free(s);
5029         } else if (DEBUGLVL(4)) {
5030                 struct GUID_txt_buf guid_txt;
5031                 DEBUG(4, ("DRS replication add DN of %s is %s\n",
5032                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
5033                           ldb_dn_get_linearized(msg->dn)));
5034         }
5035         remote_isDeleted = ldb_msg_find_attr_as_bool(msg,
5036                                                      "isDeleted", false);
5037
5038         /*
5039          * the meta data array is already sorted by the caller, except
5040          * for the RDN, which needs to be added.
5041          */
5042
5043
5044         rdn_val = ldb_dn_get_rdn_val(msg->dn);
5045         ret = replmd_update_rpmd_rdn_attr(ldb, msg, rdn_val, NULL,
5046                                           md, ar, now, is_schema_nc,
5047                                           false);
5048         if (ret != LDB_SUCCESS) {
5049                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl ADD: %s", __func__, ldb_errstring(ldb));
5050                 return replmd_replicated_request_error(ar, ret);
5051         }
5052
5053         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &md->ctr.ctr1, msg->dn);
5054         if (ret != LDB_SUCCESS) {
5055                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl ADD: %s", __func__, ldb_errstring(ldb));
5056                 return replmd_replicated_request_error(ar, ret);
5057         }
5058
5059         for (i=0; i < md->ctr.ctr1.count; i++) {
5060                 md->ctr.ctr1.array[i].local_usn = ar->seq_num;
5061         }
5062         ndr_err = ndr_push_struct_blob(&md_value, msg, md,
5063                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
5064         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5065                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
5066                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
5067         }
5068         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &md_value, NULL);
5069         if (ret != LDB_SUCCESS) {
5070                 return replmd_replicated_request_error(ar, ret);
5071         }
5072
5073         replmd_ldb_message_sort(msg, ar->schema);
5074
5075         if (!remote_isDeleted) {
5076                 ret = dsdb_module_schedule_sd_propagation(ar->module,
5077                                                           ar->objs->partition_dn,
5078                                                           msg->dn, true);
5079                 if (ret != LDB_SUCCESS) {
5080                         return replmd_replicated_request_error(ar, ret);
5081                 }
5082         }
5083
5084         ar->isDeleted = remote_isDeleted;
5085
5086         ret = ldb_build_add_req(&change_req,
5087                                 ldb,
5088                                 ar,
5089                                 msg,
5090                                 ar->controls,
5091                                 ar,
5092                                 replmd_op_add_callback,
5093                                 ar->req);
5094         LDB_REQ_SET_LOCATION(change_req);
5095         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5096
5097         /* current partition control needed by "repmd_op_callback" */
5098         ret = ldb_request_add_control(change_req,
5099                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
5100                                       false, NULL);
5101         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5102
5103         if (ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
5104                 /* this tells the partition module to make it a
5105                    partial replica if creating an NC */
5106                 ret = ldb_request_add_control(change_req,
5107                                               DSDB_CONTROL_PARTIAL_REPLICA,
5108                                               false, NULL);
5109                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5110         }
5111
5112         return ldb_next_request(ar->module, change_req);
5113 }
5114
5115 static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request *req,
5116                                                               struct ldb_reply *ares)
5117 {
5118         struct replmd_replicated_request *ar = talloc_get_type(req->context,
5119                                                struct replmd_replicated_request);
5120         int ret;
5121
5122         if (!ares) {
5123                 return ldb_module_done(ar->req, NULL, NULL,
5124                                         LDB_ERR_OPERATIONS_ERROR);
5125         }
5126
5127         /*
5128          * The error NO_SUCH_OBJECT is not expected, unless the search
5129          * base is the partition DN, and that case doesn't happen here
5130          * because then we wouldn't get a parent_guid_value in any
5131          * case.
5132          */
5133         if (ares->error != LDB_SUCCESS) {
5134                 return ldb_module_done(ar->req, ares->controls,
5135                                         ares->response, ares->error);
5136         }
5137
5138         switch (ares->type) {
5139         case LDB_REPLY_ENTRY:
5140         {
5141                 struct ldb_message *parent_msg = ares->message;
5142                 struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
5143                 struct ldb_dn *parent_dn;
5144                 int comp_num;
5145
5146                 if (!ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")
5147                     && ldb_msg_check_string_attribute(parent_msg, "isDeleted", "TRUE")) {
5148                         /* Per MS-DRSR 4.1.10.6.10
5149                          * FindBestParentObject we need to move this
5150                          * new object under a deleted object to
5151                          * lost-and-found */
5152                         struct ldb_dn *nc_root;
5153
5154                         ret = dsdb_find_nc_root(ldb_module_get_ctx(ar->module), msg, msg->dn, &nc_root);
5155                         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
5156                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5157                                                        "No suitable NC root found for %s.  "
5158                                                        "We need to move this object because parent object %s "
5159                                                        "is deleted, but this object is not.",
5160                                                        ldb_dn_get_linearized(msg->dn),
5161                                                        ldb_dn_get_linearized(parent_msg->dn));
5162                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5163                         } else if (ret != LDB_SUCCESS) {
5164                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5165                                                        "Unable to find NC root for %s: %s. "
5166                                                        "We need to move this object because parent object %s "
5167                                                        "is deleted, but this object is not.",
5168                                                        ldb_dn_get_linearized(msg->dn),
5169                                                        ldb_errstring(ldb_module_get_ctx(ar->module)),
5170                                                        ldb_dn_get_linearized(parent_msg->dn));
5171                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5172                         }
5173
5174                         ret = dsdb_wellknown_dn(ldb_module_get_ctx(ar->module), msg,
5175                                                 nc_root,
5176                                                 DS_GUID_LOSTANDFOUND_CONTAINER,
5177                                                 &parent_dn);
5178                         if (ret != LDB_SUCCESS) {
5179                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5180                                                        "Unable to find LostAndFound Container for %s "
5181                                                        "in partition %s: %s. "
5182                                                        "We need to move this object because parent object %s "
5183                                                        "is deleted, but this object is not.",
5184                                                        ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(nc_root),
5185                                                        ldb_errstring(ldb_module_get_ctx(ar->module)),
5186                                                        ldb_dn_get_linearized(parent_msg->dn));
5187                                 return ldb_module_done(ar->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
5188                         }
5189                         ar->objs->objects[ar->index_current].last_known_parent
5190                                 = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
5191
5192                 } else {
5193                         parent_dn
5194                                 = talloc_steal(ar->objs->objects[ar->index_current].msg, parent_msg->dn);
5195
5196                 }
5197                 ar->objs->objects[ar->index_current].local_parent_dn = parent_dn;
5198
5199                 comp_num = ldb_dn_get_comp_num(msg->dn);
5200                 if (comp_num > 1) {
5201                         if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) {
5202                                 talloc_free(ares);
5203                                 return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
5204                         }
5205                 }
5206                 if (!ldb_dn_add_base(msg->dn, parent_dn)) {
5207                         talloc_free(ares);
5208                         return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
5209                 }
5210                 break;
5211         }
5212         case LDB_REPLY_REFERRAL:
5213                 /* we ignore referrals */
5214                 break;
5215
5216         case LDB_REPLY_DONE:
5217
5218                 if (ar->objs->objects[ar->index_current].local_parent_dn == NULL) {
5219                         struct GUID_txt_buf str_buf;
5220                         if (ar->search_msg != NULL) {
5221                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5222                                                        "No parent with GUID %s found for object locally known as %s",
5223                                                        GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
5224                                                        ldb_dn_get_linearized(ar->search_msg->dn));
5225                         } else {
5226                                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5227                                                        "No parent with GUID %s found for object remotely known as %s",
5228                                                        GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid, &str_buf),
5229                                                        ldb_dn_get_linearized(ar->objs->objects[ar->index_current].msg->dn));
5230                         }
5231
5232                         /*
5233                          * This error code is really important, as it
5234                          * is the flag back to the callers to retry
5235                          * this with DRSUAPI_DRS_GET_ANC, and so get
5236                          * the parent objects before the child
5237                          * objects
5238                          */
5239                         return ldb_module_done(ar->req, NULL, NULL,
5240                                                replmd_replicated_request_werror(ar, WERR_DS_DRA_MISSING_PARENT));
5241                 }
5242
5243                 if (ar->search_msg != NULL) {
5244                         ret = replmd_replicated_apply_merge(ar);
5245                 } else {
5246                         ret = replmd_replicated_apply_add(ar);
5247                 }
5248                 if (ret != LDB_SUCCESS) {
5249                         return ldb_module_done(ar->req, NULL, NULL, ret);
5250                 }
5251         }
5252
5253         talloc_free(ares);
5254         return LDB_SUCCESS;
5255 }
5256
5257 /*
5258  * Look for the parent object, so we put the new object in the right
5259  * place This is akin to NameObject in MS-DRSR - this routine and the
5260  * callbacks find the right parent name, and correct name for this
5261  * object
5262  */
5263
5264 static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_request *ar)
5265 {
5266         struct ldb_context *ldb;
5267         int ret;
5268         char *tmp_str;
5269         char *filter;
5270         struct ldb_request *search_req;
5271         static const char *attrs[] = {"isDeleted", NULL};
5272         struct GUID_txt_buf guid_str_buf;
5273
5274         ldb = ldb_module_get_ctx(ar->module);
5275
5276         if (ar->objs->objects[ar->index_current].parent_guid == NULL) {
5277                 if (ar->search_msg != NULL) {
5278                         return replmd_replicated_apply_merge(ar);
5279                 } else {
5280                         return replmd_replicated_apply_add(ar);
5281                 }
5282         }
5283
5284         tmp_str = GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
5285                                   &guid_str_buf);
5286
5287         filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
5288         if (!filter) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
5289
5290         ret = ldb_build_search_req(&search_req,
5291                                    ldb,
5292                                    ar,
5293                                    ar->objs->partition_dn,
5294                                    LDB_SCOPE_SUBTREE,
5295                                    filter,
5296                                    attrs,
5297                                    NULL,
5298                                    ar,
5299                                    replmd_replicated_apply_search_for_parent_callback,
5300                                    ar->req);
5301         LDB_REQ_SET_LOCATION(search_req);
5302
5303         ret = dsdb_request_add_controls(search_req,
5304                                         DSDB_SEARCH_SHOW_RECYCLED|
5305                                         DSDB_SEARCH_SHOW_DELETED|
5306                                         DSDB_SEARCH_SHOW_EXTENDED_DN);
5307         if (ret != LDB_SUCCESS) {
5308                 return ret;
5309         }
5310
5311         return ldb_next_request(ar->module, search_req);
5312 }
5313
5314 /*
5315   handle renames that come in over DRS replication
5316  */
5317 static int replmd_replicated_handle_rename(struct replmd_replicated_request *ar,
5318                                            struct ldb_message *msg,
5319                                            struct ldb_request *parent,
5320                                            bool *renamed)
5321 {
5322         int ret;
5323         TALLOC_CTX *tmp_ctx = talloc_new(msg);
5324         struct ldb_result *res;
5325         struct ldb_dn *conflict_dn;
5326         const char *attrs[] = { "replPropertyMetaData", "objectGUID", NULL };
5327         const struct ldb_val *omd_value;
5328         struct replPropertyMetaDataBlob omd, *rmd;
5329         enum ndr_err_code ndr_err;
5330         bool rename_incoming_record, rodc;
5331         struct replPropertyMetaData1 *rmd_name, *omd_name;
5332         struct ldb_dn *new_dn;
5333         struct GUID guid;
5334
5335         DEBUG(4,("replmd_replicated_request rename %s => %s\n",
5336                  ldb_dn_get_linearized(ar->search_msg->dn),
5337                  ldb_dn_get_linearized(msg->dn)));
5338
5339
5340         ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
5341                                  DSDB_FLAG_NEXT_MODULE, ar->req);
5342         if (ret == LDB_SUCCESS) {
5343                 talloc_free(tmp_ctx);
5344                 *renamed = true;
5345                 return ret;
5346         }
5347
5348         if (ret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
5349                 talloc_free(tmp_ctx);
5350                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module), "Failed to locally apply remote rename from %s to %s: %s",
5351                                        ldb_dn_get_linearized(ar->search_msg->dn),
5352                                        ldb_dn_get_linearized(msg->dn),
5353                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
5354                 return ret;
5355         }
5356
5357         ret = samdb_rodc(ldb_module_get_ctx(ar->module), &rodc);
5358         if (ret != LDB_SUCCESS) {
5359                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5360                                        "Failed to determine if we are an RODC when attempting to form conflict DN: %s",
5361                                        ldb_errstring(ldb_module_get_ctx(ar->module)));
5362                 return LDB_ERR_OPERATIONS_ERROR;
5363         }
5364         /*
5365          * we have a conflict, and need to decide if we will keep the
5366          * new record or the old record
5367          */
5368
5369         conflict_dn = msg->dn;
5370
5371         if (rodc) {
5372                 /*
5373                  * We are on an RODC, or were a GC for this
5374                  * partition, so we have to fail this until
5375                  * someone who owns the partition sorts it
5376                  * out
5377                  */
5378                 ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5379                                        "Conflict adding object '%s' from incoming replication but we are read only for the partition.  \n"
5380                                        " - We must fail the operation until a master for this partition resolves the conflict",
5381                                        ldb_dn_get_linearized(conflict_dn));
5382                 goto failed;
5383         }
5384
5385         /*
5386          * first we need the replPropertyMetaData attribute from the
5387          * old record
5388          */
5389         ret = dsdb_module_search_dn(ar->module, tmp_ctx, &res, conflict_dn,
5390                                     attrs,
5391                                     DSDB_FLAG_NEXT_MODULE |
5392                                     DSDB_SEARCH_SHOW_DELETED |
5393                                     DSDB_SEARCH_SHOW_RECYCLED, ar->req);
5394         if (ret != LDB_SUCCESS) {
5395                 DEBUG(0,(__location__ ": Unable to find object for conflicting record '%s'\n",
5396                          ldb_dn_get_linearized(conflict_dn)));
5397                 goto failed;
5398         }
5399
5400         omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
5401         if (omd_value == NULL) {
5402                 DEBUG(0,(__location__ ": Unable to find replPropertyMetaData for conflicting record '%s'\n",
5403                          ldb_dn_get_linearized(conflict_dn)));
5404                 goto failed;
5405         }
5406
5407         ndr_err = ndr_pull_struct_blob(omd_value, res->msgs[0], &omd,
5408                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
5409         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5410                 DEBUG(0,(__location__ ": Failed to parse old replPropertyMetaData for %s\n",
5411                          ldb_dn_get_linearized(conflict_dn)));
5412                 goto failed;
5413         }
5414
5415         rmd = ar->objs->objects[ar->index_current].meta_data;
5416
5417         /*
5418          * we decide which is newer based on the RPMD on the name
5419          * attribute.  See [MS-DRSR] ResolveNameConflict.
5420          *
5421          * We expect omd_name to be present, as this is from a local
5422          * search, but while rmd_name should have been given to us by
5423          * the remote server, if it is missing we just prefer the
5424          * local name in
5425          * replmd_replPropertyMetaData1_new_should_be_taken()
5426          */
5427         rmd_name = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
5428         omd_name = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
5429         if (!omd_name) {
5430                 DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
5431                          ldb_dn_get_linearized(conflict_dn)));
5432                 goto failed;
5433         }
5434
5435         /*
5436          * Should we preserve the current record, and so rename the
5437          * incoming record to be a conflict?
5438          */
5439         rename_incoming_record =
5440                 !replmd_replPropertyMetaData1_new_should_be_taken(
5441                         ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
5442                         omd_name, rmd_name);
5443
5444         if (rename_incoming_record) {
5445
5446                 new_dn = replmd_conflict_dn(msg, msg->dn,
5447                                             &ar->objs->objects[ar->index_current].object_guid);
5448                 if (new_dn == NULL) {
5449                         ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5450                                                                   "Failed to form conflict DN for %s\n",
5451                                                                   ldb_dn_get_linearized(msg->dn));
5452
5453                         return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
5454                 }
5455
5456                 ret = dsdb_module_rename(ar->module, ar->search_msg->dn, new_dn,
5457                                          DSDB_FLAG_NEXT_MODULE, ar->req);
5458                 if (ret != LDB_SUCCESS) {
5459                         ldb_asprintf_errstring(ldb_module_get_ctx(ar->module),
5460                                                "Failed to rename incoming conflicting dn '%s' (was '%s') to '%s' - %s\n",
5461                                                ldb_dn_get_linearized(conflict_dn),
5462                                                ldb_dn_get_linearized(ar->search_msg->dn),
5463                                                ldb_dn_get_linearized(new_dn),
5464                                                ldb_errstring(ldb_module_get_ctx(ar->module)));
5465                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
5466                 }
5467
5468                 msg->dn = new_dn;
5469                 *renamed = true;
5470                 return LDB_SUCCESS;
5471         }
5472
5473         /* we are renaming the existing record */
5474
5475         guid = samdb_result_guid(res->msgs[0], "objectGUID");
5476         if (GUID_all_zero(&guid)) {
5477                 DEBUG(0,(__location__ ": Failed to find objectGUID for existing conflict record %s\n",
5478                          ldb_dn_get_linearized(conflict_dn)));
5479                 goto failed;
5480         }
5481
5482         new_dn = replmd_conflict_dn(tmp_ctx, conflict_dn, &guid);
5483         if (new_dn == NULL) {
5484                 DEBUG(0,(__location__ ": Failed to form conflict DN for %s\n",
5485                          ldb_dn_get_linearized(conflict_dn)));
5486                 goto failed;
5487         }
5488
5489         DEBUG(2,(__location__ ": Resolving conflict record via existing-record rename '%s' -> '%s'\n",
5490                  ldb_dn_get_linearized(conflict_dn), ldb_dn_get_linearized(new_dn)));
5491
5492         ret = dsdb_module_rename(ar->module, conflict_dn, new_dn,
5493                                  DSDB_FLAG_OWN_MODULE, ar->req);
5494         if (ret != LDB_SUCCESS) {
5495                 DEBUG(0,(__location__ ": Failed to rename conflict dn '%s' to '%s' - %s\n",
5496                          ldb_dn_get_linearized(conflict_dn),
5497                          ldb_dn_get_linearized(new_dn),
5498                          ldb_errstring(ldb_module_get_ctx(ar->module))));
5499                 goto failed;
5500         }
5501
5502         /*
5503          * now we need to ensure that the rename is seen as an
5504          * originating update. We do that with a modify.
5505          */
5506         ret = replmd_name_modify(ar, ar->req, new_dn);
5507         if (ret != LDB_SUCCESS) {
5508                 goto failed;
5509         }
5510
5511         DEBUG(2,(__location__ ": With conflicting record renamed, re-apply replicated rename '%s' -> '%s'\n",
5512                  ldb_dn_get_linearized(ar->search_msg->dn),
5513                  ldb_dn_get_linearized(msg->dn)));
5514
5515
5516         ret = dsdb_module_rename(ar->module, ar->search_msg->dn, msg->dn,
5517                                  DSDB_FLAG_NEXT_MODULE, ar->req);
5518         if (ret != LDB_SUCCESS) {
5519                 DEBUG(0,(__location__ ": After conflict resolution, failed to rename dn '%s' to '%s' - %s\n",
5520                          ldb_dn_get_linearized(ar->search_msg->dn),
5521                          ldb_dn_get_linearized(msg->dn),
5522                          ldb_errstring(ldb_module_get_ctx(ar->module))));
5523                         goto failed;
5524         }
5525 failed:
5526
5527         /*
5528          * On failure make the caller get the error
5529          * This means replication will stop with an error,
5530          * but there is not much else we can do.  In the
5531          * LDB_ERR_ENTRY_ALREADY_EXISTS case this is exactly what is
5532          * needed.
5533          */
5534
5535         talloc_free(tmp_ctx);
5536         return ret;
5537 }
5538
5539
5540 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
5541 {
5542         struct ldb_context *ldb;
5543         struct ldb_request *change_req;
5544         enum ndr_err_code ndr_err;
5545         struct ldb_message *msg;
5546         struct replPropertyMetaDataBlob *rmd;
5547         struct replPropertyMetaDataBlob omd;
5548         const struct ldb_val *omd_value;
5549         struct replPropertyMetaDataBlob nmd;
5550         struct ldb_val nmd_value;
5551         struct GUID remote_parent_guid;
5552         unsigned int i;
5553         uint32_t j,ni=0;
5554         unsigned int removed_attrs = 0;
5555         int ret;
5556         int (*callback)(struct ldb_request *req, struct ldb_reply *ares) = replmd_op_callback;
5557         bool isDeleted = false;
5558         bool local_isDeleted = false;
5559         bool remote_isDeleted = false;
5560         bool take_remote_isDeleted = false;
5561         bool sd_updated = false;
5562         bool renamed = false;
5563         bool is_schema_nc = false;
5564         NTSTATUS nt_status;
5565         const struct ldb_val *old_rdn, *new_rdn;
5566         struct replmd_private *replmd_private =
5567                 talloc_get_type(ldb_module_get_private(ar->module),
5568                                 struct replmd_private);
5569         NTTIME now;
5570         time_t t = time(NULL);
5571         unix_to_nt_time(&now, t);
5572
5573         ldb = ldb_module_get_ctx(ar->module);
5574         msg = ar->objs->objects[ar->index_current].msg;
5575
5576         is_schema_nc = ldb_dn_compare_base(replmd_private->schema_dn, msg->dn) == 0;
5577
5578         rmd = ar->objs->objects[ar->index_current].meta_data;
5579         ZERO_STRUCT(omd);
5580         omd.version = 1;
5581
5582         /* find existing meta data */
5583         omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData");
5584         if (omd_value) {
5585                 ndr_err = ndr_pull_struct_blob(omd_value, ar, &omd,
5586                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
5587                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5588                         nt_status = ndr_map_error2ntstatus(ndr_err);
5589                         return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
5590                 }
5591
5592                 if (omd.version != 1) {
5593                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
5594                 }
5595         }
5596
5597         if (DEBUGLVL(8)) {
5598                 struct GUID_txt_buf guid_txt;
5599
5600                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
5601                                                            LDB_CHANGETYPE_MODIFY, msg);
5602                 DEBUG(8, ("Initial DRS replication modify message of %s is:\n%s\n"
5603                           "%s\n"
5604                           "%s\n",
5605                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid, &guid_txt),
5606                           s,
5607                           ndr_print_struct_string(s,
5608                                                   (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
5609                                                   "existing replPropertyMetaData",
5610                                                   &omd),
5611                           ndr_print_struct_string(s,
5612                                                   (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
5613                                                   "incoming replPropertyMetaData",
5614                                                   rmd)));
5615                 talloc_free(s);
5616         } else if (DEBUGLVL(4)) {
5617                 struct GUID_txt_buf guid_txt;
5618
5619                 DEBUG(4, ("Initial DRS replication modify DN of %s is: %s\n",
5620                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
5621                                           &guid_txt),
5622                           ldb_dn_get_linearized(msg->dn)));
5623         }
5624                 
5625         local_isDeleted = ldb_msg_find_attr_as_bool(ar->search_msg,
5626                                                     "isDeleted", false);
5627         remote_isDeleted = ldb_msg_find_attr_as_bool(msg,
5628                                                      "isDeleted", false);
5629
5630         /*
5631          * Fill in the remote_parent_guid with the GUID or an all-zero
5632          * GUID.
5633          */
5634         if (ar->objs->objects[ar->index_current].parent_guid != NULL) {
5635                 remote_parent_guid = *ar->objs->objects[ar->index_current].parent_guid;
5636         } else {
5637                 remote_parent_guid = GUID_zero();
5638         }
5639
5640         /*
5641          * To ensure we follow a complex rename chain around, we have
5642          * to confirm that the DN is the same (mostly to confirm the
5643          * RDN) and the parentGUID is the same.
5644          *
5645          * This ensures we keep things under the correct parent, which
5646          * replmd_replicated_handle_rename() will do.
5647          */
5648
5649         if (strcmp(ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(ar->search_msg->dn)) == 0
5650             && GUID_equal(&remote_parent_guid, &ar->local_parent_guid)) {
5651                 ret = LDB_SUCCESS;
5652         } else {
5653                 /*
5654                  * handle renames, even just by case that come in over
5655                  * DRS.  Changes in the parent DN don't hit us here,
5656                  * because the search for a parent will clean up those
5657                  * components.
5658                  *
5659                  * We also have already filtered out the case where
5660                  * the peer has an older name to what we have (see
5661                  * replmd_replicated_apply_search_callback())
5662                  */
5663                 ret = replmd_replicated_handle_rename(ar, msg, ar->req, &renamed);
5664         }
5665
5666         if (ret != LDB_SUCCESS) {
5667                 ldb_debug(ldb, LDB_DEBUG_FATAL,
5668                           "replmd_replicated_request rename %s => %s failed - %s\n",
5669                           ldb_dn_get_linearized(ar->search_msg->dn),
5670                           ldb_dn_get_linearized(msg->dn),
5671                           ldb_errstring(ldb));
5672                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
5673         }
5674
5675         if (renamed == true) {
5676                 /*
5677                  * Set the callback to one that will fix up the name
5678                  * metadata on the new conflict DN
5679                  */
5680                 callback = replmd_op_name_modify_callback;
5681         }
5682
5683         ZERO_STRUCT(nmd);
5684         nmd.version = 1;
5685         nmd.ctr.ctr1.count = omd.ctr.ctr1.count + rmd->ctr.ctr1.count;
5686         nmd.ctr.ctr1.array = talloc_array(ar,
5687                                           struct replPropertyMetaData1,
5688                                           nmd.ctr.ctr1.count);
5689         if (!nmd.ctr.ctr1.array) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
5690
5691         /* first copy the old meta data */
5692         for (i=0; i < omd.ctr.ctr1.count; i++) {
5693                 nmd.ctr.ctr1.array[ni]  = omd.ctr.ctr1.array[i];
5694                 ni++;
5695         }
5696
5697         ar->seq_num = 0;
5698         /* now merge in the new meta data */
5699         for (i=0; i < rmd->ctr.ctr1.count; i++) {
5700                 bool found = false;
5701
5702                 for (j=0; j < ni; j++) {
5703                         bool cmp;
5704
5705                         if (rmd->ctr.ctr1.array[i].attid != nmd.ctr.ctr1.array[j].attid) {
5706                                 continue;
5707                         }
5708
5709                         cmp = replmd_replPropertyMetaData1_new_should_be_taken(
5710                                 ar->objs->dsdb_repl_flags,
5711                                 &nmd.ctr.ctr1.array[j],
5712                                 &rmd->ctr.ctr1.array[i]);
5713                         if (cmp) {
5714                                 /* replace the entry */
5715                                 nmd.ctr.ctr1.array[j] = rmd->ctr.ctr1.array[i];
5716                                 if (ar->seq_num == 0) {
5717                                         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
5718                                         if (ret != LDB_SUCCESS) {
5719                                                 return replmd_replicated_request_error(ar, ret);
5720                                         }
5721                                 }
5722                                 nmd.ctr.ctr1.array[j].local_usn = ar->seq_num;
5723                                 switch (nmd.ctr.ctr1.array[j].attid) {
5724                                 case DRSUAPI_ATTID_ntSecurityDescriptor:
5725                                         sd_updated = true;
5726                                         break;
5727                                 case DRSUAPI_ATTID_isDeleted:
5728                                         take_remote_isDeleted = true;
5729                                         break;
5730                                 default:
5731                                         break;
5732                                 }
5733                                 found = true;
5734                                 break;
5735                         }
5736
5737                         if (rmd->ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType) {
5738                                 DEBUG(3,("Discarding older DRS attribute update to %s on %s from %s\n",
5739                                          msg->elements[i-removed_attrs].name,
5740                                          ldb_dn_get_linearized(msg->dn),
5741                                          GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
5742                         }
5743
5744                         /* we don't want to apply this change so remove the attribute */
5745                         ldb_msg_remove_element(msg, &msg->elements[i-removed_attrs]);
5746                         removed_attrs++;
5747
5748                         found = true;
5749                         break;
5750                 }
5751
5752                 if (found) continue;
5753
5754                 nmd.ctr.ctr1.array[ni] = rmd->ctr.ctr1.array[i];
5755                 if (ar->seq_num == 0) {
5756                         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ar->seq_num);
5757                         if (ret != LDB_SUCCESS) {
5758                                 return replmd_replicated_request_error(ar, ret);
5759                         }
5760                 }
5761                 nmd.ctr.ctr1.array[ni].local_usn = ar->seq_num;
5762                 switch (nmd.ctr.ctr1.array[ni].attid) {
5763                 case DRSUAPI_ATTID_ntSecurityDescriptor:
5764                         sd_updated = true;
5765                         break;
5766                 case DRSUAPI_ATTID_isDeleted:
5767                         take_remote_isDeleted = true;
5768                         break;
5769                 default:
5770                         break;
5771                 }
5772                 ni++;
5773         }
5774
5775         /*
5776          * finally correct the size of the meta_data array
5777          */
5778         nmd.ctr.ctr1.count = ni;
5779
5780         new_rdn = ldb_dn_get_rdn_val(msg->dn);
5781         old_rdn = ldb_dn_get_rdn_val(ar->search_msg->dn);
5782
5783         if (renamed) {
5784                 ret = replmd_update_rpmd_rdn_attr(ldb, msg, new_rdn, old_rdn,
5785                                                   &nmd, ar, now, is_schema_nc,
5786                                                   false);
5787                 if (ret != LDB_SUCCESS) {
5788                         ldb_asprintf_errstring(ldb, "%s: error during DRS repl merge: %s", __func__, ldb_errstring(ldb));
5789                         return replmd_replicated_request_error(ar, ret);
5790                 }
5791         }
5792         /*
5793          * sort the new meta data array
5794          */
5795         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, msg->dn);
5796         if (ret != LDB_SUCCESS) {
5797                 ldb_asprintf_errstring(ldb, "%s: error during DRS repl merge: %s", __func__, ldb_errstring(ldb));
5798                 return ret;
5799         }
5800
5801         /*
5802          * Work out if this object is deleted, so we can prune any extra attributes.  See MS-DRSR 4.1.10.6.9
5803          * UpdateObject.
5804          *
5805          * This also controls SD propagation below
5806          */
5807         if (take_remote_isDeleted) {
5808                 isDeleted = remote_isDeleted;
5809         } else {
5810                 isDeleted = local_isDeleted;
5811         }
5812
5813         ar->isDeleted = isDeleted;
5814
5815         /*
5816          * check if some replicated attributes left, otherwise skip the ldb_modify() call
5817          */
5818         if (msg->num_elements == 0) {
5819                 ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_apply_merge[%u]: skip replace\n",
5820                           ar->index_current);
5821
5822                 return replmd_replicated_apply_isDeleted(ar);
5823         }
5824
5825         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_replicated_apply_merge[%u]: replace %u attributes\n",
5826                   ar->index_current, msg->num_elements);
5827
5828         if (renamed) {
5829                 sd_updated = true;
5830         }
5831
5832         if (sd_updated && !isDeleted) {
5833                 ret = dsdb_module_schedule_sd_propagation(ar->module,
5834                                                           ar->objs->partition_dn,
5835                                                           msg->dn, true);
5836                 if (ret != LDB_SUCCESS) {
5837                         return ldb_operr(ldb);
5838                 }
5839         }
5840
5841         /* create the meta data value */
5842         ndr_err = ndr_push_struct_blob(&nmd_value, msg, &nmd,
5843                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
5844         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5845                 nt_status = ndr_map_error2ntstatus(ndr_err);
5846                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
5847         }
5848
5849         /*
5850          * when we know that we'll modify the record, add the whenChanged, uSNChanged
5851          * and replPopertyMetaData attributes
5852          */
5853         ret = ldb_msg_add_string(msg, "whenChanged", ar->objs->objects[ar->index_current].when_changed);
5854         if (ret != LDB_SUCCESS) {
5855                 return replmd_replicated_request_error(ar, ret);
5856         }
5857         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ar->seq_num);
5858         if (ret != LDB_SUCCESS) {
5859                 return replmd_replicated_request_error(ar, ret);
5860         }
5861         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
5862         if (ret != LDB_SUCCESS) {
5863                 return replmd_replicated_request_error(ar, ret);
5864         }
5865
5866         replmd_ldb_message_sort(msg, ar->schema);
5867
5868         /* we want to replace the old values */
5869         for (i=0; i < msg->num_elements; i++) {
5870                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
5871                 if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0) {
5872                         if (msg->elements[i].num_values == 0) {
5873                                 ldb_asprintf_errstring(ldb, __location__
5874                                                        ": objectClass removed on %s, aborting replication\n",
5875                                                        ldb_dn_get_linearized(msg->dn));
5876                                 return replmd_replicated_request_error(ar, LDB_ERR_OBJECT_CLASS_VIOLATION);
5877                         }
5878                 }
5879         }
5880
5881         if (DEBUGLVL(8)) {
5882                 struct GUID_txt_buf guid_txt;
5883
5884                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
5885                                                            LDB_CHANGETYPE_MODIFY,
5886                                                            msg);
5887                 DEBUG(8, ("Final DRS replication modify message of %s:\n%s\n",
5888                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
5889                                           &guid_txt),
5890                           s));
5891                 talloc_free(s);
5892         } else if (DEBUGLVL(4)) {
5893                 struct GUID_txt_buf guid_txt;
5894
5895                 DEBUG(4, ("Final DRS replication modify DN of %s is %s\n",
5896                           GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
5897                                           &guid_txt),
5898                           ldb_dn_get_linearized(msg->dn)));
5899         }
5900
5901         ret = ldb_build_mod_req(&change_req,
5902                                 ldb,
5903                                 ar,
5904                                 msg,
5905                                 ar->controls,
5906                                 ar,
5907                                 callback,
5908                                 ar->req);
5909         LDB_REQ_SET_LOCATION(change_req);
5910         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5911
5912         /* current partition control needed by "repmd_op_callback" */
5913         ret = ldb_request_add_control(change_req,
5914                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
5915                                       false, NULL);
5916         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
5917
5918         return ldb_next_request(ar->module, change_req);
5919 }
5920
5921 static int replmd_replicated_apply_search_callback(struct ldb_request *req,
5922                                                    struct ldb_reply *ares)
5923 {
5924         struct replmd_replicated_request *ar = talloc_get_type(req->context,
5925                                                struct replmd_replicated_request);
5926         int ret;
5927
5928         if (!ares) {
5929                 return ldb_module_done(ar->req, NULL, NULL,
5930                                         LDB_ERR_OPERATIONS_ERROR);
5931         }
5932         if (ares->error != LDB_SUCCESS &&
5933             ares->error != LDB_ERR_NO_SUCH_OBJECT) {
5934                 return ldb_module_done(ar->req, ares->controls,
5935                                         ares->response, ares->error);
5936         }
5937
5938         switch (ares->type) {
5939         case LDB_REPLY_ENTRY:
5940                 ar->search_msg = talloc_steal(ar, ares->message);
5941                 break;
5942
5943         case LDB_REPLY_REFERRAL:
5944                 /* we ignore referrals */
5945                 break;
5946
5947         case LDB_REPLY_DONE:
5948         {
5949                 struct replPropertyMetaData1 *md_remote;
5950                 struct replPropertyMetaData1 *md_local;
5951
5952                 struct replPropertyMetaDataBlob omd;
5953                 const struct ldb_val *omd_value;
5954                 struct replPropertyMetaDataBlob *rmd;
5955                 struct ldb_message *msg;
5956                 int instanceType;
5957                 ar->objs->objects[ar->index_current].local_parent_dn = NULL;
5958                 ar->objs->objects[ar->index_current].last_known_parent = NULL;
5959
5960                 /*
5961                  * This is the ADD case, find the appropriate parent,
5962                  * as this object doesn't exist locally:
5963                  */
5964                 if (ar->search_msg == NULL) {
5965                         ret = replmd_replicated_apply_search_for_parent(ar);
5966                         if (ret != LDB_SUCCESS) {
5967                                 return ldb_module_done(ar->req, NULL, NULL, ret);
5968                         }
5969                         talloc_free(ares);
5970                         return LDB_SUCCESS;
5971                 }
5972
5973                 /*
5974                  * Otherwise, in the MERGE case, work out if we are
5975                  * attempting a rename, and if so find the parent the
5976                  * newly renamed object wants to belong under (which
5977                  * may not be the parent in it's attached string DN
5978                  */
5979                 rmd = ar->objs->objects[ar->index_current].meta_data;
5980                 ZERO_STRUCT(omd);
5981                 omd.version = 1;
5982
5983                 /* find existing meta data */
5984                 omd_value = ldb_msg_find_ldb_val(ar->search_msg, "replPropertyMetaData");
5985                 if (omd_value) {
5986                         enum ndr_err_code ndr_err;
5987                         ndr_err = ndr_pull_struct_blob(omd_value, ar, &omd,
5988                                                        (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
5989                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
5990                                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
5991                                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
5992                         }
5993
5994                         if (omd.version != 1) {
5995                                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
5996                         }
5997                 }
5998
5999                 ar->local_parent_guid = samdb_result_guid(ar->search_msg, "parentGUID");
6000
6001                 instanceType = ldb_msg_find_attr_as_int(ar->search_msg, "instanceType", 0);
6002                 if (((instanceType & INSTANCE_TYPE_IS_NC_HEAD) == 0)
6003                     && GUID_all_zero(&ar->local_parent_guid)) {
6004                         DEBUG(0, ("Refusing to replicate new version of %s "
6005                                   "as local object has an all-zero parentGUID attribute, "
6006                                   "despite not being an NC root\n",
6007                                   ldb_dn_get_linearized(ar->search_msg->dn)));
6008                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6009                 }
6010
6011                 /*
6012                  * now we need to check for double renames. We could have a
6013                  * local rename pending which our replication partner hasn't
6014                  * received yet. We choose which one wins by looking at the
6015                  * attribute stamps on the two objects, the newer one wins.
6016                  *
6017                  * This also simply applies the correct algorithms for
6018                  * determining if a change was made to name at all, or
6019                  * if the object has just been renamed under the same
6020                  * parent.
6021                  */
6022                 md_remote = replmd_replPropertyMetaData1_find_attid(rmd, DRSUAPI_ATTID_name);
6023                 md_local = replmd_replPropertyMetaData1_find_attid(&omd, DRSUAPI_ATTID_name);
6024                 if (!md_local) {
6025                         DEBUG(0,(__location__ ": Failed to find name attribute in local LDB replPropertyMetaData for %s\n",
6026                                  ldb_dn_get_linearized(ar->search_msg->dn)));
6027                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_DB_ERROR);
6028                 }
6029
6030                 /*
6031                  * if there is no name attribute given then we have to assume the
6032                  *  object we've received has the older name
6033                  */
6034                 if (replmd_replPropertyMetaData1_new_should_be_taken(
6035                             ar->objs->dsdb_repl_flags & DSDB_REPL_FLAG_PRIORITISE_INCOMING,
6036                             md_local, md_remote)) {
6037                         struct GUID_txt_buf p_guid_local;
6038                         struct GUID_txt_buf p_guid_remote;
6039                         msg = ar->objs->objects[ar->index_current].msg;
6040
6041                         /* Merge on the existing object, with rename */
6042
6043                         DEBUG(4,(__location__ ": Looking for new parent for object %s currently under %s "
6044                                  "as incoming object changing to %s under %s\n",
6045                                  ldb_dn_get_linearized(ar->search_msg->dn),
6046                                  GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6047                                  ldb_dn_get_linearized(msg->dn),
6048                                  GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6049                                                  &p_guid_remote)));
6050                         ret = replmd_replicated_apply_search_for_parent(ar);
6051                 } else {
6052                         struct GUID_txt_buf p_guid_local;
6053                         struct GUID_txt_buf p_guid_remote;
6054                         msg = ar->objs->objects[ar->index_current].msg;
6055
6056                         /*
6057                          * Merge on the existing object, force no
6058                          * rename (code below just to explain why in
6059                          * the DEBUG() logs)
6060                          */
6061
6062                         if (strcmp(ldb_dn_get_linearized(ar->search_msg->dn),
6063                                    ldb_dn_get_linearized(msg->dn)) == 0) {
6064                                 if (ar->objs->objects[ar->index_current].parent_guid != NULL &&
6065                                     GUID_equal(&ar->local_parent_guid,
6066                                                ar->objs->objects[ar->index_current].parent_guid)
6067                                     == false) {
6068                                         DEBUG(4,(__location__ ": Keeping object %s at under %s "
6069                                                  "despite incoming object changing parent to %s\n",
6070                                                  ldb_dn_get_linearized(ar->search_msg->dn),
6071                                                  GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6072                                                  GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6073                                                                  &p_guid_remote)));
6074                                 }
6075                         } else {
6076                                 DEBUG(4,(__location__ ": Keeping object %s at under %s "
6077                                          " and rejecting older rename to %s under %s\n",
6078                                          ldb_dn_get_linearized(ar->search_msg->dn),
6079                                          GUID_buf_string(&ar->local_parent_guid, &p_guid_local),
6080                                          ldb_dn_get_linearized(msg->dn),
6081                                          GUID_buf_string(ar->objs->objects[ar->index_current].parent_guid,
6082                                                          &p_guid_remote)));
6083                         }
6084                         /*
6085                          * This assignment ensures that the strcmp()
6086                          * and GUID_equal() calls in
6087                          * replmd_replicated_apply_merge() avoids the
6088                          * rename call
6089                          */
6090                         ar->objs->objects[ar->index_current].parent_guid =
6091                                 &ar->local_parent_guid;
6092
6093                         msg->dn = ar->search_msg->dn;
6094                         ret = replmd_replicated_apply_merge(ar);
6095                 }
6096                 if (ret != LDB_SUCCESS) {
6097                         return ldb_module_done(ar->req, NULL, NULL, ret);
6098                 }
6099         }
6100         }
6101
6102         talloc_free(ares);
6103         return LDB_SUCCESS;
6104 }
6105
6106 /**
6107  * Stores the linked attributes received in the replication chunk - these get
6108  * applied at the end of the transaction. We also check that each linked
6109  * attribute is valid, i.e. source and target objects are known.
6110  */
6111 static int replmd_store_linked_attributes(struct replmd_replicated_request *ar)
6112 {
6113         int ret = LDB_SUCCESS;
6114         uint32_t i;
6115         struct ldb_module *module = ar->module;
6116         struct replmd_private *replmd_private =
6117                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
6118         struct ldb_context *ldb;
6119
6120         ldb = ldb_module_get_ctx(module);
6121
6122         DEBUG(4,("linked_attributes_count=%u\n", ar->objs->linked_attributes_count));
6123
6124         /* save away the linked attributes for the end of the transaction */
6125         for (i = 0; i < ar->objs->linked_attributes_count; i++) {
6126                 struct la_entry *la_entry;
6127
6128                 if (replmd_private->la_ctx == NULL) {
6129                         replmd_private->la_ctx = talloc_new(replmd_private);
6130                 }
6131                 la_entry = talloc(replmd_private->la_ctx, struct la_entry);
6132                 if (la_entry == NULL) {
6133                         ldb_oom(ldb);
6134                         return LDB_ERR_OPERATIONS_ERROR;
6135                 }
6136                 la_entry->la = talloc(la_entry, struct drsuapi_DsReplicaLinkedAttribute);
6137                 if (la_entry->la == NULL) {
6138                         talloc_free(la_entry);
6139                         ldb_oom(ldb);
6140                         return LDB_ERR_OPERATIONS_ERROR;
6141                 }
6142                 *la_entry->la = ar->objs->linked_attributes[i];
6143                 la_entry->dsdb_repl_flags = ar->objs->dsdb_repl_flags;
6144
6145                 /* we need to steal the non-scalars so they stay
6146                    around until the end of the transaction */
6147                 talloc_steal(la_entry->la, la_entry->la->identifier);
6148                 talloc_steal(la_entry->la, la_entry->la->value.blob);
6149
6150                 ret = replmd_verify_linked_attribute(ar, la_entry);
6151
6152                 if (ret != LDB_SUCCESS) {
6153                         break;
6154                 }
6155
6156                 DLIST_ADD(replmd_private->la_list, la_entry);
6157         }
6158
6159         return ret;
6160 }
6161
6162 static int replmd_replicated_uptodate_vector(struct replmd_replicated_request *ar);
6163
6164 static int replmd_replicated_apply_next(struct replmd_replicated_request *ar)
6165 {
6166         struct ldb_context *ldb;
6167         int ret;
6168         char *tmp_str;
6169         char *filter;
6170         struct ldb_request *search_req;
6171         static const char *attrs[] = { "repsFrom", "replUpToDateVector",
6172                                        "parentGUID", "instanceType",
6173                                        "replPropertyMetaData", "nTSecurityDescriptor",
6174                                        "isDeleted", NULL };
6175         struct GUID_txt_buf guid_str_buf;
6176
6177         if (ar->index_current >= ar->objs->num_objects) {
6178
6179                 /*
6180                  * Now that we've applied all the objects, check the new linked
6181                  * attributes and store them (we apply them in .prepare_commit)
6182                  */
6183                 ret = replmd_store_linked_attributes(ar);
6184
6185                 if (ret != LDB_SUCCESS) {
6186                         return ret;
6187                 }
6188
6189                 /* done applying objects, move on to the next stage */
6190                 return replmd_replicated_uptodate_vector(ar);
6191         }
6192
6193         ldb = ldb_module_get_ctx(ar->module);
6194         ar->search_msg = NULL;
6195         ar->isDeleted = false;
6196
6197         tmp_str = GUID_buf_string(&ar->objs->objects[ar->index_current].object_guid,
6198                                   &guid_str_buf);
6199
6200         filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
6201         if (!filter) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6202
6203         ret = ldb_build_search_req(&search_req,
6204                                    ldb,
6205                                    ar,
6206                                    ar->objs->partition_dn,
6207                                    LDB_SCOPE_SUBTREE,
6208                                    filter,
6209                                    attrs,
6210                                    NULL,
6211                                    ar,
6212                                    replmd_replicated_apply_search_callback,
6213                                    ar->req);
6214         LDB_REQ_SET_LOCATION(search_req);
6215
6216         ret = dsdb_request_add_controls(search_req, DSDB_SEARCH_SHOW_RECYCLED);
6217
6218         if (ret != LDB_SUCCESS) {
6219                 return ret;
6220         }
6221
6222         return ldb_next_request(ar->module, search_req);
6223 }
6224
6225 /*
6226  * This is essentially a wrapper for replmd_replicated_apply_next()
6227  *
6228  * This is needed to ensure that both codepaths call this handler.
6229  */
6230 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar)
6231 {
6232         struct ldb_dn *deleted_objects_dn;
6233         struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
6234         int ret = dsdb_get_deleted_objects_dn(ldb_module_get_ctx(ar->module), msg, msg->dn,
6235                                               &deleted_objects_dn);
6236         if (ar->isDeleted && (ret != LDB_SUCCESS || ldb_dn_compare(msg->dn, deleted_objects_dn) != 0)) {
6237                 /*
6238                  * Do a delete here again, so that if there is
6239                  * anything local that conflicts with this
6240                  * object being deleted, it is removed.  This
6241                  * includes links.  See MS-DRSR 4.1.10.6.9
6242                  * UpdateObject.
6243                  *
6244                  * If the object is already deleted, and there
6245                  * is no more work required, it doesn't do
6246                  * anything.
6247                  */
6248
6249                 /* This has been updated to point to the DN we eventually did the modify on */
6250
6251                 struct ldb_request *del_req;
6252                 struct ldb_result *res;
6253
6254                 TALLOC_CTX *tmp_ctx = talloc_new(ar);
6255                 if (!tmp_ctx) {
6256                         ret = ldb_oom(ldb_module_get_ctx(ar->module));
6257                         return ret;
6258                 }
6259
6260                 res = talloc_zero(tmp_ctx, struct ldb_result);
6261                 if (!res) {
6262                         ret = ldb_oom(ldb_module_get_ctx(ar->module));
6263                         talloc_free(tmp_ctx);
6264                         return ret;
6265                 }
6266
6267                 /* Build a delete request, which hopefully will artually turn into nothing */
6268                 ret = ldb_build_del_req(&del_req, ldb_module_get_ctx(ar->module), tmp_ctx,
6269                                         msg->dn,
6270                                         NULL,
6271                                         res,
6272                                         ldb_modify_default_callback,
6273                                         ar->req);
6274                 LDB_REQ_SET_LOCATION(del_req);
6275                 if (ret != LDB_SUCCESS) {
6276                         talloc_free(tmp_ctx);
6277                         return ret;
6278                 }
6279
6280                 /*
6281                  * This is the guts of the call, call back
6282                  * into our delete code, but setting the
6283                  * re_delete flag so we delete anything that
6284                  * shouldn't be there on a deleted or recycled
6285                  * object
6286                  */
6287                 ret = replmd_delete_internals(ar->module, del_req, true);
6288                 if (ret == LDB_SUCCESS) {
6289                         ret = ldb_wait(del_req->handle, LDB_WAIT_ALL);
6290                 }
6291
6292                 talloc_free(tmp_ctx);
6293                 if (ret != LDB_SUCCESS) {
6294                         return ret;
6295                 }
6296         }
6297
6298         ar->index_current++;
6299         return replmd_replicated_apply_next(ar);
6300 }
6301
6302 static int replmd_replicated_uptodate_modify_callback(struct ldb_request *req,
6303                                                       struct ldb_reply *ares)
6304 {
6305         struct ldb_context *ldb;
6306         struct replmd_replicated_request *ar = talloc_get_type(req->context,
6307                                                struct replmd_replicated_request);
6308         ldb = ldb_module_get_ctx(ar->module);
6309
6310         if (!ares) {
6311                 return ldb_module_done(ar->req, NULL, NULL,
6312                                         LDB_ERR_OPERATIONS_ERROR);
6313         }
6314         if (ares->error != LDB_SUCCESS) {
6315                 return ldb_module_done(ar->req, ares->controls,
6316                                         ares->response, ares->error);
6317         }
6318
6319         if (ares->type != LDB_REPLY_DONE) {
6320                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
6321                 return ldb_module_done(ar->req, NULL, NULL,
6322                                         LDB_ERR_OPERATIONS_ERROR);
6323         }
6324
6325         talloc_free(ares);
6326
6327         return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6328 }
6329
6330 static int replmd_replicated_uptodate_modify(struct replmd_replicated_request *ar)
6331 {
6332         struct ldb_context *ldb;
6333         struct ldb_request *change_req;
6334         enum ndr_err_code ndr_err;
6335         struct ldb_message *msg;
6336         struct replUpToDateVectorBlob ouv;
6337         const struct ldb_val *ouv_value;
6338         const struct drsuapi_DsReplicaCursor2CtrEx *ruv;
6339         struct replUpToDateVectorBlob nuv;
6340         struct ldb_val nuv_value;
6341         struct ldb_message_element *nuv_el = NULL;
6342         struct ldb_message_element *orf_el = NULL;
6343         struct repsFromToBlob nrf;
6344         struct ldb_val *nrf_value = NULL;
6345         struct ldb_message_element *nrf_el = NULL;
6346         unsigned int i;
6347         uint32_t j,ni=0;
6348         bool found = false;
6349         time_t t = time(NULL);
6350         NTTIME now;
6351         int ret;
6352         uint32_t instanceType;
6353
6354         ldb = ldb_module_get_ctx(ar->module);
6355         ruv = ar->objs->uptodateness_vector;
6356         ZERO_STRUCT(ouv);
6357         ouv.version = 2;
6358         ZERO_STRUCT(nuv);
6359         nuv.version = 2;
6360
6361         unix_to_nt_time(&now, t);
6362
6363         if (ar->search_msg == NULL) {
6364                 /* this happens for a REPL_OBJ call where we are
6365                    creating the target object by replicating it. The
6366                    subdomain join code does this for the partition DN
6367                 */
6368                 DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as no target DN\n"));
6369                 return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6370         }
6371
6372         instanceType = ldb_msg_find_attr_as_uint(ar->search_msg, "instanceType", 0);
6373         if (! (instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
6374                 DEBUG(4,(__location__ ": Skipping UDV and repsFrom update as not NC root: %s\n",
6375                          ldb_dn_get_linearized(ar->search_msg->dn)));
6376                 return ldb_module_done(ar->req, NULL, NULL, LDB_SUCCESS);
6377         }
6378
6379         /*
6380          * first create the new replUpToDateVector
6381          */
6382         ouv_value = ldb_msg_find_ldb_val(ar->search_msg, "replUpToDateVector");
6383         if (ouv_value) {
6384                 ndr_err = ndr_pull_struct_blob(ouv_value, ar, &ouv,
6385                                                (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
6386                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6387                         NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6388                         return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6389                 }
6390
6391                 if (ouv.version != 2) {
6392                         return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6393                 }
6394         }
6395
6396         /*
6397          * the new uptodateness vector will at least
6398          * contain 1 entry, one for the source_dsa
6399          *
6400          * plus optional values from our old vector and the one from the source_dsa
6401          */
6402         nuv.ctr.ctr2.count = ouv.ctr.ctr2.count;
6403         if (ruv) nuv.ctr.ctr2.count += ruv->count;
6404         nuv.ctr.ctr2.cursors = talloc_array(ar,
6405                                             struct drsuapi_DsReplicaCursor2,
6406                                             nuv.ctr.ctr2.count);
6407         if (!nuv.ctr.ctr2.cursors) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6408
6409         /* first copy the old vector */
6410         for (i=0; i < ouv.ctr.ctr2.count; i++) {
6411                 nuv.ctr.ctr2.cursors[ni] = ouv.ctr.ctr2.cursors[i];
6412                 ni++;
6413         }
6414
6415         /* merge in the source_dsa vector is available */
6416         for (i=0; (ruv && i < ruv->count); i++) {
6417                 found = false;
6418
6419                 if (GUID_equal(&ruv->cursors[i].source_dsa_invocation_id,
6420                                &ar->our_invocation_id)) {
6421                         continue;
6422                 }
6423
6424                 for (j=0; j < ni; j++) {
6425                         if (!GUID_equal(&ruv->cursors[i].source_dsa_invocation_id,
6426                                         &nuv.ctr.ctr2.cursors[j].source_dsa_invocation_id)) {
6427                                 continue;
6428                         }
6429
6430                         found = true;
6431
6432                         if (ruv->cursors[i].highest_usn > nuv.ctr.ctr2.cursors[j].highest_usn) {
6433                                 nuv.ctr.ctr2.cursors[j] = ruv->cursors[i];
6434                         }
6435                         break;
6436                 }
6437
6438                 if (found) continue;
6439
6440                 /* if it's not there yet, add it */
6441                 nuv.ctr.ctr2.cursors[ni] = ruv->cursors[i];
6442                 ni++;
6443         }
6444
6445         /*
6446          * finally correct the size of the cursors array
6447          */
6448         nuv.ctr.ctr2.count = ni;
6449
6450         /*
6451          * sort the cursors
6452          */
6453         TYPESAFE_QSORT(nuv.ctr.ctr2.cursors, nuv.ctr.ctr2.count, drsuapi_DsReplicaCursor2_compare);
6454
6455         /*
6456          * create the change ldb_message
6457          */
6458         msg = ldb_msg_new(ar);
6459         if (!msg) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6460         msg->dn = ar->search_msg->dn;
6461
6462         ndr_err = ndr_push_struct_blob(&nuv_value, msg, &nuv,
6463                                        (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob);
6464         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6465                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6466                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6467         }
6468         ret = ldb_msg_add_value(msg, "replUpToDateVector", &nuv_value, &nuv_el);
6469         if (ret != LDB_SUCCESS) {
6470                 return replmd_replicated_request_error(ar, ret);
6471         }
6472         nuv_el->flags = LDB_FLAG_MOD_REPLACE;
6473
6474         /*
6475          * now create the new repsFrom value from the given repsFromTo1 structure
6476          */
6477         ZERO_STRUCT(nrf);
6478         nrf.version                                     = 1;
6479         nrf.ctr.ctr1                                    = *ar->objs->source_dsa;
6480         nrf.ctr.ctr1.last_attempt                       = now;
6481         nrf.ctr.ctr1.last_success                       = now;
6482         nrf.ctr.ctr1.result_last_attempt                = WERR_OK;
6483
6484         /*
6485          * first see if we already have a repsFrom value for the current source dsa
6486          * if so we'll later replace this value
6487          */
6488         orf_el = ldb_msg_find_element(ar->search_msg, "repsFrom");
6489         if (orf_el) {
6490                 for (i=0; i < orf_el->num_values; i++) {
6491                         struct repsFromToBlob *trf;
6492
6493                         trf = talloc(ar, struct repsFromToBlob);
6494                         if (!trf) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6495
6496                         ndr_err = ndr_pull_struct_blob(&orf_el->values[i], trf, trf,
6497                                                        (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
6498                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6499                                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6500                                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6501                         }
6502
6503                         if (trf->version != 1) {
6504                                 return replmd_replicated_request_werror(ar, WERR_DS_DRA_INTERNAL_ERROR);
6505                         }
6506
6507                         /*
6508                          * we compare the source dsa objectGUID not the invocation_id
6509                          * because we want only one repsFrom value per source dsa
6510                          * and when the invocation_id of the source dsa has changed we don't need
6511                          * the old repsFrom with the old invocation_id
6512                          */
6513                         if (!GUID_equal(&trf->ctr.ctr1.source_dsa_obj_guid,
6514                                         &ar->objs->source_dsa->source_dsa_obj_guid)) {
6515                                 talloc_free(trf);
6516                                 continue;
6517                         }
6518
6519                         talloc_free(trf);
6520                         nrf_value = &orf_el->values[i];
6521                         break;
6522                 }
6523
6524                 /*
6525                  * copy over all old values to the new ldb_message
6526                  */
6527                 ret = ldb_msg_add_empty(msg, "repsFrom", 0, &nrf_el);
6528                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6529                 *nrf_el = *orf_el;
6530         }
6531
6532         /*
6533          * if we haven't found an old repsFrom value for the current source dsa
6534          * we'll add a new value
6535          */
6536         if (!nrf_value) {
6537                 struct ldb_val zero_value;
6538                 ZERO_STRUCT(zero_value);
6539                 ret = ldb_msg_add_value(msg, "repsFrom", &zero_value, &nrf_el);
6540                 if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6541
6542                 nrf_value = &nrf_el->values[nrf_el->num_values - 1];
6543         }
6544
6545         /* we now fill the value which is already attached to ldb_message */
6546         ndr_err = ndr_push_struct_blob(nrf_value, msg,
6547                                        &nrf,
6548                                        (ndr_push_flags_fn_t)ndr_push_repsFromToBlob);
6549         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
6550                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
6551                 return replmd_replicated_request_werror(ar, ntstatus_to_werror(nt_status));
6552         }
6553
6554         /*
6555          * the ldb_message_element for the attribute, has all the old values and the new one
6556          * so we'll replace the whole attribute with all values
6557          */
6558         nrf_el->flags = LDB_FLAG_MOD_REPLACE;
6559
6560         if (CHECK_DEBUGLVL(4)) {
6561                 char *s = ldb_ldif_message_redacted_string(ldb, ar,
6562                                                            LDB_CHANGETYPE_MODIFY,
6563                                                            msg);
6564                 DEBUG(4, ("DRS replication uptodate modify message:\n%s\n", s));
6565                 talloc_free(s);
6566         }
6567
6568         /* prepare the ldb_modify() request */
6569         ret = ldb_build_mod_req(&change_req,
6570                                 ldb,
6571                                 ar,
6572                                 msg,
6573                                 ar->controls,
6574                                 ar,
6575                                 replmd_replicated_uptodate_modify_callback,
6576                                 ar->req);
6577         LDB_REQ_SET_LOCATION(change_req);
6578         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6579
6580         return ldb_next_request(ar->module, change_req);
6581 }
6582
6583 static int replmd_replicated_uptodate_search_callback(struct ldb_request *req,
6584                                                       struct ldb_reply *ares)
6585 {
6586         struct replmd_replicated_request *ar = talloc_get_type(req->context,
6587                                                struct replmd_replicated_request);
6588         int ret;
6589
6590         if (!ares) {
6591                 return ldb_module_done(ar->req, NULL, NULL,
6592                                         LDB_ERR_OPERATIONS_ERROR);
6593         }
6594         if (ares->error != LDB_SUCCESS &&
6595             ares->error != LDB_ERR_NO_SUCH_OBJECT) {
6596                 return ldb_module_done(ar->req, ares->controls,
6597                                         ares->response, ares->error);
6598         }
6599
6600         switch (ares->type) {
6601         case LDB_REPLY_ENTRY:
6602                 ar->search_msg = talloc_steal(ar, ares->message);
6603                 break;
6604
6605         case LDB_REPLY_REFERRAL:
6606                 /* we ignore referrals */
6607                 break;
6608
6609         case LDB_REPLY_DONE:
6610                 ret = replmd_replicated_uptodate_modify(ar);
6611                 if (ret != LDB_SUCCESS) {
6612                         return ldb_module_done(ar->req, NULL, NULL, ret);
6613                 }
6614         }
6615
6616         talloc_free(ares);
6617         return LDB_SUCCESS;
6618 }
6619
6620
6621 static int replmd_replicated_uptodate_vector(struct replmd_replicated_request *ar)
6622 {
6623         struct ldb_context *ldb = ldb_module_get_ctx(ar->module);
6624         struct replmd_private *replmd_private =
6625                 talloc_get_type_abort(ldb_module_get_private(ar->module),
6626                 struct replmd_private);
6627         int ret;
6628         static const char *attrs[] = {
6629                 "replUpToDateVector",
6630                 "repsFrom",
6631                 "instanceType",
6632                 NULL
6633         };
6634         struct ldb_request *search_req;
6635
6636         ar->search_msg = NULL;
6637
6638         /*
6639          * Let the caller know that we did an originating updates
6640          */
6641         ar->objs->originating_updates = replmd_private->originating_updates;
6642
6643         ret = ldb_build_search_req(&search_req,
6644                                    ldb,
6645                                    ar,
6646                                    ar->objs->partition_dn,
6647                                    LDB_SCOPE_BASE,
6648                                    "(objectClass=*)",
6649                                    attrs,
6650                                    NULL,
6651                                    ar,
6652                                    replmd_replicated_uptodate_search_callback,
6653                                    ar->req);
6654         LDB_REQ_SET_LOCATION(search_req);
6655         if (ret != LDB_SUCCESS) return replmd_replicated_request_error(ar, ret);
6656
6657         return ldb_next_request(ar->module, search_req);
6658 }
6659
6660
6661
6662 static int replmd_extended_replicated_objects(struct ldb_module *module, struct ldb_request *req)
6663 {
6664         struct ldb_context *ldb;
6665         struct dsdb_extended_replicated_objects *objs;
6666         struct replmd_replicated_request *ar;
6667         struct ldb_control **ctrls;
6668         int ret;
6669
6670         ldb = ldb_module_get_ctx(module);
6671
6672         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_extended_replicated_objects\n");
6673
6674         objs = talloc_get_type(req->op.extended.data, struct dsdb_extended_replicated_objects);
6675         if (!objs) {
6676                 ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_extended_replicated_objects: invalid extended data\n");
6677                 return LDB_ERR_PROTOCOL_ERROR;
6678         }
6679
6680         if (objs->version != DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION) {
6681                 ldb_debug(ldb, LDB_DEBUG_FATAL, "replmd_extended_replicated_objects: extended data invalid version [%u != %u]\n",
6682                           objs->version, DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION);
6683                 return LDB_ERR_PROTOCOL_ERROR;
6684         }
6685
6686         ar = replmd_ctx_init(module, req);
6687         if (!ar)
6688                 return LDB_ERR_OPERATIONS_ERROR;
6689
6690         /* Set the flags to have the replmd_op_callback run over the full set of objects */
6691         ar->apply_mode = true;
6692         ar->objs = objs;
6693         ar->schema = dsdb_get_schema(ldb, ar);
6694         if (!ar->schema) {
6695                 ldb_debug_set(ldb, LDB_DEBUG_FATAL, "replmd_ctx_init: no loaded schema found\n");
6696                 talloc_free(ar);
6697                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
6698                 return LDB_ERR_CONSTRAINT_VIOLATION;
6699         }
6700
6701         ctrls = req->controls;
6702
6703         if (req->controls) {
6704                 req->controls = talloc_memdup(ar, req->controls,
6705                                               talloc_get_size(req->controls));
6706                 if (!req->controls) return replmd_replicated_request_werror(ar, WERR_NOT_ENOUGH_MEMORY);
6707         }
6708
6709         ret = ldb_request_add_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID, false, NULL);
6710         if (ret != LDB_SUCCESS) {
6711                 return ret;
6712         }
6713
6714         /* If this change contained linked attributes in the body
6715          * (rather than in the links section) we need to update
6716          * backlinks in linked_attributes */
6717         ret = ldb_request_add_control(req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
6718         if (ret != LDB_SUCCESS) {
6719                 return ret;
6720         }
6721
6722         ar->controls = req->controls;
6723         req->controls = ctrls;
6724
6725         return replmd_replicated_apply_next(ar);
6726 }
6727
6728 /**
6729  * Checks how to handle an missing target - either we need to fail the
6730  * replication and retry with GET_TGT, ignore the link and continue, or try to
6731  * add a partial link to an unknown target.
6732  */
6733 static int replmd_allow_missing_target(struct ldb_module *module,
6734                                        TALLOC_CTX *mem_ctx,
6735                                        struct ldb_dn *target_dn,
6736                                        struct ldb_dn *source_dn,
6737                                        bool is_obj_commit,
6738                                        struct GUID *guid,
6739                                        uint32_t dsdb_repl_flags,
6740                                        bool *ignore_link,
6741                                        const char * missing_str)
6742 {
6743         struct ldb_context *ldb = ldb_module_get_ctx(module);
6744         bool is_in_same_nc;
6745
6746         /*
6747          * we may not be able to resolve link targets properly when
6748          * dealing with subsets of objects, e.g. the source is a
6749          * critical object and the target isn't
6750          *
6751          * TODO:
6752          * When we implement Trusted Domains we need to consider
6753          * whether they get treated as an incomplete replica here or not
6754          */
6755         if (dsdb_repl_flags & DSDB_REPL_FLAG_OBJECT_SUBSET) {
6756
6757                 /*
6758                  * Ignore the link. We don't increase the highwater-mark in
6759                  * the object subset cases, so subsequent replications should
6760                  * resolve any missing links
6761                  */
6762                 DEBUG(2, ("%s target %s linked from %s\n", missing_str,
6763                           ldb_dn_get_linearized(target_dn),
6764                           ldb_dn_get_linearized(source_dn)));
6765                 *ignore_link = true;
6766                 return LDB_SUCCESS;
6767         }
6768
6769         if (dsdb_repl_flags & DSDB_REPL_FLAG_TARGETS_UPTODATE) {
6770
6771                 /*
6772                  * target should already be up-to-date so there's no point in
6773                  * retrying. This could be due to bad timing, or if a target
6774                  * on a one-way link was deleted. We ignore the link rather
6775                  * than failing the replication cycle completely
6776                  */
6777                 *ignore_link = true;
6778                 DBG_WARNING("%s is %s but up to date. Ignoring link from %s\n",
6779                             ldb_dn_get_linearized(target_dn), missing_str,
6780                             ldb_dn_get_linearized(source_dn));
6781                 return LDB_SUCCESS;
6782         }
6783         
6784         is_in_same_nc = dsdb_objects_have_same_nc(ldb,
6785                                                   mem_ctx,
6786                                                   source_dn,
6787                                                   target_dn);
6788         if (is_in_same_nc) {
6789                 /* fail the replication and retry with GET_TGT */
6790                 ldb_asprintf_errstring(ldb, "%s target %s GUID %s linked from %s\n",
6791                                        missing_str,
6792                                        ldb_dn_get_linearized(target_dn),
6793                                        GUID_string(mem_ctx, guid),
6794                                        ldb_dn_get_linearized(source_dn));
6795                 return LDB_ERR_NO_SUCH_OBJECT;
6796         }
6797
6798         /*
6799          * The target of the cross-partition link is missing. Continue
6800          * and try to at least add the forward-link. This isn't great,
6801          * but a partial link can be fixed by dbcheck, so it's better
6802          * than dropping the link completely.
6803          */
6804         *ignore_link = false;
6805
6806         if (is_obj_commit) {
6807
6808                 /*
6809                  * Only log this when we're actually committing the objects.
6810                  * This avoids spurious logs, i.e. if we're just verifying the
6811                  * received link during a join.
6812                  */
6813                 DBG_WARNING("%s cross-partition target %s linked from %s\n",
6814                             missing_str, ldb_dn_get_linearized(target_dn),
6815                             ldb_dn_get_linearized(source_dn));
6816         }
6817         
6818         return LDB_SUCCESS;
6819 }
6820
6821 /**
6822  * Checks that the target object for a linked attribute exists.
6823  * @param guid returns the target object's GUID (is returned)if it exists)
6824  * @param ignore_link set to true if the linked attribute should be ignored
6825  * (i.e. the target doesn't exist, but that it's OK to skip the link)
6826  */
6827 static int replmd_check_target_exists(struct ldb_module *module,
6828                                       struct dsdb_dn *dsdb_dn,
6829                                       struct la_entry *la_entry,
6830                                       struct ldb_dn *source_dn,
6831                                       bool is_obj_commit,
6832                                       struct GUID *guid,
6833                                       bool *ignore_link)
6834 {
6835         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
6836         struct ldb_context *ldb = ldb_module_get_ctx(module);
6837         struct ldb_result *target_res;
6838         TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
6839         const char *attrs[] = { "isDeleted", "isRecycled", NULL };
6840         NTSTATUS ntstatus;
6841         int ret;
6842         enum deletion_state target_deletion_state = OBJECT_REMOVED;
6843         bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) ? true : false;
6844
6845         *ignore_link = false;
6846         ntstatus = dsdb_get_extended_dn_guid(dsdb_dn->dn, guid, "GUID");
6847
6848         if (!NT_STATUS_IS_OK(ntstatus) && !active) {
6849
6850                 /*
6851                  * This strange behaviour (allowing a NULL/missing
6852                  * GUID) originally comes from:
6853                  *
6854                  * commit e3054ce0fe0f8f62d2f5b2a77893e7a1479128bd
6855                  * Author: Andrew Tridgell <tridge@samba.org>
6856                  * Date:   Mon Dec 21 21:21:55 2009 +1100
6857                  *
6858                  *  s4-drs: cope better with NULL GUIDS from DRS
6859                  *
6860                  *  It is valid to get a NULL GUID over DRS for a deleted forward link. We
6861                  *  need to match by DN if possible when seeing if we should update an
6862                  *  existing link.
6863                  *
6864                  *  Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
6865                  */
6866                 ret = dsdb_module_search_dn(module, tmp_ctx, &target_res,
6867                                             dsdb_dn->dn, attrs,
6868                                             DSDB_FLAG_NEXT_MODULE |
6869                                             DSDB_SEARCH_SHOW_RECYCLED |
6870                                             DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
6871                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
6872                                             NULL);
6873         } else if (!NT_STATUS_IS_OK(ntstatus)) {
6874                 ldb_asprintf_errstring(ldb, "Failed to find GUID in linked attribute 0x%x blob for %s from %s",
6875                                        la->attid,
6876                                        ldb_dn_get_linearized(dsdb_dn->dn),
6877                                        ldb_dn_get_linearized(source_dn));
6878                 talloc_free(tmp_ctx);
6879                 return LDB_ERR_OPERATIONS_ERROR;
6880         } else {
6881                 ret = dsdb_module_search(module, tmp_ctx, &target_res,
6882                                          NULL, LDB_SCOPE_SUBTREE,
6883                                          attrs,
6884                                          DSDB_FLAG_NEXT_MODULE |
6885                                          DSDB_SEARCH_SHOW_RECYCLED |
6886                                          DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
6887                                          DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
6888                                          NULL,
6889                                          "objectGUID=%s",
6890                                          GUID_string(tmp_ctx, guid));
6891         }
6892
6893         if (ret != LDB_SUCCESS) {
6894                 ldb_asprintf_errstring(ldb, "Failed to re-resolve GUID %s: %s\n",
6895                                        GUID_string(tmp_ctx, guid),
6896                                        ldb_errstring(ldb));
6897                 talloc_free(tmp_ctx);
6898                 return ret;
6899         }
6900
6901         if (target_res->count == 0) {
6902
6903                 /*
6904                  * target object is unknown. Check whether to ignore the link,
6905                  * fail the replication, or add a partial link
6906                  */
6907                 ret = replmd_allow_missing_target(module, tmp_ctx, dsdb_dn->dn,
6908                                                   source_dn, is_obj_commit, guid,
6909                                                   la_entry->dsdb_repl_flags,
6910                                                   ignore_link, "Unknown");
6911
6912         } else if (target_res->count != 1) {
6913                 ldb_asprintf_errstring(ldb, "More than one object found matching objectGUID %s\n",
6914                                        GUID_string(tmp_ctx, guid));
6915                 ret = LDB_ERR_OPERATIONS_ERROR;
6916         } else {
6917                 struct ldb_message *target_msg = target_res->msgs[0];
6918
6919                 dsdb_dn->dn = talloc_steal(dsdb_dn, target_msg->dn);
6920
6921                 /* Get the object's state (i.e. Not Deleted, Tombstone, etc) */
6922                 replmd_deletion_state(module, target_msg,
6923                                       &target_deletion_state, NULL);
6924
6925                 /*
6926                  * Check for deleted objects as per MS-DRSR 4.1.10.6.14
6927                  * ProcessLinkValue(). Link updates should not be sent for
6928                  * recycled and tombstone objects (deleting the links should
6929                  * happen when we delete the object). This probably means our
6930                  * copy of the target object isn't up to date.
6931                  */
6932                 if (target_deletion_state >= OBJECT_RECYCLED) {
6933
6934                         /*
6935                          * target object is deleted. Check whether to ignore the
6936                          * link, fail the replication, or add a partial link
6937                          */
6938                         ret = replmd_allow_missing_target(module, tmp_ctx,
6939                                                           dsdb_dn->dn, source_dn,
6940                                                           is_obj_commit, guid,
6941                                                           la_entry->dsdb_repl_flags,
6942                                                           ignore_link, "Deleted");
6943                 }
6944         }
6945
6946         talloc_free(tmp_ctx);
6947         return ret;
6948 }
6949
6950 /**
6951  * Extracts the key details about the source/target object for a
6952  * linked-attribute entry.
6953  * This returns the following details:
6954  * @param ret_attr the schema details for the linked attribute
6955  * @param source_msg the search result for the source object
6956  * @param target_dsdb_dn the unpacked DN info for the target object
6957  */
6958 static int replmd_extract_la_entry_details(struct ldb_module *module,
6959                                            struct la_entry *la_entry,
6960                                            TALLOC_CTX *mem_ctx,
6961                                            const struct dsdb_attribute **ret_attr,
6962                                            struct ldb_message **source_msg,
6963                                            struct dsdb_dn **target_dsdb_dn)
6964 {
6965         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
6966         struct ldb_context *ldb = ldb_module_get_ctx(module);
6967         const struct dsdb_schema *schema = dsdb_get_schema(ldb, mem_ctx);
6968         int ret;
6969         const struct dsdb_attribute *attr;
6970         WERROR status;
6971         struct ldb_result *res;
6972         const char *attrs[4];
6973
6974 /*
6975 linked_attributes[0]:
6976      &objs->linked_attributes[i]: struct drsuapi_DsReplicaLinkedAttribute
6977         identifier               : *
6978             identifier: struct drsuapi_DsReplicaObjectIdentifier
6979                 __ndr_size               : 0x0000003a (58)
6980                 __ndr_size_sid           : 0x00000000 (0)
6981                 guid                     : 8e95b6a9-13dd-4158-89db-3220a5be5cc7
6982                 sid                      : S-0-0
6983                 __ndr_size_dn            : 0x00000000 (0)
6984                 dn                       : ''
6985         attid                    : DRSUAPI_ATTID_member (0x1F)
6986         value: struct drsuapi_DsAttributeValue
6987             __ndr_size               : 0x0000007e (126)
6988             blob                     : *
6989                 blob                     : DATA_BLOB length=126
6990         flags                    : 0x00000001 (1)
6991                1: DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE
6992         originating_add_time     : Wed Sep  2 22:20:01 2009 EST
6993         meta_data: struct drsuapi_DsReplicaMetaData
6994             version                  : 0x00000015 (21)
6995             originating_change_time  : Wed Sep  2 23:39:07 2009 EST
6996             originating_invocation_id: 794640f3-18cf-40ee-a211-a93992b67a64
6997             originating_usn          : 0x000000000001e19c (123292)
6998
6999 (for cases where the link is to a normal DN)
7000      &target: struct drsuapi_DsReplicaObjectIdentifier3
7001         __ndr_size               : 0x0000007e (126)
7002         __ndr_size_sid           : 0x0000001c (28)
7003         guid                     : 7639e594-db75-4086-b0d4-67890ae46031
7004         sid                      : S-1-5-21-2848215498-2472035911-1947525656-19924
7005         __ndr_size_dn            : 0x00000022 (34)
7006         dn                       : 'CN=UOne,OU=TestOU,DC=vsofs8,DC=com'
7007  */
7008
7009         /* find the attribute being modified */
7010         attr = dsdb_attribute_by_attributeID_id(schema, la->attid);
7011         if (attr == NULL) {
7012                 struct GUID_txt_buf guid_str;
7013                 ldb_asprintf_errstring(ldb, "Unable to find attributeID 0x%x for link on <GUID=%s>",
7014                                        la->attid,
7015                                        GUID_buf_string(&la->identifier->guid,
7016                                                        &guid_str));
7017                 return LDB_ERR_OPERATIONS_ERROR;
7018         }
7019
7020         attrs[0] = attr->lDAPDisplayName;
7021         attrs[1] = "isDeleted";
7022         attrs[2] = "isRecycled";
7023         attrs[3] = NULL;
7024
7025         /*
7026          * get the existing message from the db for the object with
7027          * this GUID, returning attribute being modified. We will then
7028          * use this msg as the basis for a modify call
7029          */
7030         ret = dsdb_module_search(module, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
7031                                  DSDB_FLAG_NEXT_MODULE |
7032                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
7033                                  DSDB_SEARCH_SHOW_RECYCLED |
7034                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
7035                                  DSDB_SEARCH_REVEAL_INTERNALS,
7036                                  NULL,
7037                                  "objectGUID=%s", GUID_string(mem_ctx, &la->identifier->guid));
7038         if (ret != LDB_SUCCESS) {
7039                 return ret;
7040         }
7041         if (res->count != 1) {
7042                 ldb_asprintf_errstring(ldb, "DRS linked attribute for GUID %s - DN not found",
7043                                        GUID_string(mem_ctx, &la->identifier->guid));
7044                 return LDB_ERR_NO_SUCH_OBJECT;
7045         }
7046
7047         *source_msg = res->msgs[0];
7048
7049         /* the value blob for the attribute holds the target object DN */
7050         status = dsdb_dn_la_from_blob(ldb, attr, schema, mem_ctx, la->value.blob, target_dsdb_dn);
7051         if (!W_ERROR_IS_OK(status)) {
7052                 ldb_asprintf_errstring(ldb, "Failed to parsed linked attribute blob for %s on %s - %s\n",
7053                                        attr->lDAPDisplayName,
7054                                        ldb_dn_get_linearized(res->msgs[0]->dn),
7055                                        win_errstr(status));
7056                 return LDB_ERR_OPERATIONS_ERROR;
7057         }
7058
7059         *ret_attr = attr;
7060
7061         return LDB_SUCCESS;
7062 }
7063
7064 /**
7065  * Verifies the source and target objects are known for a linked attribute
7066  */
7067 static int replmd_verify_linked_attribute(struct replmd_replicated_request *ar,
7068                                           struct la_entry *la)
7069 {
7070         int ret = LDB_SUCCESS;
7071         TALLOC_CTX *tmp_ctx = talloc_new(la);
7072         struct ldb_module *module = ar->module;
7073         struct ldb_message *src_msg;
7074         const struct dsdb_attribute *attr;
7075         struct dsdb_dn *tgt_dsdb_dn;
7076         struct GUID guid = GUID_zero();
7077         bool dummy;
7078
7079         ret = replmd_extract_la_entry_details(module, la, tmp_ctx, &attr,
7080                                               &src_msg, &tgt_dsdb_dn);
7081
7082         /*
7083          * When we fail to find the source object, the error code we pass
7084          * back here is really important. It flags back to the callers to
7085          * retry this request with DRSUAPI_DRS_GET_ANC. This case should
7086          * never happen if we're replicating from a Samba DC, but it is
7087          * needed to talk to a Windows DC
7088          */
7089         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
7090                 ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_MISSING_PARENT);
7091         }
7092
7093         if (ret != LDB_SUCCESS) {
7094                 talloc_free(tmp_ctx);
7095                 return ret;
7096         }
7097
7098         /*
7099          * We can skip the target object checks if we're only syncing critical
7100          * objects, or we know the target is up-to-date. If either case, we
7101          * still continue even if the target doesn't exist
7102          */
7103         if ((la->dsdb_repl_flags & (DSDB_REPL_FLAG_OBJECT_SUBSET |
7104                                     DSDB_REPL_FLAG_TARGETS_UPTODATE)) == 0) {
7105
7106                 ret = replmd_check_target_exists(module, tgt_dsdb_dn, la,
7107                                                  src_msg->dn, false, &guid,
7108                                                  &dummy);
7109         }
7110
7111         /*
7112          * When we fail to find the target object, the error code we pass
7113          * back here is really important. It flags back to the callers to
7114          * retry this request with DRSUAPI_DRS_GET_TGT
7115          */
7116         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
7117                 ret = replmd_replicated_request_werror(ar, WERR_DS_DRA_RECYCLED_TARGET);
7118         }
7119
7120         talloc_free(tmp_ctx);
7121         return ret;
7122 }
7123
7124 /*
7125   process one linked attribute structure
7126  */
7127 static int replmd_process_linked_attribute(struct ldb_module *module,
7128                                            struct replmd_private *replmd_private,
7129                                            struct la_entry *la_entry,
7130                                            struct ldb_request *parent)
7131 {
7132         struct drsuapi_DsReplicaLinkedAttribute *la = la_entry->la;
7133         struct ldb_context *ldb = ldb_module_get_ctx(module);
7134         struct ldb_message *msg;
7135         TALLOC_CTX *tmp_ctx = talloc_new(la_entry);
7136         const struct dsdb_schema *schema = dsdb_get_schema(ldb, tmp_ctx);
7137         int ret;
7138         const struct dsdb_attribute *attr;
7139         struct dsdb_dn *dsdb_dn;
7140         uint64_t seq_num = 0;
7141         struct ldb_message_element *old_el;
7142         time_t t = time(NULL);
7143         struct parsed_dn *pdn_list, *pdn, *next;
7144         struct GUID guid = GUID_zero();
7145         bool active = (la->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)?true:false;
7146         bool ignore_link;
7147         enum deletion_state deletion_state = OBJECT_NOT_DELETED;
7148
7149         /*
7150          * get the attribute being modified, the search result for the source object,
7151          * and the target object's DN details
7152          */
7153         ret = replmd_extract_la_entry_details(module, la_entry, tmp_ctx, &attr,
7154                                               &msg, &dsdb_dn);
7155
7156         if (ret != LDB_SUCCESS) {
7157                 talloc_free(tmp_ctx);
7158                 return ret;
7159         }
7160
7161         /*
7162          * Check for deleted objects per MS-DRSR 4.1.10.6.14
7163          * ProcessLinkValue, because link updates are not applied to
7164          * recycled and tombstone objects.  We don't have to delete
7165          * any existing link, that should have happened when the
7166          * object deletion was replicated or initiated.
7167          */
7168         replmd_deletion_state(module, msg, &deletion_state, NULL);
7169
7170         if (deletion_state >= OBJECT_RECYCLED) {
7171                 talloc_free(tmp_ctx);
7172                 return LDB_SUCCESS;
7173         }
7174
7175         old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName);
7176         if (old_el == NULL) {
7177                 ret = ldb_msg_add_empty(msg, attr->lDAPDisplayName, LDB_FLAG_MOD_REPLACE, &old_el);
7178                 if (ret != LDB_SUCCESS) {
7179                         ldb_module_oom(module);
7180                         talloc_free(tmp_ctx);
7181                         return LDB_ERR_OPERATIONS_ERROR;
7182                 }
7183         } else {
7184                 old_el->flags = LDB_FLAG_MOD_REPLACE;
7185         }
7186
7187         /* parse the existing links */
7188         ret = get_parsed_dns_trusted(module, replmd_private, tmp_ctx, old_el, &pdn_list,
7189                                      attr->syntax->ldap_oid, parent);
7190
7191         if (ret != LDB_SUCCESS) {
7192                 talloc_free(tmp_ctx);
7193                 return ret;
7194         }
7195
7196         ret = replmd_check_target_exists(module, dsdb_dn, la_entry, msg->dn,
7197                                          true, &guid, &ignore_link);
7198
7199         if (ret != LDB_SUCCESS) {
7200                 talloc_free(tmp_ctx);
7201                 return ret;
7202         }
7203
7204         /*
7205          * there are some cases where the target object doesn't exist, but it's
7206          * OK to ignore the linked attribute
7207          */
7208         if (ignore_link) {
7209                 talloc_free(tmp_ctx);
7210                 return ret;
7211         }
7212
7213         /* see if this link already exists */
7214         ret = parsed_dn_find(ldb, pdn_list, old_el->num_values,
7215                              &guid,
7216                              dsdb_dn->dn,
7217                              dsdb_dn->extra_part, 0,
7218                              &pdn, &next,
7219                              attr->syntax->ldap_oid,
7220                              true);
7221         if (ret != LDB_SUCCESS) {
7222                 talloc_free(tmp_ctx);
7223                 return ret;
7224         }
7225
7226
7227         if (pdn != NULL) {
7228                 /* see if this update is newer than what we have already */
7229                 struct GUID invocation_id = GUID_zero();
7230                 uint32_t version = 0;
7231                 uint32_t originating_usn = 0;
7232                 NTTIME change_time = 0;
7233                 uint32_t rmd_flags = dsdb_dn_rmd_flags(pdn->dsdb_dn->dn);
7234
7235                 dsdb_get_extended_dn_guid(pdn->dsdb_dn->dn, &invocation_id, "RMD_INVOCID");
7236                 dsdb_get_extended_dn_uint32(pdn->dsdb_dn->dn, &version, "RMD_VERSION");
7237                 dsdb_get_extended_dn_uint32(pdn->dsdb_dn->dn, &originating_usn, "RMD_ORIGINATING_USN");
7238                 dsdb_get_extended_dn_nttime(pdn->dsdb_dn->dn, &change_time, "RMD_CHANGETIME");
7239
7240                 if (!replmd_update_is_newer(&invocation_id,
7241                                             &la->meta_data.originating_invocation_id,
7242                                             version,
7243                                             la->meta_data.version,
7244                                             change_time,
7245                                             la->meta_data.originating_change_time)) {
7246                         DEBUG(3,("Discarding older DRS linked attribute update to %s on %s from %s\n",
7247                                  old_el->name, ldb_dn_get_linearized(msg->dn),
7248                                  GUID_string(tmp_ctx, &la->meta_data.originating_invocation_id)));
7249                         talloc_free(tmp_ctx);
7250                         return LDB_SUCCESS;
7251                 }
7252
7253                 /* get a seq_num for this change */
7254                 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
7255                 if (ret != LDB_SUCCESS) {
7256                         talloc_free(tmp_ctx);
7257                         return ret;
7258                 }
7259
7260                 if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
7261                         /* remove the existing backlink */
7262                         ret = replmd_add_backlink(module, replmd_private,
7263                                                   schema, 
7264                                                   msg->dn,
7265                                                   &guid, false, attr,
7266                                                   parent);
7267                         if (ret != LDB_SUCCESS) {
7268                                 talloc_free(tmp_ctx);
7269                                 return ret;
7270                         }
7271                 }
7272
7273                 ret = replmd_update_la_val(tmp_ctx, pdn->v, dsdb_dn, pdn->dsdb_dn,
7274                                            &la->meta_data.originating_invocation_id,
7275                                            la->meta_data.originating_usn, seq_num,
7276                                            la->meta_data.originating_change_time,
7277                                            la->meta_data.version,
7278                                            !active);
7279                 if (ret != LDB_SUCCESS) {
7280                         talloc_free(tmp_ctx);
7281                         return ret;
7282                 }
7283
7284                 if (active) {
7285                         /* add the new backlink */
7286                         ret = replmd_add_backlink(module, replmd_private,
7287                                                   schema, 
7288                                                   msg->dn,
7289                                                   &guid, true, attr,
7290                                                   parent);
7291                         if (ret != LDB_SUCCESS) {
7292                                 talloc_free(tmp_ctx);
7293                                 return ret;
7294                         }
7295                 }
7296         } else {
7297                 unsigned offset;
7298                 /* get a seq_num for this change */
7299                 ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &seq_num);
7300                 if (ret != LDB_SUCCESS) {
7301                         talloc_free(tmp_ctx);
7302                         return ret;
7303                 }
7304                 /*
7305                  * We know where the new one needs to be, from the *next
7306                  * pointer into pdn_list.
7307                  */
7308                 if (next == NULL) {
7309                         offset = old_el->num_values;
7310                 } else {
7311                         if (next->dsdb_dn == NULL) {
7312                                 ret = really_parse_trusted_dn(tmp_ctx, ldb, next,
7313                                                               attr->syntax->ldap_oid);
7314                                 if (ret != LDB_SUCCESS) {
7315                                         return ret;
7316                                 }
7317                         }
7318                         offset = next - pdn_list;
7319                         if (offset > old_el->num_values) {
7320                                 talloc_free(tmp_ctx);
7321                                 return LDB_ERR_OPERATIONS_ERROR;
7322                         }
7323                 }
7324
7325                 old_el->values = talloc_realloc(msg->elements, old_el->values,
7326                                                 struct ldb_val, old_el->num_values+1);
7327                 if (!old_el->values) {
7328                         ldb_module_oom(module);
7329                         return LDB_ERR_OPERATIONS_ERROR;
7330                 }
7331
7332                 if (offset != old_el->num_values) {
7333                         memmove(&old_el->values[offset + 1], &old_el->values[offset],
7334                                 (old_el->num_values - offset) * sizeof(old_el->values[0]));
7335                 }
7336
7337                 old_el->num_values++;
7338
7339                 ret = replmd_build_la_val(tmp_ctx, &old_el->values[offset], dsdb_dn,
7340                                           &la->meta_data.originating_invocation_id,
7341                                           la->meta_data.originating_usn, seq_num,
7342                                           la->meta_data.originating_change_time,
7343                                           la->meta_data.version,
7344                                           !active);
7345                 if (ret != LDB_SUCCESS) {
7346                         talloc_free(tmp_ctx);
7347                         return ret;
7348                 }
7349
7350                 if (active) {
7351                         ret = replmd_add_backlink(module, replmd_private,
7352                                                   schema, 
7353                                                   msg->dn,
7354                                                   &guid, true, attr,
7355                                                   parent);
7356                         if (ret != LDB_SUCCESS) {
7357                                 talloc_free(tmp_ctx);
7358                                 return ret;
7359                         }
7360                 }
7361         }
7362
7363         /* we only change whenChanged and uSNChanged if the seq_num
7364            has changed */
7365         ret = add_time_element(msg, "whenChanged", t);
7366         if (ret != LDB_SUCCESS) {
7367                 talloc_free(tmp_ctx);
7368                 ldb_operr(ldb);
7369                 return ret;
7370         }
7371
7372         ret = add_uint64_element(ldb, msg, "uSNChanged", seq_num);
7373         if (ret != LDB_SUCCESS) {
7374                 talloc_free(tmp_ctx);
7375                 ldb_operr(ldb);
7376                 return ret;
7377         }
7378
7379         old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName);
7380         if (old_el == NULL) {
7381                 talloc_free(tmp_ctx);
7382                 return ldb_operr(ldb);
7383         }
7384
7385         ret = dsdb_check_single_valued_link(attr, old_el);
7386         if (ret != LDB_SUCCESS) {
7387                 talloc_free(tmp_ctx);
7388                 return ret;
7389         }
7390
7391         old_el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
7392
7393         ret = linked_attr_modify(module, msg, parent);
7394         if (ret != LDB_SUCCESS) {
7395                 ldb_debug(ldb, LDB_DEBUG_WARNING, "Failed to apply linked attribute change '%s'\n%s\n",
7396                           ldb_errstring(ldb),
7397                           ldb_ldif_message_redacted_string(ldb,
7398                                                            tmp_ctx,
7399                                                            LDB_CHANGETYPE_MODIFY,
7400                                                            msg));
7401                 talloc_free(tmp_ctx);
7402                 return ret;
7403         }
7404
7405         talloc_free(tmp_ctx);
7406
7407         return ret;
7408 }
7409
7410 static int replmd_extended(struct ldb_module *module, struct ldb_request *req)
7411 {
7412         if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) {
7413                 return replmd_extended_replicated_objects(module, req);
7414         }
7415
7416         return ldb_next_request(module, req);
7417 }
7418
7419
7420 /*
7421   we hook into the transaction operations to allow us to
7422   perform the linked attribute updates at the end of the whole
7423   transaction. This allows a forward linked attribute to be created
7424   before the object is created. During a vampire, w2k8 sends us linked
7425   attributes before the objects they are part of.
7426  */
7427 static int replmd_start_transaction(struct ldb_module *module)
7428 {
7429         /* create our private structure for this transaction */
7430         struct replmd_private *replmd_private = talloc_get_type(ldb_module_get_private(module),
7431                                                                 struct replmd_private);
7432         replmd_txn_cleanup(replmd_private);
7433
7434         /* free any leftover mod_usn records from cancelled
7435            transactions */
7436         while (replmd_private->ncs) {
7437                 struct nc_entry *e = replmd_private->ncs;
7438                 DLIST_REMOVE(replmd_private->ncs, e);
7439                 talloc_free(e);
7440         }
7441
7442         replmd_private->originating_updates = false;
7443
7444         return ldb_next_start_trans(module);
7445 }
7446
7447 /*
7448   on prepare commit we loop over our queued la_context structures and
7449   apply each of them
7450  */
7451 static int replmd_prepare_commit(struct ldb_module *module)
7452 {
7453         struct replmd_private *replmd_private =
7454                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
7455         struct la_entry *la, *prev;
7456         int ret;
7457
7458         /*
7459          * Walk the list of linked attributes from DRS replication.
7460          *
7461          * We walk backwards, to do the first entry first, as we
7462          * added the entries with DLIST_ADD() which puts them at the
7463          * start of the list
7464          */
7465         for (la = DLIST_TAIL(replmd_private->la_list); la; la=prev) {
7466                 prev = DLIST_PREV(la);
7467                 DLIST_REMOVE(replmd_private->la_list, la);
7468                 ret = replmd_process_linked_attribute(module, replmd_private,
7469                                                       la, NULL);
7470                 if (ret != LDB_SUCCESS) {
7471                         replmd_txn_cleanup(replmd_private);
7472                         return ret;
7473                 }
7474         }
7475
7476         replmd_txn_cleanup(replmd_private);
7477
7478         /* possibly change @REPLCHANGED */
7479         ret = replmd_notify_store(module, NULL);
7480         if (ret != LDB_SUCCESS) {
7481                 return ret;
7482         }
7483
7484         return ldb_next_prepare_commit(module);
7485 }
7486
7487 static int replmd_del_transaction(struct ldb_module *module)
7488 {
7489         struct replmd_private *replmd_private =
7490                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
7491         replmd_txn_cleanup(replmd_private);
7492
7493         return ldb_next_del_trans(module);
7494 }
7495
7496
7497 static const struct ldb_module_ops ldb_repl_meta_data_module_ops = {
7498         .name          = "repl_meta_data",
7499         .init_context      = replmd_init,
7500         .add               = replmd_add,
7501         .modify            = replmd_modify,
7502         .rename            = replmd_rename,
7503         .del               = replmd_delete,
7504         .extended          = replmd_extended,
7505         .start_transaction = replmd_start_transaction,
7506         .prepare_commit    = replmd_prepare_commit,
7507         .del_transaction   = replmd_del_transaction,
7508 };
7509
7510 int ldb_repl_meta_data_module_init(const char *version)
7511 {
7512         LDB_MODULE_CHECK_VERSION(version);
7513         return ldb_register_module(&ldb_repl_meta_data_module_ops);
7514 }