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