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