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