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