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