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