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