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