3e4880e131c2391a0b11a11304cfa622c4f0ec27
[abartlet/samba.git/.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
84         /* the controls we pass down */
85         struct ldb_control **controls;
86
87         /* details for the mode where we apply a bunch of inbound replication meessages */
88         bool apply_mode;
89         uint32_t index_current;
90         struct dsdb_extended_replicated_objects *objs;
91
92         struct ldb_message *search_msg;
93
94         uint64_t seq_num;
95         bool is_urgent;
96
97         bool isDeleted;
98 };
99
100 static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar);
101 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete);
102
103 enum urgent_situation {
104         REPL_URGENT_ON_CREATE = 1,
105         REPL_URGENT_ON_UPDATE = 2,
106         REPL_URGENT_ON_DELETE = 4
107 };
108
109 enum deletion_state {
110         OBJECT_NOT_DELETED=1,
111         OBJECT_DELETED=2,
112         OBJECT_RECYCLED=3,
113         OBJECT_TOMBSTONE=4,
114         OBJECT_REMOVED=5
115 };
116
117 static void replmd_deletion_state(struct ldb_module *module,
118                                   const struct ldb_message *msg,
119                                   enum deletion_state *current_state,
120                                   enum deletion_state *next_state)
121 {
122         int ret;
123         bool enabled = false;
124
125         if (msg == NULL) {
126                 *current_state = OBJECT_REMOVED;
127                 if (next_state != NULL) {
128                         *next_state = OBJECT_REMOVED;
129                 }
130                 return;
131         }
132
133         ret = dsdb_recyclebin_enabled(module, &enabled);
134         if (ret != LDB_SUCCESS) {
135                 enabled = false;
136         }
137
138         if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
139                 if (!enabled) {
140                         *current_state = OBJECT_TOMBSTONE;
141                         if (next_state != NULL) {
142                                 *next_state = OBJECT_REMOVED;
143                         }
144                         return;
145                 }
146
147                 if (ldb_msg_check_string_attribute(msg, "isRecycled", "TRUE")) {
148                         *current_state = OBJECT_RECYCLED;
149                         if (next_state != NULL) {
150                                 *next_state = OBJECT_REMOVED;
151                         }
152                         return;
153                 }
154
155                 *current_state = OBJECT_DELETED;
156                 if (next_state != NULL) {
157                         *next_state = OBJECT_RECYCLED;
158                 }
159                 return;
160         }
161
162         *current_state = OBJECT_NOT_DELETED;
163         if (next_state == NULL) {
164                 return;
165         }
166
167         if (enabled) {
168                 *next_state = OBJECT_DELETED;
169         } else {
170                 *next_state = OBJECT_TOMBSTONE;
171         }
172 }
173
174 static const struct {
175         const char *update_name;
176         enum urgent_situation repl_situation;
177 } urgent_objects[] = {
178                 {"nTDSDSA", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE)},
179                 {"crossRef", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE)},
180                 {"attributeSchema", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
181                 {"classSchema", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
182                 {"secret", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
183                 {"rIDManager", (REPL_URGENT_ON_CREATE | REPL_URGENT_ON_UPDATE)},
184                 {NULL, 0}
185 };
186
187 /* Attributes looked for when updating or deleting, to check for a urgent replication needed */
188 static const char *urgent_attrs[] = {
189                 "lockoutTime",
190                 "pwdLastSet",
191                 "userAccountControl",
192                 NULL
193 };
194
195
196 static bool replmd_check_urgent_objectclass(const struct ldb_message_element *objectclass_el,
197                                         enum urgent_situation situation)
198 {
199         unsigned int i, j;
200         for (i=0; urgent_objects[i].update_name; i++) {
201
202                 if ((situation & urgent_objects[i].repl_situation) == 0) {
203                         continue;
204                 }
205
206                 for (j=0; j<objectclass_el->num_values; j++) {
207                         const struct ldb_val *v = &objectclass_el->values[j];
208                         if (ldb_attr_cmp((const char *)v->data, urgent_objects[i].update_name) == 0) {
209                                 return true;
210                         }
211                 }
212         }
213         return false;
214 }
215
216 static bool replmd_check_urgent_attribute(const struct ldb_message_element *el)
217 {
218         if (ldb_attr_in_list(urgent_attrs, el->name)) {
219                 return true;
220         }
221         return false;
222 }
223
224
225 static int replmd_replicated_apply_isDeleted(struct replmd_replicated_request *ar);
226
227 /*
228   initialise the module
229   allocate the private structure and build the list
230   of partition DNs for use by replmd_notify()
231  */
232 static int replmd_init(struct ldb_module *module)
233 {
234         struct replmd_private *replmd_private;
235         struct ldb_context *ldb = ldb_module_get_ctx(module);
236
237         replmd_private = talloc_zero(module, struct replmd_private);
238         if (replmd_private == NULL) {
239                 ldb_oom(ldb);
240                 return LDB_ERR_OPERATIONS_ERROR;
241         }
242         ldb_module_set_private(module, replmd_private);
243
244         replmd_private->schema_dn = ldb_get_schema_basedn(ldb);
245
246         return ldb_next_init(module);
247 }
248
249 /*
250   cleanup our per-transaction contexts
251  */
252 static void replmd_txn_cleanup(struct replmd_private *replmd_private)
253 {
254         talloc_free(replmd_private->la_ctx);
255         replmd_private->la_list = NULL;
256         replmd_private->la_ctx = NULL;
257
258         talloc_free(replmd_private->bl_ctx);
259         replmd_private->la_backlinks = NULL;
260         replmd_private->bl_ctx = NULL;
261 }
262
263
264 struct la_backlink {
265         struct la_backlink *next, *prev;
266         const char *attr_name;
267         struct GUID forward_guid, target_guid;
268         bool active;
269 };
270
271 /*
272   process a backlinks we accumulated during a transaction, adding and
273   deleting the backlinks from the target objects
274  */
275 static int replmd_process_backlink(struct ldb_module *module, struct la_backlink *bl, struct ldb_request *parent)
276 {
277         struct ldb_dn *target_dn, *source_dn;
278         int ret;
279         struct ldb_context *ldb = ldb_module_get_ctx(module);
280         struct ldb_message *msg;
281         TALLOC_CTX *tmp_ctx = talloc_new(bl);
282         char *dn_string;
283
284         /*
285           - find DN of target
286           - find DN of source
287           - construct ldb_message
288               - either an add or a delete
289          */
290         ret = dsdb_module_dn_by_guid(module, tmp_ctx, &bl->target_guid, &target_dn, parent);
291         if (ret != LDB_SUCCESS) {
292                 DEBUG(2,(__location__ ": WARNING: Failed to find target DN for linked attribute with GUID %s\n",
293                          GUID_string(bl, &bl->target_guid)));
294                 return LDB_SUCCESS;
295         }
296
297         ret = dsdb_module_dn_by_guid(module, tmp_ctx, &bl->forward_guid, &source_dn, parent);
298         if (ret != LDB_SUCCESS) {
299                 ldb_asprintf_errstring(ldb, "Failed to find source DN for linked attribute with GUID %s\n",
300                                        GUID_string(bl, &bl->forward_guid));
301                 talloc_free(tmp_ctx);
302                 return ret;
303         }
304
305         msg = ldb_msg_new(tmp_ctx);
306         if (msg == NULL) {
307                 ldb_module_oom(module);
308                 talloc_free(tmp_ctx);
309                 return LDB_ERR_OPERATIONS_ERROR;
310         }
311
312         /* construct a ldb_message for adding/deleting the backlink */
313         msg->dn = target_dn;
314         dn_string = ldb_dn_get_extended_linearized(tmp_ctx, source_dn, 1);
315         if (!dn_string) {
316                 ldb_module_oom(module);
317                 talloc_free(tmp_ctx);
318                 return LDB_ERR_OPERATIONS_ERROR;
319         }
320         ret = ldb_msg_add_steal_string(msg, bl->attr_name, dn_string);
321         if (ret != LDB_SUCCESS) {
322                 talloc_free(tmp_ctx);
323                 return ret;
324         }
325         msg->elements[0].flags = bl->active?LDB_FLAG_MOD_ADD:LDB_FLAG_MOD_DELETE;
326
327         /* a backlink should never be single valued. Unfortunately the
328            exchange schema has a attribute
329            msExchBridgeheadedLocalConnectorsDNBL which is single
330            valued and a backlink. We need to cope with that by
331            ignoring the single value flag */
332         msg->elements[0].flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
333
334         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
335         if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && !bl->active) {
336                 /* we allow LDB_ERR_NO_SUCH_ATTRIBUTE as success to
337                    cope with possible corruption where the backlink has
338                    already been removed */
339                 DEBUG(3,("WARNING: backlink from %s already removed from %s - %s\n",
340                          ldb_dn_get_linearized(target_dn),
341                          ldb_dn_get_linearized(source_dn),
342                          ldb_errstring(ldb)));
343                 ret = LDB_SUCCESS;
344         } else if (ret != LDB_SUCCESS) {
345                 ldb_asprintf_errstring(ldb, "Failed to %s backlink from %s to %s - %s",
346                                        bl->active?"add":"remove",
347                                        ldb_dn_get_linearized(source_dn),
348                                        ldb_dn_get_linearized(target_dn),
349                                        ldb_errstring(ldb));
350                 talloc_free(tmp_ctx);
351                 return ret;
352         }
353         talloc_free(tmp_ctx);
354         return ret;
355 }
356
357 /*
358   add a backlink to the list of backlinks to add/delete in the prepare
359   commit
360  */
361 static int replmd_add_backlink(struct ldb_module *module, const struct dsdb_schema *schema,
362                                struct GUID *forward_guid, struct GUID *target_guid,
363                                bool active, const struct dsdb_attribute *schema_attr, bool immediate)
364 {
365         const struct dsdb_attribute *target_attr;
366         struct la_backlink *bl;
367         struct replmd_private *replmd_private =
368                 talloc_get_type_abort(ldb_module_get_private(module), struct replmd_private);
369
370         target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1);
371         if (!target_attr) {
372                 /*
373                  * windows 2003 has a broken schema where the
374                  * definition of msDS-IsDomainFor is missing (which is
375                  * supposed to be the backlink of the
376                  * msDS-HasDomainNCs attribute
377                  */
378                 return LDB_SUCCESS;
379         }
380
381         /* see if its already in the list */
382         for (bl=replmd_private->la_backlinks; bl; bl=bl->next) {
383                 if (GUID_equal(forward_guid, &bl->forward_guid) &&
384                     GUID_equal(target_guid, &bl->target_guid) &&
385                     (target_attr->lDAPDisplayName == bl->attr_name ||
386                      strcmp(target_attr->lDAPDisplayName, bl->attr_name) == 0)) {
387                         break;
388                 }
389         }
390
391         if (bl) {
392                 /* we found an existing one */
393                 if (bl->active == active) {
394                         return LDB_SUCCESS;
395                 }
396                 DLIST_REMOVE(replmd_private->la_backlinks, bl);
397                 talloc_free(bl);
398                 return LDB_SUCCESS;
399         }
400
401         if (replmd_private->bl_ctx == NULL) {
402                 replmd_private->bl_ctx = talloc_new(replmd_private);
403                 if (replmd_private->bl_ctx == NULL) {
404                         ldb_module_oom(module);
405                         return LDB_ERR_OPERATIONS_ERROR;
406                 }
407         }
408
409         /* its a new one */
410         bl = talloc(replmd_private->bl_ctx, struct la_backlink);
411         if (bl == NULL) {
412                 ldb_module_oom(module);
413                 return LDB_ERR_OPERATIONS_ERROR;
414         }
415
416         /* Ensure the schema does not go away before the bl->attr_name is used */
417         if (!talloc_reference(bl, schema)) {
418                 talloc_free(bl);
419                 ldb_module_oom(module);
420                 return LDB_ERR_OPERATIONS_ERROR;
421         }
422
423         bl->attr_name = target_attr->lDAPDisplayName;
424         bl->forward_guid = *forward_guid;
425         bl->target_guid = *target_guid;
426         bl->active = active;
427
428         /* the caller may ask for this backlink to be processed
429            immediately */
430         if (immediate) {
431                 int ret = replmd_process_backlink(module, bl, NULL);
432                 talloc_free(bl);
433                 return ret;
434         }
435
436         DLIST_ADD(replmd_private->la_backlinks, bl);
437
438         return LDB_SUCCESS;
439 }
440
441
442 /*
443  * Callback for most write operations in this module:
444  *
445  * notify the repl task that a object has changed. The notifies are
446  * gathered up in the replmd_private structure then written to the
447  * @REPLCHANGED object in each partition during the prepare_commit
448  */
449 static int replmd_op_callback(struct ldb_request *req, struct ldb_reply *ares)
450 {
451         int ret;
452         struct replmd_replicated_request *ac =
453                 talloc_get_type_abort(req->context, struct replmd_replicated_request);
454         struct replmd_private *replmd_private =
455                 talloc_get_type_abort(ldb_module_get_private(ac->module), struct replmd_private);
456         struct nc_entry *modified_partition;
457         struct ldb_control *partition_ctrl;
458         const struct dsdb_control_current_partition *partition;
459
460         struct ldb_control **controls;
461
462         partition_ctrl = ldb_reply_get_control(ares, DSDB_CONTROL_CURRENT_PARTITION_OID);
463
464         controls = ares->controls;
465         if (ldb_request_get_control(ac->req,
466                                     DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
467                 /*
468                  * Remove the current partition control from what we pass up
469                  * the chain if it hasn't been requested manually.
470                  */
471                 controls = ldb_controls_except_specified(ares->controls, ares,
472                                                          partition_ctrl);
473         }
474
475         if (ares->error != LDB_SUCCESS) {
476                 DEBUG(5,("%s failure. Error is: %s\n", __FUNCTION__, ldb_strerror(ares->error)));
477                 return ldb_module_done(ac->req, controls,
478                                         ares->response, ares->error);
479         }
480
481         if (ares->type != LDB_REPLY_DONE) {
482                 ldb_set_errstring(ldb_module_get_ctx(ac->module), "Invalid reply type for notify\n!");
483                 return ldb_module_done(ac->req, NULL,
484                                        NULL, LDB_ERR_OPERATIONS_ERROR);
485         }
486
487         if (!partition_ctrl) {
488                 ldb_set_errstring(ldb_module_get_ctx(ac->module),"No partition control on reply");
489                 return ldb_module_done(ac->req, NULL,
490                                        NULL, LDB_ERR_OPERATIONS_ERROR);
491         }
492
493         partition = talloc_get_type_abort(partition_ctrl->data,
494                                     struct dsdb_control_current_partition);
495
496         if (ac->seq_num > 0) {
497                 for (modified_partition = replmd_private->ncs; modified_partition;
498                      modified_partition = modified_partition->next) {
499                         if (ldb_dn_compare(modified_partition->dn, partition->dn) == 0) {
500                                 break;
501                         }
502                 }
503
504                 if (modified_partition == NULL) {
505                         modified_partition = talloc_zero(replmd_private, struct nc_entry);
506                         if (!modified_partition) {
507                                 ldb_oom(ldb_module_get_ctx(ac->module));
508                                 return ldb_module_done(ac->req, NULL,
509                                                        NULL, LDB_ERR_OPERATIONS_ERROR);
510                         }
511                         modified_partition->dn = ldb_dn_copy(modified_partition, partition->dn);
512                         if (!modified_partition->dn) {
513                                 ldb_oom(ldb_module_get_ctx(ac->module));
514                                 return ldb_module_done(ac->req, NULL,
515                                                        NULL, LDB_ERR_OPERATIONS_ERROR);
516                         }
517                         DLIST_ADD(replmd_private->ncs, modified_partition);
518                 }
519
520                 if (ac->seq_num > modified_partition->mod_usn) {
521                         modified_partition->mod_usn = ac->seq_num;
522                         if (ac->is_urgent) {
523                                 modified_partition->mod_usn_urgent = ac->seq_num;
524                         }
525                 }
526         }
527
528         if (ac->apply_mode) {
529                 ret = replmd_replicated_apply_isDeleted(ac);
530                 if (ret != LDB_SUCCESS) {
531                         return ldb_module_done(ac->req, NULL, NULL, ret);
532                 }
533                 return ret;
534         } else {
535                 /* free the partition control container here, for the
536                  * common path.  Other cases will have it cleaned up
537                  * eventually with the ares */
538                 talloc_free(partition_ctrl);
539                 return ldb_module_done(ac->req, controls,
540                                        ares->response, LDB_SUCCESS);
541         }
542 }
543
544
545 /*
546  * update a @REPLCHANGED record in each partition if there have been
547  * any writes of replicated data in the partition
548  */
549 static int replmd_notify_store(struct ldb_module *module, struct ldb_request *parent)
550 {
551         struct replmd_private *replmd_private =
552                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
553
554         while (replmd_private->ncs) {
555                 int ret;
556                 struct nc_entry *modified_partition = replmd_private->ncs;
557
558                 ret = dsdb_module_save_partition_usn(module, modified_partition->dn,
559                                                      modified_partition->mod_usn,
560                                                      modified_partition->mod_usn_urgent, parent);
561                 if (ret != LDB_SUCCESS) {
562                         DEBUG(0,(__location__ ": Failed to save partition uSN for %s\n",
563                                  ldb_dn_get_linearized(modified_partition->dn)));
564                         return ret;
565                 }
566                 DLIST_REMOVE(replmd_private->ncs, modified_partition);
567                 talloc_free(modified_partition);
568         }
569
570         return LDB_SUCCESS;
571 }
572
573
574 /*
575   created a replmd_replicated_request context
576  */
577 static struct replmd_replicated_request *replmd_ctx_init(struct ldb_module *module,
578                                                          struct ldb_request *req)
579 {
580         struct ldb_context *ldb;
581         struct replmd_replicated_request *ac;
582
583         ldb = ldb_module_get_ctx(module);
584
585         ac = talloc_zero(req, struct replmd_replicated_request);
586         if (ac == NULL) {
587                 ldb_oom(ldb);
588                 return NULL;
589         }
590
591         ac->module = module;
592         ac->req = req;
593
594         ac->schema = dsdb_get_schema(ldb, ac);
595         if (!ac->schema) {
596                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
597                               "replmd_modify: no dsdb_schema loaded");
598                 DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
599                 return NULL;
600         }
601
602         return ac;
603 }
604
605 /*
606   add a time element to a record
607 */
608 static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
609 {
610         struct ldb_message_element *el;
611         char *s;
612         int ret;
613
614         if (ldb_msg_find_element(msg, attr) != NULL) {
615                 return LDB_SUCCESS;
616         }
617
618         s = ldb_timestring(msg, t);
619         if (s == NULL) {
620                 return LDB_ERR_OPERATIONS_ERROR;
621         }
622
623         ret = ldb_msg_add_string(msg, attr, s);
624         if (ret != LDB_SUCCESS) {
625                 return ret;
626         }
627
628         el = ldb_msg_find_element(msg, attr);
629         /* always set as replace. This works because on add ops, the flag
630            is ignored */
631         el->flags = LDB_FLAG_MOD_REPLACE;
632
633         return LDB_SUCCESS;
634 }
635
636 /*
637   add a uint64_t element to a record
638 */
639 static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg,
640                               const char *attr, uint64_t v)
641 {
642         struct ldb_message_element *el;
643         int ret;
644
645         if (ldb_msg_find_element(msg, attr) != NULL) {
646                 return LDB_SUCCESS;
647         }
648
649         ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v);
650         if (ret != LDB_SUCCESS) {
651                 return ret;
652         }
653
654         el = ldb_msg_find_element(msg, attr);
655         /* always set as replace. This works because on add ops, the flag
656            is ignored */
657         el->flags = LDB_FLAG_MOD_REPLACE;
658
659         return LDB_SUCCESS;
660 }
661
662 static int replmd_replPropertyMetaData1_attid_sort(const struct replPropertyMetaData1 *m1,
663                                                    const struct replPropertyMetaData1 *m2,
664                                                    const uint32_t *rdn_attid)
665 {
666         /*
667          * This assignment seems inoccous, but it is critical for the
668          * system, as we need to do the comparisons as a unsigned
669          * quantity, not signed (enums are signed integers)
670          */
671         uint32_t attid_1 = m1->attid;
672         uint32_t attid_2 = m2->attid;
673
674         if (attid_1 == attid_2) {
675                 return 0;
676         }
677
678         /*
679          * the rdn attribute should be at the end!
680          * so we need to return a value greater than zero
681          * which means m1 is greater than m2
682          */
683         if (attid_1 == *rdn_attid) {
684                 return 1;
685         }
686
687         /*
688          * the rdn attribute should be at the end!
689          * so we need to return a value less than zero
690          * which means m2 is greater than m1
691          */
692         if (attid_2 == *rdn_attid) {
693                 return -1;
694         }
695
696         /*
697          * See above regarding this being an unsigned comparison.
698          * Otherwise when the high bit is set on non-standard
699          * attributes, they would end up first, before objectClass
700          * (0).
701          */
702         return attid_1 > attid_2 ? 1 : -1;
703 }
704
705 static int replmd_replPropertyMetaDataCtr1_verify(struct ldb_context *ldb,
706                                                   struct replPropertyMetaDataCtr1 *ctr1,
707                                                   const struct dsdb_attribute *rdn_sa,
708                                                   struct ldb_dn *dn)
709 {
710         if (ctr1->count == 0) {
711                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
712                               "No elements found in replPropertyMetaData for %s!\n",
713                               ldb_dn_get_linearized(dn));
714                 return LDB_ERR_CONSTRAINT_VIOLATION;
715         }
716         if (ctr1->array[ctr1->count - 1].attid != rdn_sa->attributeID_id) {
717                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
718                               "No rDN found in replPropertyMetaData for %s!\n",
719                               ldb_dn_get_linearized(dn));
720                 return LDB_ERR_CONSTRAINT_VIOLATION;
721         }
722
723         /* the objectClass attribute is value 0x00000000, so must be first */
724         if (ctr1->array[0].attid != DRSUAPI_ATTID_objectClass) {
725                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
726                               "No objectClass found in replPropertyMetaData for %s!\n",
727                               ldb_dn_get_linearized(dn));
728                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
729         }
730
731         return LDB_SUCCESS;
732 }
733
734 static int replmd_replPropertyMetaDataCtr1_sort_and_verify(struct ldb_context *ldb,
735                                                            struct replPropertyMetaDataCtr1 *ctr1,
736                                                            const struct dsdb_schema *schema,
737                                                            struct ldb_dn *dn)
738 {
739         const char *rdn_name;
740         const struct dsdb_attribute *rdn_sa;
741
742         rdn_name = ldb_dn_get_rdn_name(dn);
743         if (!rdn_name) {
744                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
745                               __location__ ": No rDN for %s?\n",
746                               ldb_dn_get_linearized(dn));
747                 return LDB_ERR_INVALID_DN_SYNTAX;
748         }
749
750         rdn_sa = dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
751         if (rdn_sa == NULL) {
752                 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
753                               __location__ ": No sa found for rDN %s for %s\n",
754                               rdn_name, ldb_dn_get_linearized(dn));
755                 return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
756         }
757
758         DEBUG(6,("Sorting rpmd with attid exception %u rDN=%s DN=%s\n",
759                  rdn_sa->attributeID_id, rdn_name, ldb_dn_get_linearized(dn)));
760
761         LDB_TYPESAFE_QSORT(ctr1->array, ctr1->count, &rdn_sa->attributeID_id,
762                            replmd_replPropertyMetaData1_attid_sort);
763         return replmd_replPropertyMetaDataCtr1_verify(ldb, ctr1, rdn_sa, dn);
764 }
765
766 static int replmd_ldb_message_element_attid_sort(const struct ldb_message_element *e1,
767                                                  const struct ldb_message_element *e2,
768                                                  const struct dsdb_schema *schema)
769 {
770         const struct dsdb_attribute *a1;
771         const struct dsdb_attribute *a2;
772
773         /*
774          * TODO: make this faster by caching the dsdb_attribute pointer
775          *       on the ldb_messag_element
776          */
777
778         a1 = dsdb_attribute_by_lDAPDisplayName(schema, e1->name);
779         a2 = dsdb_attribute_by_lDAPDisplayName(schema, e2->name);
780
781         /*
782          * TODO: remove this check, we should rely on e1 and e2 having valid attribute names
783          *       in the schema
784          */
785         if (!a1 || !a2) {
786                 return strcasecmp(e1->name, e2->name);
787         }
788         if (a1->attributeID_id == a2->attributeID_id) {
789                 return 0;
790         }
791         return a1->attributeID_id > a2->attributeID_id ? 1 : -1;
792 }
793
794 static void replmd_ldb_message_sort(struct ldb_message *msg,
795                                     const struct dsdb_schema *schema)
796 {
797         LDB_TYPESAFE_QSORT(msg->elements, msg->num_elements, schema, replmd_ldb_message_element_attid_sort);
798 }
799
800 static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
801                                const struct GUID *invocation_id, uint64_t seq_num,
802                                uint64_t local_usn, NTTIME nttime, uint32_t version, bool deleted);
803
804
805 /*
806   fix up linked attributes in replmd_add.
807   This involves setting up the right meta-data in extended DN
808   components, and creating backlinks to the object
809  */
810 static int replmd_add_fix_la(struct ldb_module *module, struct ldb_message_element *el,
811                              uint64_t seq_num, const struct GUID *invocationId, time_t t,
812                              struct GUID *guid, const struct dsdb_attribute *sa, struct ldb_request *parent)
813 {
814         unsigned int i;
815         TALLOC_CTX *tmp_ctx = talloc_new(el->values);
816         struct ldb_context *ldb = ldb_module_get_ctx(module);
817
818         /* We will take a reference to the schema in replmd_add_backlink */
819         const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
820         NTTIME now;
821
822         unix_to_nt_time(&now, t);
823
824         for (i=0; i<el->num_values; i++) {
825                 struct ldb_val *v = &el->values[i];
826                 struct dsdb_dn *dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, v, sa->syntax->ldap_oid);
827                 struct GUID target_guid;
828                 NTSTATUS status;
829                 int ret;
830
831                 /* note that the DN already has the extended
832                    components from the extended_dn_store module */
833                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &target_guid, "GUID");
834                 if (!NT_STATUS_IS_OK(status) || GUID_all_zero(&target_guid)) {
835                         ret = dsdb_module_guid_by_dn(module, dsdb_dn->dn, &target_guid, parent);
836                         if (ret != LDB_SUCCESS) {
837                                 talloc_free(tmp_ctx);
838                                 return ret;
839                         }
840                         ret = dsdb_set_extended_dn_guid(dsdb_dn->dn, &target_guid, "GUID");
841                         if (ret != LDB_SUCCESS) {
842                                 talloc_free(tmp_ctx);
843                                 return ret;
844                         }
845                 }
846
847                 ret = replmd_build_la_val(el->values, v, dsdb_dn, invocationId,
848                                           seq_num, seq_num, now, 0, false);
849                 if (ret != LDB_SUCCESS) {
850                         talloc_free(tmp_ctx);
851                         return ret;
852                 }
853
854                 ret = replmd_add_backlink(module, schema, guid, &target_guid, true, sa, false);
855                 if (ret != LDB_SUCCESS) {
856                         talloc_free(tmp_ctx);
857                         return ret;
858                 }
859         }
860
861         talloc_free(tmp_ctx);
862         return LDB_SUCCESS;
863 }
864
865
866 /*
867   intercept add requests
868  */
869 static int replmd_add(struct ldb_module *module, struct ldb_request *req)
870 {
871         struct samldb_msds_intid_persistant *msds_intid_struct;
872         struct ldb_context *ldb;
873         struct ldb_control *control;
874         struct replmd_replicated_request *ac;
875         enum ndr_err_code ndr_err;
876         struct ldb_request *down_req;
877         struct ldb_message *msg;
878         const DATA_BLOB *guid_blob;
879         struct GUID guid;
880         struct replPropertyMetaDataBlob nmd;
881         struct ldb_val nmd_value;
882         const struct GUID *our_invocation_id;
883         time_t t = time(NULL);
884         NTTIME now;
885         char *time_str;
886         int ret;
887         unsigned int i;
888         unsigned int functional_level;
889         uint32_t ni=0;
890         bool allow_add_guid = false;
891         bool remove_current_guid = false;
892         bool is_urgent = false;
893         struct ldb_message_element *objectclass_el;
894         struct replmd_private *replmd_private =
895                 talloc_get_type_abort(ldb_module_get_private(module), struct replmd_private);
896
897         /* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
898         control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
899         if (control) {
900                 allow_add_guid = true;
901         }
902
903         /* do not manipulate our control entries */
904         if (ldb_dn_is_special(req->op.add.message->dn)) {
905                 return ldb_next_request(module, req);
906         }
907
908         ldb = ldb_module_get_ctx(module);
909
910         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_add\n");
911
912         guid_blob = ldb_msg_find_ldb_val(req->op.add.message, "objectGUID");
913         if (guid_blob != NULL) {
914                 if (!allow_add_guid) {
915                         ldb_set_errstring(ldb,
916                                           "replmd_add: it's not allowed to add an object with objectGUID!");
917                         return LDB_ERR_UNWILLING_TO_PERFORM;
918                 } else {
919                         NTSTATUS status = GUID_from_data_blob(guid_blob,&guid);
920                         if (!NT_STATUS_IS_OK(status)) {
921                                 ldb_set_errstring(ldb,
922                                                   "replmd_add: Unable to parse the 'objectGUID' as a GUID!");
923                                 return LDB_ERR_UNWILLING_TO_PERFORM;
924                         }
925                         /* we remove this attribute as it can be a string and
926                          * will not be treated correctly and then we will re-add
927                          * it later on in the good format */
928                         remove_current_guid = true;
929                 }
930         } else {
931                 /* a new GUID */
932                 guid = GUID_random();
933         }
934
935         ac = replmd_ctx_init(module, req);
936         if (ac == NULL) {
937                 return ldb_module_oom(module);
938         }
939
940         functional_level = dsdb_functional_level(ldb);
941
942         /* Get a sequence number from the backend */
943         ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, &ac->seq_num);
944         if (ret != LDB_SUCCESS) {
945                 talloc_free(ac);
946                 return ret;
947         }
948
949         /* get our invocationId */
950         our_invocation_id = samdb_ntds_invocation_id(ldb);
951         if (!our_invocation_id) {
952                 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
953                               "replmd_add: unable to find invocationId\n");
954                 talloc_free(ac);
955                 return LDB_ERR_OPERATIONS_ERROR;
956         }
957
958         /* we have to copy the message as the caller might have it as a const */
959         msg = ldb_msg_copy_shallow(ac, req->op.add.message);
960         if (msg == NULL) {
961                 ldb_oom(ldb);
962                 talloc_free(ac);
963                 return LDB_ERR_OPERATIONS_ERROR;
964         }
965
966         /* generated times */
967         unix_to_nt_time(&now, t);
968         time_str = ldb_timestring(msg, t);
969         if (!time_str) {
970                 ldb_oom(ldb);
971                 talloc_free(ac);
972                 return LDB_ERR_OPERATIONS_ERROR;
973         }
974         if (remove_current_guid) {
975                 ldb_msg_remove_attr(msg,"objectGUID");
976         }
977
978         /*
979          * remove autogenerated attributes
980          */
981         ldb_msg_remove_attr(msg, "whenCreated");
982         ldb_msg_remove_attr(msg, "whenChanged");
983         ldb_msg_remove_attr(msg, "uSNCreated");
984         ldb_msg_remove_attr(msg, "uSNChanged");
985         ldb_msg_remove_attr(msg, "replPropertyMetaData");
986
987         /*
988          * readd replicated attributes
989          */
990         ret = ldb_msg_add_string(msg, "whenCreated", time_str);
991         if (ret != LDB_SUCCESS) {
992                 ldb_oom(ldb);
993                 talloc_free(ac);
994                 return ret;
995         }
996
997         /* build the replication meta_data */
998         ZERO_STRUCT(nmd);
999         nmd.version             = 1;
1000         nmd.ctr.ctr1.count      = msg->num_elements;
1001         nmd.ctr.ctr1.array      = talloc_array(msg,
1002                                                struct replPropertyMetaData1,
1003                                                nmd.ctr.ctr1.count);
1004         if (!nmd.ctr.ctr1.array) {
1005                 ldb_oom(ldb);
1006                 talloc_free(ac);
1007                 return LDB_ERR_OPERATIONS_ERROR;
1008         }
1009
1010         for (i=0; i < msg->num_elements; i++) {
1011                 struct ldb_message_element *e = &msg->elements[i];
1012                 struct replPropertyMetaData1 *m = &nmd.ctr.ctr1.array[ni];
1013                 const struct dsdb_attribute *sa;
1014
1015                 if (e->name[0] == '@') continue;
1016
1017                 sa = dsdb_attribute_by_lDAPDisplayName(ac->schema, e->name);
1018                 if (!sa) {
1019                         ldb_debug_set(ldb, LDB_DEBUG_ERROR,
1020                                       "replmd_add: attribute '%s' not defined in schema\n",
1021                                       e->name);
1022                         talloc_free(ac);
1023                         return LDB_ERR_NO_SUCH_ATTRIBUTE;
1024                 }
1025
1026                 if ((sa->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (sa->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
1027                         /* if the attribute is not replicated (0x00000001)
1028                          * or constructed (0x00000004) it has no metadata
1029                          */
1030                         continue;
1031                 }
1032
1033                 if (sa->linkID != 0 && functional_level > DS_DOMAIN_FUNCTION_2000) {
1034                         ret = replmd_add_fix_la(module, e, ac->seq_num, our_invocation_id, t, &guid, sa, req);
1035                         if (ret != LDB_SUCCESS) {
1036                                 talloc_free(ac);
1037                                 return ret;
1038                         }
1039                         /* linked attributes are not stored in
1040                            replPropertyMetaData in FL above w2k */
1041                         continue;
1042                 }
1043
1044                 m->attid                        = sa->attributeID_id;
1045                 m->version                      = 1;
1046                 if (m->attid == 0x20030) {
1047                         const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
1048                         const char* rdn;
1049
1050                         if (rdn_val == NULL) {
1051                                 ldb_oom(ldb);
1052                                 talloc_free(ac);
1053                                 return LDB_ERR_OPERATIONS_ERROR;
1054                         }
1055
1056                         rdn = (const char*)rdn_val->data;
1057                         if (strcmp(rdn, "Deleted Objects") == 0) {
1058                                 /*
1059                                  * Set the originating_change_time to 29/12/9999 at 23:59:59
1060                                  * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container
1061                                  */
1062                                 m->originating_change_time      = DELETED_OBJECT_CONTAINER_CHANGE_TIME;
1063                         } else {
1064                                 m->originating_change_time      = now;
1065                         }
1066                 } else {
1067                         m->originating_change_time      = now;
1068                 }
1069                 m->originating_invocation_id    = *our_invocation_id;
1070                 m->originating_usn              = ac->seq_num;
1071                 m->local_usn                    = ac->seq_num;
1072                 ni++;
1073         }
1074
1075         /* fix meta data count */
1076         nmd.ctr.ctr1.count = ni;
1077
1078         /*
1079          * sort meta data array, and move the rdn attribute entry to the end
1080          */
1081         ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &nmd.ctr.ctr1, ac->schema, msg->dn);
1082         if (ret != LDB_SUCCESS) {
1083                 ldb_asprintf_errstring(ldb, "%s: error during direct ADD: %s", __func__, ldb_errstring(ldb));
1084                 talloc_free(ac);
1085                 return ret;
1086         }
1087
1088         /* generated NDR encoded values */
1089         ndr_err = ndr_push_struct_blob(&nmd_value, msg,
1090                                        &nmd,
1091                                        (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
1092         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1093                 ldb_oom(ldb);
1094                 talloc_free(ac);
1095                 return LDB_ERR_OPERATIONS_ERROR;
1096         }
1097
1098         /*
1099          * add the autogenerated values
1100          */
1101         ret = dsdb_msg_add_guid(msg, &guid, "objectGUID");
1102         if (ret != LDB_SUCCESS) {
1103                 ldb_oom(ldb);
1104                 talloc_free(ac);
1105                 return ret;
1106         }
1107         ret = ldb_msg_add_string(msg, "whenChanged", time_str);
1108         if (ret != LDB_SUCCESS) {
1109                 ldb_oom(ldb);
1110                 talloc_free(ac);
1111                 return ret;
1112         }
1113         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNCreated", ac->seq_num);
1114         if (ret != LDB_SUCCESS) {
1115                 ldb_oom(ldb);
1116                 talloc_free(ac);
1117                 return ret;
1118         }
1119         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNChanged", ac->seq_num);
1120         if (ret != LDB_SUCCESS) {
1121                 ldb_oom(ldb);
1122                 talloc_free(ac);
1123                 return ret;
1124         }
1125         ret = ldb_msg_add_value(msg, "replPropertyMetaData", &nmd_value, NULL);
1126         if (ret != LDB_SUCCESS) {
1127                 ldb_oom(ldb);
1128                 talloc_free(ac);
1129                 return ret;
1130         }
1131
1132         /*
1133          * sort the attributes by attid before storing the object
1134          */
1135         replmd_ldb_message_sort(msg, ac->schema);
1136
1137         /*
1138          * Assert that we do have an objectClass
1139          */
1140         objectclass_el = ldb_msg_find_element(msg, "objectClass");
1141         if (objectclass_el == NULL) {
1142                 ldb_asprintf_errstring(ldb, __location__
1143                                        ": objectClass missing on %s\n",
1144                                        ldb_dn_get_linearized(msg->dn));
1145                 talloc_free(ac);
1146                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1147         }
1148         is_urgent = replmd_check_urgent_objectclass(objectclass_el,
1149                                                         REPL_URGENT_ON_CREATE);
1150
1151         ac->is_urgent = is_urgent;
1152         ret = ldb_build_add_req(&down_req, ldb, ac,
1153                                 msg,
1154                                 req->controls,
1155                                 ac, replmd_op_callback,
1156                                 req);
1157
1158         LDB_REQ_SET_LOCATION(down_req);
1159         if (ret != LDB_SUCCESS) {
1160                 talloc_free(ac);
1161                 return ret;
1162         }
1163
1164         /* current partition control is needed by "replmd_op_callback" */
1165         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
1166                 ret = ldb_request_add_control(down_req,
1167                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
1168                                               false, NULL);
1169                 if (ret != LDB_SUCCESS) {
1170                         talloc_free(ac);
1171                         return ret;
1172                 }
1173         }
1174
1175         if (functional_level == DS_DOMAIN_FUNCTION_2000) {
1176                 ret = ldb_request_add_control(down_req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
1177                 if (ret != LDB_SUCCESS) {
1178                         talloc_free(ac);
1179                         return ret;
1180                 }
1181         }
1182
1183         /* mark the control done */
1184         if (control) {
1185                 control->critical = 0;
1186         }
1187         if (ldb_dn_compare_base(replmd_private->schema_dn, req->op.add.message->dn) != 0) {
1188
1189                 /* Update the usn in the SAMLDB_MSDS_INTID_OPAQUE opaque */
1190                 msds_intid_struct = (struct samldb_msds_intid_persistant *) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE);
1191                 if (msds_intid_struct) {
1192                         msds_intid_struct->usn = ac->seq_num;
1193                 }
1194         }
1195         /* go on with the call chain */
1196         return ldb_next_request(module, down_req);
1197 }
1198
1199
1200 /*
1201  * update the replPropertyMetaData for one element
1202  */
1203 static int replmd_update_rpmd_element(struct ldb_context *ldb,
1204                                       struct ldb_message *msg,
1205                                       struct ldb_message_element *el,
1206                                       struct ldb_message_element *old_el,
1207                                       struct replPropertyMetaDataBlob *omd,
1208                                       const struct dsdb_schema *schema,
1209                                       uint64_t *seq_num,
1210                                       const struct GUID *our_invocation_id,
1211                                       NTTIME now,
1212                                       struct ldb_request *req)
1213 {
1214         uint32_t i;
1215         const struct dsdb_attribute *a;
1216         struct replPropertyMetaData1 *md1;
1217         bool may_skip = false;
1218
1219         a = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
1220         if (a == NULL) {
1221                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
1222                         /* allow this to make it possible for dbcheck
1223                            to remove bad attributes */
1224                         return LDB_SUCCESS;
1225                 }
1226
1227                 DEBUG(0,(__location__ ": Unable to find attribute %s in schema\n",
1228                          el->name));
1229                 return LDB_ERR_OPERATIONS_ERROR;
1230         }
1231
1232         if ((a->systemFlags & DS_FLAG_ATTR_NOT_REPLICATED) || (a->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED)) {
1233                 return LDB_SUCCESS;
1234         }
1235
1236         /*
1237          * if the attribute's value haven't changed, and this isn't
1238          * just a delete of everything then return LDB_SUCCESS Unless
1239          * we have the provision control or if the attribute is
1240          * interSiteTopologyGenerator as this page explain:
1241          * http://support.microsoft.com/kb/224815 this attribute is
1242          * periodicaly written by the DC responsible for the intersite
1243          * generation in a given site
1244          *
1245          * Unchanged could be deleting or replacing an already-gone
1246          * thing with an unconstrained delete/empty replace or a
1247          * replace with the same value, but not an add with the same
1248          * value because that could be about adding a duplicate (which
1249          * is for someone else to error out on).
1250          */
1251         if (old_el != NULL && ldb_msg_element_equal_ordered(el, old_el)) {
1252                 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) {
1253                         may_skip = true;
1254                 }
1255         } else if (old_el == NULL && el->num_values == 0) {
1256                 if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) {
1257                         may_skip = true;
1258                 } else if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
1259                         may_skip = true;
1260                 }
1261         }
1262
1263         if (may_skip) {
1264                 if (strcmp(el->name, "interSiteTopologyGenerator") != 0 &&
1265                     !ldb_request_get_control(req, LDB_CONTROL_PROVISION_OID)) {
1266                         /*
1267                          * allow this to make it possible for dbcheck
1268                          * to rebuild broken metadata
1269                          */
1270                         return LDB_SUCCESS;
1271                 }
1272         }
1273
1274         for (i=0; i<omd->ctr.ctr1.count; i++) {
1275                 if (a->attributeID_id == omd->ctr.ctr1.array[i].attid) break;
1276         }
1277
1278         if (a->linkID != 0 && dsdb_functional_level(ldb) > DS_DOMAIN_FUNCTION_2000) {
1279                 /* linked attributes are not stored in
1280                    replPropertyMetaData in FL above w2k, but we do
1281                    raise the seqnum for the object  */
1282                 if (*seq_num == 0 &&
1283                     ldb_sequence_number(ldb, LDB_SEQ_NEXT, seq_num) != LDB_SUCCESS) {
1284                         return LDB_ERR_OPERATIONS_ERROR;
1285                 }
1286                 return LDB_SUCCESS;
1287         }
1288
1289         if (i == omd->ctr.ctr1.count) {
1290                 /* we need to add a new one */
1291                 omd->ctr.ctr1.array = talloc_realloc(msg, omd->ctr.ctr1.array,
1292                                                      struct replPropertyMetaData1, omd->ctr.ctr1.count+1);
1293                 if (omd->ctr.ctr1.array == NULL) {
1294                         ldb_oom(ldb);
1295                         return LDB_ERR_OPERATIONS_ERROR;
1296                 }
1297                 omd->ctr.ctr1.count++;
1298                 ZERO_STRUCT(omd->ctr.ctr1.array[i]);
1299         }
1300
1301         /* Get a new sequence number from the backend. We only do this
1302          * if we have a change that requires a new
1303          * replPropertyMetaData element
1304          */
1305         if (*seq_num == 0) {
1306                 int ret = ldb_sequence_number(ldb, LDB_SEQ_NEXT, seq_num);
1307                 if (ret != LDB_SUCCESS) {
1308                         return LDB_ERR_OPERATIONS_ERROR;
1309                 }
1310         }
1311
1312         md1 = &omd->ctr.ctr1.array[i];
1313         md1->version++;
1314         md1->attid                     = a->attributeID_id;
1315         if (md1->attid == 0x20030) {
1316                 const struct ldb_val *rdn_val = ldb_dn_get_rdn_val(msg->dn);
1317                 const char* rdn;
1318
1319                 if (rdn_val == NULL) {
1320                         ldb_oom(ldb);
1321                         return LDB_ERR_OPERATIONS_ERROR;
1322                 }
1323
1324                 rdn = (const char*)rdn_val->data;
1325                 if (strcmp(rdn, "Deleted Objects") == 0) {
1326                         /*
1327                          * Set the originating_change_time to 29/12/9999 at 23:59:59
1328                          * as specified in MS-ADTS 7.1.1.4.2 Deleted Objects Container
1329                          */
1330                         md1->originating_change_time    = DELETED_OBJECT_CONTAINER_CHANGE_TIME;
1331                 } else {
1332                         md1->originating_change_time    = now;
1333                 }
1334         } else {
1335                 md1->originating_change_time    = now;
1336         }
1337         md1->originating_invocation_id = *our_invocation_id;
1338         md1->originating_usn           = *seq_num;
1339         md1->local_usn                 = *seq_num;
1340
1341         return LDB_SUCCESS;
1342 }
1343
1344 static uint64_t find_max_local_usn(struct replPropertyMetaDataBlob omd)
1345 {
1346         uint32_t count = omd.ctr.ctr1.count;
1347         uint64_t max = 0;
1348         uint32_t i;
1349         for (i=0; i < count; i++) {
1350                 struct replPropertyMetaData1 m = omd.ctr.ctr1.array[i];
1351                 if (max < m.local_usn) {
1352                         max = m.local_usn;
1353                 }
1354         }
1355         return max;
1356 }
1357
1358 /*
1359  * update the replPropertyMetaData object each time we modify an
1360  * object. This is needed for DRS replication, as the merge on the
1361  * client is based on this object
1362  */
1363 static int replmd_update_rpmd(struct ldb_module *module,
1364                               const struct dsdb_schema *schema,
1365                               struct ldb_request *req,
1366                               const char * const *rename_attrs,
1367                               struct ldb_message *msg, uint64_t *seq_num,
1368                               time_t t,
1369                               bool *is_urgent, bool *rodc)
1370 {
1371         const struct ldb_val *omd_value;
1372         enum ndr_err_code ndr_err;
1373         struct replPropertyMetaDataBlob omd;
1374         unsigned int i;
1375         NTTIME now;
1376         const struct GUID *our_invocation_id;
1377         int ret;
1378         const char * const *attrs = NULL;
1379         const char * const attrs1[] = { "replPropertyMetaData", "*", NULL };
1380         const char * const attrs2[] = { "uSNChanged", "objectClass", "instanceType", NULL };
1381         struct ldb_result *res;
1382         struct ldb_context *ldb;
1383         struct ldb_message_element *objectclass_el;
1384         enum urgent_situation situation;
1385         bool rmd_is_provided;
1386         bool rmd_is_just_resorted = false;
1387
1388         if (rename_attrs) {
1389                 attrs = rename_attrs;
1390         } else {
1391                 attrs = attrs1;
1392         }
1393
1394         ldb = ldb_module_get_ctx(module);
1395
1396         our_invocation_id = samdb_ntds_invocation_id(ldb);
1397         if (!our_invocation_id) {
1398                 /* this happens during an initial vampire while
1399                    updating the schema */
1400                 DEBUG(5,("No invocationID - skipping replPropertyMetaData update\n"));
1401                 return LDB_SUCCESS;
1402         }
1403
1404         unix_to_nt_time(&now, t);
1405
1406         if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_OID)) {
1407                 rmd_is_provided = true;
1408                 if (ldb_request_get_control(req, DSDB_CONTROL_CHANGEREPLMETADATA_RESORT_OID)) {
1409                         rmd_is_just_resorted = true;
1410                 }
1411         } else {
1412                 rmd_is_provided = false;
1413         }
1414
1415         /* if isDeleted is present and is TRUE, then we consider we are deleting,
1416          * otherwise we consider we are updating */
1417         if (ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")) {
1418                 situation = REPL_URGENT_ON_DELETE;
1419         } else if (rename_attrs) {
1420                 situation = REPL_URGENT_ON_CREATE | REPL_URGENT_ON_DELETE;
1421         } else {
1422                 situation = REPL_URGENT_ON_UPDATE;
1423         }
1424
1425         if (rmd_is_provided) {
1426                 /* In this case the change_replmetadata control was supplied */
1427                 /* We check that it's the only attribute that is provided
1428                  * (it's a rare case so it's better to keep the code simplier)
1429                  * We also check that the highest local_usn is bigger or the same as
1430                  * uSNChanged. */
1431                 uint64_t db_seq;
1432                 if( msg->num_elements != 1 ||
1433                         strncmp(msg->elements[0].name,
1434                                 "replPropertyMetaData", 20) ) {
1435                         DEBUG(0,(__location__ ": changereplmetada control called without "\
1436                                 "a specified replPropertyMetaData attribute or with others\n"));
1437                         return LDB_ERR_OPERATIONS_ERROR;
1438                 }
1439                 if (situation != REPL_URGENT_ON_UPDATE) {
1440                         DEBUG(0,(__location__ ": changereplmetada control can't be called when deleting an object\n"));
1441                         return LDB_ERR_OPERATIONS_ERROR;
1442                 }
1443                 omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
1444                 if (!omd_value) {
1445                         DEBUG(0,(__location__ ": replPropertyMetaData was not specified for Object %s\n",
1446                                  ldb_dn_get_linearized(msg->dn)));
1447                         return LDB_ERR_OPERATIONS_ERROR;
1448                 }
1449                 ndr_err = ndr_pull_struct_blob(omd_value, msg, &omd,
1450                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
1451                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1452                         DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
1453                                  ldb_dn_get_linearized(msg->dn)));
1454                         return LDB_ERR_OPERATIONS_ERROR;
1455                 }
1456
1457                 ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs2,
1458                                             DSDB_FLAG_NEXT_MODULE |
1459                                             DSDB_SEARCH_SHOW_RECYCLED |
1460                                             DSDB_SEARCH_SHOW_EXTENDED_DN |
1461                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
1462                                             DSDB_SEARCH_REVEAL_INTERNALS, req);
1463
1464                 if (ret != LDB_SUCCESS) {
1465                         return ret;
1466                 }
1467
1468                 if (rmd_is_just_resorted == false) {
1469                         *seq_num = find_max_local_usn(omd);
1470
1471                         db_seq = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNChanged", 0);
1472
1473                         /*
1474                          * The test here now allows for a new
1475                          * replPropertyMetaData with no change, if was
1476                          * just dbcheck re-sorting the values.
1477                          */
1478                         if (*seq_num <= db_seq) {
1479                                 DEBUG(0,(__location__ ": changereplmetada control provided but max(local_usn)" \
1480                                          " is less than uSNChanged (max = %lld uSNChanged = %lld)\n",
1481                                          (long long)*seq_num, (long long)db_seq));
1482                                 return LDB_ERR_OPERATIONS_ERROR;
1483                         }
1484                 }
1485
1486         } else {
1487                 /* search for the existing replPropertyMetaDataBlob. We need
1488                  * to use REVEAL and ask for DNs in storage format to support
1489                  * the check for values being the same in
1490                  * replmd_update_rpmd_element()
1491                  */
1492                 ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs,
1493                                             DSDB_FLAG_NEXT_MODULE |
1494                                             DSDB_SEARCH_SHOW_RECYCLED |
1495                                             DSDB_SEARCH_SHOW_EXTENDED_DN |
1496                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
1497                                             DSDB_SEARCH_REVEAL_INTERNALS, req);
1498                 if (ret != LDB_SUCCESS) {
1499                         return ret;
1500                 }
1501
1502                 omd_value = ldb_msg_find_ldb_val(res->msgs[0], "replPropertyMetaData");
1503                 if (!omd_value) {
1504                         DEBUG(0,(__location__ ": Object %s does not have a replPropertyMetaData attribute\n",
1505                                  ldb_dn_get_linearized(msg->dn)));
1506                         return LDB_ERR_OPERATIONS_ERROR;
1507                 }
1508
1509                 ndr_err = ndr_pull_struct_blob(omd_value, msg, &omd,
1510                                                (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
1511                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1512                         DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s\n",
1513                                  ldb_dn_get_linearized(msg->dn)));
1514                         return LDB_ERR_OPERATIONS_ERROR;
1515                 }
1516
1517                 if (omd.version != 1) {
1518                         DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s\n",
1519                                  omd.version, ldb_dn_get_linearized(msg->dn)));
1520                         return LDB_ERR_OPERATIONS_ERROR;
1521                 }
1522
1523                 for (i=0; i<msg->num_elements; i++) {
1524                         struct ldb_message_element *old_el;
1525                         old_el = ldb_msg_find_element(res->msgs[0], msg->elements[i].name);
1526                         ret = replmd_update_rpmd_element(ldb, msg, &msg->elements[i], old_el, &omd, schema, seq_num,
1527                                                          our_invocation_id, now, req);
1528                         if (ret != LDB_SUCCESS) {
1529                                 return ret;
1530                         }
1531
1532                         if (!*is_urgent && (situation == REPL_URGENT_ON_UPDATE)) {
1533                                 *is_urgent = replmd_check_urgent_attribute(&msg->elements[i]);
1534                         }
1535
1536                 }
1537         }
1538
1539         /*
1540          * Assert that we have an objectClass attribute - this is major
1541          * corruption if we don't have this!
1542          */
1543         objectclass_el = ldb_msg_find_element(res->msgs[0], "objectClass");
1544         if (objectclass_el != NULL) {
1545                 /*
1546                  * Now check if this objectClass means we need to do urgent replication
1547                  */
1548                 if (!*is_urgent && replmd_check_urgent_objectclass(objectclass_el,
1549                                                                    situation)) {
1550                         *is_urgent = true;
1551                 }
1552         } else if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
1553                 ldb_asprintf_errstring(ldb, __location__
1554                                        ": objectClass missing on %s\n",
1555                                        ldb_dn_get_linearized(msg->dn));
1556                 return LDB_ERR_OBJECT_CLASS_VIOLATION;
1557         }
1558
1559         /*
1560          * replmd_update_rpmd_element has done an update if the
1561          * seq_num is set
1562          */
1563         if (*seq_num != 0 || rmd_is_just_resorted == true) {
1564                 struct ldb_val *md_value;
1565                 struct ldb_message_element *el;
1566
1567                 /*if we are RODC and this is a DRSR update then its ok*/
1568                 if (!ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)
1569                     && !ldb_request_get_control(req, DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA)) {
1570                         unsigned instanceType;
1571
1572                         ret = samdb_rodc(ldb, rodc);
1573                         if (ret != LDB_SUCCESS) {
1574                                 DEBUG(4, (__location__ ": unable to tell if we are an RODC\n"));
1575                         } else if (*rodc) {
1576                                 ldb_set_errstring(ldb, "RODC modify is forbidden!");
1577                                 return LDB_ERR_REFERRAL;
1578                         }
1579
1580                         instanceType = ldb_msg_find_attr_as_uint(res->msgs[0], "instanceType", INSTANCE_TYPE_WRITE);
1581                         if (!(instanceType & INSTANCE_TYPE_WRITE)) {
1582                                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM,
1583                                                  "cannot change replicated attribute on partial replica");
1584                         }
1585                 }
1586
1587                 md_value = talloc(msg, struct ldb_val);
1588                 if (md_value == NULL) {
1589                         ldb_oom(ldb);
1590                         return LDB_ERR_OPERATIONS_ERROR;
1591                 }
1592
1593                 ret = replmd_replPropertyMetaDataCtr1_sort_and_verify(ldb, &omd.ctr.ctr1, schema, msg->dn);
1594                 if (ret != LDB_SUCCESS) {
1595                         ldb_asprintf_errstring(ldb, "%s: %s", __func__, ldb_errstring(ldb));
1596                         return ret;
1597                 }
1598
1599                 ndr_err = ndr_push_struct_blob(md_value, msg, &omd,
1600                                                (ndr_push_flags_fn_t)ndr_push_replPropertyMetaDataBlob);
1601                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1602                         DEBUG(0,(__location__ ": Failed to marshall replPropertyMetaData for %s\n",
1603                                  ldb_dn_get_linearized(msg->dn)));
1604                         return LDB_ERR_OPERATIONS_ERROR;
1605                 }
1606
1607                 ret = ldb_msg_add_empty(msg, "replPropertyMetaData", LDB_FLAG_MOD_REPLACE, &el);
1608                 if (ret != LDB_SUCCESS) {
1609                         DEBUG(0,(__location__ ": Failed to add updated replPropertyMetaData %s\n",
1610                                  ldb_dn_get_linearized(msg->dn)));
1611                         return ret;
1612                 }
1613
1614                 el->num_values = 1;
1615                 el->values = md_value;
1616         }
1617
1618         return LDB_SUCCESS;
1619 }
1620
1621 struct parsed_dn {
1622         struct dsdb_dn *dsdb_dn;
1623         struct GUID *guid;
1624         struct ldb_val *v;
1625 };
1626
1627 static int parsed_dn_compare(struct parsed_dn *pdn1, struct parsed_dn *pdn2)
1628 {
1629         return GUID_compare(pdn1->guid, pdn2->guid);
1630 }
1631
1632 static struct parsed_dn *parsed_dn_find(struct parsed_dn *pdn,
1633                                         unsigned int count, struct GUID *guid,
1634                                         struct ldb_dn *dn)
1635 {
1636         struct parsed_dn *ret;
1637         unsigned int i;
1638         if (dn && GUID_all_zero(guid)) {
1639                 /* when updating a link using DRS, we sometimes get a
1640                    NULL GUID. We then need to try and match by DN */
1641                 for (i=0; i<count; i++) {
1642                         if (ldb_dn_compare(pdn[i].dsdb_dn->dn, dn) == 0) {
1643                                 dsdb_get_extended_dn_guid(pdn[i].dsdb_dn->dn, guid, "GUID");
1644                                 return &pdn[i];
1645                         }
1646                 }
1647                 return NULL;
1648         }
1649         BINARY_ARRAY_SEARCH(pdn, count, guid, guid, GUID_compare, ret);
1650         return ret;
1651 }
1652
1653 /*
1654   get a series of message element values as an array of DNs and GUIDs
1655   the result is sorted by GUID
1656  */
1657 static int get_parsed_dns(struct ldb_module *module, TALLOC_CTX *mem_ctx,
1658                           struct ldb_message_element *el, struct parsed_dn **pdn,
1659                           const char *ldap_oid, struct ldb_request *parent)
1660 {
1661         unsigned int i;
1662         struct ldb_context *ldb = ldb_module_get_ctx(module);
1663
1664         if (el == NULL) {
1665                 *pdn = NULL;
1666                 return LDB_SUCCESS;
1667         }
1668
1669         (*pdn) = talloc_array(mem_ctx, struct parsed_dn, el->num_values);
1670         if (!*pdn) {
1671                 ldb_module_oom(module);
1672                 return LDB_ERR_OPERATIONS_ERROR;
1673         }
1674
1675         for (i=0; i<el->num_values; i++) {
1676                 struct ldb_val *v = &el->values[i];
1677                 NTSTATUS status;
1678                 struct ldb_dn *dn;
1679                 struct parsed_dn *p;
1680
1681                 p = &(*pdn)[i];
1682
1683                 p->dsdb_dn = dsdb_dn_parse(*pdn, ldb, v, ldap_oid);
1684                 if (p->dsdb_dn == NULL) {
1685                         return LDB_ERR_INVALID_DN_SYNTAX;
1686                 }
1687
1688                 dn = p->dsdb_dn->dn;
1689
1690                 p->guid = talloc(*pdn, struct GUID);
1691                 if (p->guid == NULL) {
1692                         ldb_module_oom(module);
1693                         return LDB_ERR_OPERATIONS_ERROR;
1694                 }
1695
1696                 status = dsdb_get_extended_dn_guid(dn, p->guid, "GUID");
1697                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1698                         /* we got a DN without a GUID - go find the GUID */
1699                         int ret = dsdb_module_guid_by_dn(module, dn, p->guid, parent);
1700                         if (ret != LDB_SUCCESS) {
1701                                 ldb_asprintf_errstring(ldb, "Unable to find GUID for DN %s\n",
1702                                                        ldb_dn_get_linearized(dn));
1703                                 if (ret == LDB_ERR_NO_SUCH_OBJECT &&
1704                                     LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE &&
1705                                     ldb_attr_cmp(el->name, "member") == 0) {
1706                                         return LDB_ERR_UNWILLING_TO_PERFORM;
1707                                 }
1708                                 return ret;
1709                         }
1710                         ret = dsdb_set_extended_dn_guid(dn, p->guid, "GUID");
1711                         if (ret != LDB_SUCCESS) {
1712                                 return ret;
1713                         }
1714                 } else if (!NT_STATUS_IS_OK(status)) {
1715                         return LDB_ERR_OPERATIONS_ERROR;
1716                 }
1717
1718                 /* keep a pointer to the original ldb_val */
1719                 p->v = v;
1720         }
1721
1722         TYPESAFE_QSORT(*pdn, el->num_values, parsed_dn_compare);
1723
1724         return LDB_SUCCESS;
1725 }
1726
1727 /*
1728   build a new extended DN, including all meta data fields
1729
1730   RMD_FLAGS           = DSDB_RMD_FLAG_* bits
1731   RMD_ADDTIME         = originating_add_time
1732   RMD_INVOCID         = originating_invocation_id
1733   RMD_CHANGETIME      = originating_change_time
1734   RMD_ORIGINATING_USN = originating_usn
1735   RMD_LOCAL_USN       = local_usn
1736   RMD_VERSION         = version
1737  */
1738 static int replmd_build_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
1739                                const struct GUID *invocation_id, uint64_t seq_num,
1740                                uint64_t local_usn, NTTIME nttime, uint32_t version, bool deleted)
1741 {
1742         struct ldb_dn *dn = dsdb_dn->dn;
1743         const char *tstring, *usn_string, *flags_string;
1744         struct ldb_val tval;
1745         struct ldb_val iid;
1746         struct ldb_val usnv, local_usnv;
1747         struct ldb_val vers, flagsv;
1748         NTSTATUS status;
1749         int ret;
1750         const char *dnstring;
1751         char *vstring;
1752         uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
1753
1754         tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
1755         if (!tstring) {
1756                 return LDB_ERR_OPERATIONS_ERROR;
1757         }
1758         tval = data_blob_string_const(tstring);
1759
1760         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)seq_num);
1761         if (!usn_string) {
1762                 return LDB_ERR_OPERATIONS_ERROR;
1763         }
1764         usnv = data_blob_string_const(usn_string);
1765
1766         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)local_usn);
1767         if (!usn_string) {
1768                 return LDB_ERR_OPERATIONS_ERROR;
1769         }
1770         local_usnv = data_blob_string_const(usn_string);
1771
1772         vstring = talloc_asprintf(mem_ctx, "%lu", (unsigned long)version);
1773         if (!vstring) {
1774                 return LDB_ERR_OPERATIONS_ERROR;
1775         }
1776         vers = data_blob_string_const(vstring);
1777
1778         status = GUID_to_ndr_blob(invocation_id, dn, &iid);
1779         if (!NT_STATUS_IS_OK(status)) {
1780                 return LDB_ERR_OPERATIONS_ERROR;
1781         }
1782
1783         flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
1784         if (!flags_string) {
1785                 return LDB_ERR_OPERATIONS_ERROR;
1786         }
1787         flagsv = data_blob_string_const(flags_string);
1788
1789         ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
1790         if (ret != LDB_SUCCESS) return ret;
1791         ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", &tval);
1792         if (ret != LDB_SUCCESS) return ret;
1793         ret = ldb_dn_set_extended_component(dn, "RMD_INVOCID", &iid);
1794         if (ret != LDB_SUCCESS) return ret;
1795         ret = ldb_dn_set_extended_component(dn, "RMD_CHANGETIME", &tval);
1796         if (ret != LDB_SUCCESS) return ret;
1797         ret = ldb_dn_set_extended_component(dn, "RMD_LOCAL_USN", &local_usnv);
1798         if (ret != LDB_SUCCESS) return ret;
1799         ret = ldb_dn_set_extended_component(dn, "RMD_ORIGINATING_USN", &usnv);
1800         if (ret != LDB_SUCCESS) return ret;
1801         ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
1802         if (ret != LDB_SUCCESS) return ret;
1803
1804         dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
1805         if (dnstring == NULL) {
1806                 return LDB_ERR_OPERATIONS_ERROR;
1807         }
1808         *v = data_blob_string_const(dnstring);
1809
1810         return LDB_SUCCESS;
1811 }
1812
1813 static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
1814                                 struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
1815                                 uint64_t seq_num, uint64_t local_usn, NTTIME nttime,
1816                                 uint32_t version, bool deleted);
1817
1818 /*
1819   check if any links need upgrading from w2k format
1820
1821   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.
1822  */
1823 static int replmd_check_upgrade_links(struct parsed_dn *dns, uint32_t count, struct ldb_message_element *parent_ctx, const struct GUID *invocation_id)
1824 {
1825         uint32_t i;
1826         for (i=0; i<count; i++) {
1827                 NTSTATUS status;
1828                 uint32_t version;
1829                 int ret;
1830
1831                 status = dsdb_get_extended_dn_uint32(dns[i].dsdb_dn->dn, &version, "RMD_VERSION");
1832                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1833                         continue;
1834                 }
1835
1836                 /* it's an old one that needs upgrading */
1837                 ret = replmd_update_la_val(parent_ctx->values, dns[i].v, dns[i].dsdb_dn, dns[i].dsdb_dn, invocation_id,
1838                                            1, 1, 0, 0, false);
1839                 if (ret != LDB_SUCCESS) {
1840                         return ret;
1841                 }
1842         }
1843         return LDB_SUCCESS;
1844 }
1845
1846 /*
1847   update an extended DN, including all meta data fields
1848
1849   see replmd_build_la_val for value names
1850  */
1851 static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct dsdb_dn *dsdb_dn,
1852                                 struct dsdb_dn *old_dsdb_dn, const struct GUID *invocation_id,
1853                                 uint64_t usn, uint64_t local_usn, NTTIME nttime,
1854                                 uint32_t version, bool deleted)
1855 {
1856         struct ldb_dn *dn = dsdb_dn->dn;
1857         const char *tstring, *usn_string, *flags_string;
1858         struct ldb_val tval;
1859         struct ldb_val iid;
1860         struct ldb_val usnv, local_usnv;
1861         struct ldb_val vers, flagsv;
1862         const struct ldb_val *old_addtime;
1863         uint32_t old_version;
1864         NTSTATUS status;
1865         int ret;
1866         const char *dnstring;
1867         char *vstring;
1868         uint32_t rmd_flags = deleted?DSDB_RMD_FLAG_DELETED:0;
1869
1870         tstring = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)nttime);
1871         if (!tstring) {
1872                 return LDB_ERR_OPERATIONS_ERROR;
1873         }
1874         tval = data_blob_string_const(tstring);
1875
1876         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)usn);
1877         if (!usn_string) {
1878                 return LDB_ERR_OPERATIONS_ERROR;
1879         }
1880         usnv = data_blob_string_const(usn_string);
1881
1882         usn_string = talloc_asprintf(mem_ctx, "%llu", (unsigned long long)local_usn);
1883         if (!usn_string) {
1884                 return LDB_ERR_OPERATIONS_ERROR;
1885         }
1886         local_usnv = data_blob_string_const(usn_string);
1887
1888         status = GUID_to_ndr_blob(invocation_id, dn, &iid);
1889         if (!NT_STATUS_IS_OK(status)) {
1890                 return LDB_ERR_OPERATIONS_ERROR;
1891         }
1892
1893         flags_string = talloc_asprintf(mem_ctx, "%u", rmd_flags);
1894         if (!flags_string) {
1895                 return LDB_ERR_OPERATIONS_ERROR;
1896         }
1897         flagsv = data_blob_string_const(flags_string);
1898
1899         ret = ldb_dn_set_extended_component(dn, "RMD_FLAGS", &flagsv);
1900         if (ret != LDB_SUCCESS) return ret;
1901
1902         /* get the ADDTIME from the original */
1903         old_addtime = ldb_dn_get_extended_component(old_dsdb_dn->dn, "RMD_ADDTIME");
1904         if (old_addtime == NULL) {
1905                 old_addtime = &tval;
1906         }
1907         if (dsdb_dn != old_dsdb_dn ||
1908             ldb_dn_get_extended_component(dn, "RMD_ADDTIME") == NULL) {
1909                 ret = ldb_dn_set_extended_component(dn, "RMD_ADDTIME", old_addtime);
1910                 if (ret != LDB_SUCCESS) return ret;
1911         }
1912
1913         /* use our invocation id */
1914         ret = ldb_dn_set_extended_component(dn, "RMD_INVOCID", &iid);
1915         if (ret != LDB_SUCCESS) return ret;
1916
1917         /* changetime is the current time */
1918         ret = ldb_dn_set_extended_component(dn, "RMD_CHANGETIME", &tval);
1919         if (ret != LDB_SUCCESS) return ret;
1920
1921         /* update the USN */
1922         ret = ldb_dn_set_extended_component(dn, "RMD_ORIGINATING_USN", &usnv);
1923         if (ret != LDB_SUCCESS) return ret;
1924
1925         ret = ldb_dn_set_extended_component(dn, "RMD_LOCAL_USN", &local_usnv);
1926         if (ret != LDB_SUCCESS) return ret;
1927
1928         /* increase the version by 1 */
1929         status = dsdb_get_extended_dn_uint32(old_dsdb_dn->dn, &old_version, "RMD_VERSION");
1930         if (NT_STATUS_IS_OK(status) && old_version >= version) {
1931                 version = old_version+1;
1932         }
1933         vstring = talloc_asprintf(dn, "%lu", (unsigned long)version);
1934         vers = data_blob_string_const(vstring);
1935         ret = ldb_dn_set_extended_component(dn, "RMD_VERSION", &vers);
1936         if (ret != LDB_SUCCESS) return ret;
1937
1938         dnstring = dsdb_dn_get_extended_linearized(mem_ctx, dsdb_dn, 1);
1939         if (dnstring == NULL) {
1940                 return LDB_ERR_OPERATIONS_ERROR;
1941         }
1942         *v = data_blob_string_const(dnstring);
1943
1944         return LDB_SUCCESS;
1945 }
1946
1947 /*
1948   handle adding a linked attribute
1949  */
1950 static int replmd_modify_la_add(struct ldb_module *module,
1951                                 const struct dsdb_schema *schema,
1952                                 struct ldb_message *msg,
1953                                 struct ldb_message_element *el,
1954                                 struct ldb_message_element *old_el,
1955                                 const struct dsdb_attribute *schema_attr,
1956                                 uint64_t seq_num,
1957                                 time_t t,
1958                                 struct GUID *msg_guid,
1959                                 struct ldb_request *parent)
1960 {
1961         unsigned int i;
1962         struct parsed_dn *dns, *old_dns;
1963         TALLOC_CTX *tmp_ctx = talloc_new(msg);
1964         int ret;
1965         struct ldb_val *new_values = NULL;
1966         unsigned int num_new_values = 0;
1967         unsigned old_num_values = old_el?old_el->num_values:0;
1968         const struct GUID *invocation_id;
1969         struct ldb_context *ldb = ldb_module_get_ctx(module);
1970         NTTIME now;
1971
1972         unix_to_nt_time(&now, t);
1973
1974         ret = get_parsed_dns(module, tmp_ctx, el, &dns, schema_attr->syntax->ldap_oid, parent);
1975         if (ret != LDB_SUCCESS) {
1976                 talloc_free(tmp_ctx);
1977                 return ret;
1978         }
1979
1980         ret = get_parsed_dns(module, tmp_ctx, old_el, &old_dns, schema_attr->syntax->ldap_oid, parent);
1981         if (ret != LDB_SUCCESS) {
1982                 talloc_free(tmp_ctx);
1983                 return ret;
1984         }
1985
1986         invocation_id = samdb_ntds_invocation_id(ldb);
1987         if (!invocation_id) {
1988                 talloc_free(tmp_ctx);
1989                 return LDB_ERR_OPERATIONS_ERROR;
1990         }
1991
1992         ret = replmd_check_upgrade_links(old_dns, old_num_values, old_el, invocation_id);
1993         if (ret != LDB_SUCCESS) {
1994                 talloc_free(tmp_ctx);
1995                 return ret;
1996         }
1997
1998         /* for each new value, see if it exists already with the same GUID */
1999         for (i=0; i<el->num_values; i++) {
2000                 struct parsed_dn *p = parsed_dn_find(old_dns, old_num_values, dns[i].guid, NULL);
2001                 if (p == NULL) {
2002                         /* this is a new linked attribute value */
2003                         new_values = talloc_realloc(tmp_ctx, new_values, struct ldb_val, num_new_values+1);
2004                         if (new_values == NULL) {
2005                                 ldb_module_oom(module);
2006                                 talloc_free(tmp_ctx);
2007                                 return LDB_ERR_OPERATIONS_ERROR;
2008                         }
2009                         ret = replmd_build_la_val(new_values, &new_values[num_new_values], dns[i].dsdb_dn,
2010                                                   invocation_id, seq_num, seq_num, now, 0, false);
2011                         if (ret != LDB_SUCCESS) {
2012                                 talloc_free(tmp_ctx);
2013                                 return ret;
2014                         }
2015                         num_new_values++;
2016                 } else {
2017                         /* this is only allowed if the GUID was
2018                            previously deleted. */
2019                         uint32_t rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
2020
2021                         if (!(rmd_flags & DSDB_RMD_FLAG_DELETED)) {
2022                                 ldb_asprintf_errstring(ldb, "Attribute %s already exists for target GUID %s",
2023                                                        el->name, GUID_string(tmp_ctx, p->guid));
2024                                 talloc_free(tmp_ctx);
2025                                 /* error codes for 'member' need to be
2026                                    special cased */
2027                                 if (ldb_attr_cmp(el->name, "member") == 0) {
2028                                         return LDB_ERR_ENTRY_ALREADY_EXISTS;
2029                                 } else {
2030                                         return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2031                                 }
2032                         }
2033                         ret = replmd_update_la_val(old_el->values, p->v, dns[i].dsdb_dn, p->dsdb_dn,
2034                                                    invocation_id, seq_num, seq_num, now, 0, false);
2035                         if (ret != LDB_SUCCESS) {
2036                                 talloc_free(tmp_ctx);
2037                                 return ret;
2038                         }
2039                 }
2040
2041                 ret = replmd_add_backlink(module, schema, msg_guid, dns[i].guid, true, schema_attr, true);
2042                 if (ret != LDB_SUCCESS) {
2043                         talloc_free(tmp_ctx);
2044                         return ret;
2045                 }
2046         }
2047
2048         /* add the new ones on to the end of the old values, constructing a new el->values */
2049         el->values = talloc_realloc(msg->elements, old_el?old_el->values:NULL,
2050                                     struct ldb_val,
2051                                     old_num_values+num_new_values);
2052         if (el->values == NULL) {
2053                 ldb_module_oom(module);
2054                 return LDB_ERR_OPERATIONS_ERROR;
2055         }
2056
2057         memcpy(&el->values[old_num_values], new_values, num_new_values*sizeof(struct ldb_val));
2058         el->num_values = old_num_values + num_new_values;
2059
2060         talloc_steal(msg->elements, el->values);
2061         talloc_steal(el->values, new_values);
2062
2063         talloc_free(tmp_ctx);
2064
2065         /* we now tell the backend to replace all existing values
2066            with the one we have constructed */
2067         el->flags = LDB_FLAG_MOD_REPLACE;
2068
2069         return LDB_SUCCESS;
2070 }
2071
2072
2073 /*
2074   handle deleting all active linked attributes
2075  */
2076 static int replmd_modify_la_delete(struct ldb_module *module,
2077                                    const struct dsdb_schema *schema,
2078                                    struct ldb_message *msg,
2079                                    struct ldb_message_element *el,
2080                                    struct ldb_message_element *old_el,
2081                                    const struct dsdb_attribute *schema_attr,
2082                                    uint64_t seq_num,
2083                                    time_t t,
2084                                    struct GUID *msg_guid,
2085                                    struct ldb_request *parent)
2086 {
2087         unsigned int i;
2088         struct parsed_dn *dns, *old_dns;
2089         TALLOC_CTX *tmp_ctx = talloc_new(msg);
2090         int ret;
2091         const struct GUID *invocation_id;
2092         struct ldb_context *ldb = ldb_module_get_ctx(module);
2093         NTTIME now;
2094
2095         unix_to_nt_time(&now, t);
2096
2097         /* check if there is nothing to delete */
2098         if ((!old_el || old_el->num_values == 0) &&
2099             el->num_values == 0) {
2100                 return LDB_SUCCESS;
2101         }
2102
2103         if (!old_el || old_el->num_values == 0) {
2104                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2105         }
2106
2107         ret = get_parsed_dns(module, tmp_ctx, el, &dns, schema_attr->syntax->ldap_oid, parent);
2108         if (ret != LDB_SUCCESS) {
2109                 talloc_free(tmp_ctx);
2110                 return ret;
2111         }
2112
2113         ret = get_parsed_dns(module, tmp_ctx, old_el, &old_dns, schema_attr->syntax->ldap_oid, parent);
2114         if (ret != LDB_SUCCESS) {
2115                 talloc_free(tmp_ctx);
2116                 return ret;
2117         }
2118
2119         invocation_id = samdb_ntds_invocation_id(ldb);
2120         if (!invocation_id) {
2121                 return LDB_ERR_OPERATIONS_ERROR;
2122         }
2123
2124         ret = replmd_check_upgrade_links(old_dns, old_el->num_values, old_el, invocation_id);
2125         if (ret != LDB_SUCCESS) {
2126                 talloc_free(tmp_ctx);
2127                 return ret;
2128         }
2129
2130         el->values = NULL;
2131
2132         /* see if we are being asked to delete any links that
2133            don't exist or are already deleted */
2134         for (i=0; i<el->num_values; i++) {
2135                 struct parsed_dn *p = &dns[i];
2136                 struct parsed_dn *p2;
2137                 uint32_t rmd_flags;
2138
2139                 p2 = parsed_dn_find(old_dns, old_el->num_values, p->guid, NULL);
2140                 if (!p2) {
2141                         ldb_asprintf_errstring(ldb, "Attribute %s doesn't exist for target GUID %s",
2142                                                el->name, GUID_string(tmp_ctx, p->guid));
2143                         if (ldb_attr_cmp(el->name, "member") == 0) {
2144                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2145                         } else {
2146                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2147                         }
2148                 }
2149                 rmd_flags = dsdb_dn_rmd_flags(p2->dsdb_dn->dn);
2150                 if (rmd_flags & DSDB_RMD_FLAG_DELETED) {
2151                         ldb_asprintf_errstring(ldb, "Attribute %s already deleted for target GUID %s",
2152                                                el->name, GUID_string(tmp_ctx, p->guid));
2153                         if (ldb_attr_cmp(el->name, "member") == 0) {
2154                                 return LDB_ERR_UNWILLING_TO_PERFORM;
2155                         } else {
2156                                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
2157                         }
2158                 }
2159         }
2160
2161         /* for each new value, see if it exists already with the same GUID
2162            if it is not already deleted and matches the delete list then delete it
2163         */
2164         for (i=0; i<old_el->num_values; i++) {
2165                 struct parsed_dn *p = &old_dns[i];
2166                 uint32_t rmd_flags;
2167
2168                 if (el->num_values && parsed_dn_find(dns, el->num_values, p->guid, NULL) == NULL) {
2169                         continue;
2170                 }
2171
2172                 rmd_flags = dsdb_dn_rmd_flags(p->dsdb_dn->dn);
2173                 if (rmd_flags & DSDB_RMD_FLAG_DELETED) continue;
2174
2175                 ret = replmd_update_la_val(old_el->values, p->v, p->dsdb_dn, p->dsdb_dn,
2176                                            invocation_id, seq_num, seq_num, now, 0, true);
2177                 if (ret != LDB_SUCCESS) {
2178                         talloc_free(tmp_ctx);
2179                         return ret;
2180                 }
2181
2182                 ret = replmd_add_backlink(module, schema, msg_guid, old_dns[i].guid, false, schema_attr, true);
2183                 if (ret != LDB_SUCCESS) {
2184                         talloc_free(tmp_ctx);
2185                         return ret;
2186                 }
2187         }
2188
2189         el->values = talloc_steal(msg->elements, old_el->values);
2190         el->num_values = old_el->num_values;
2191
2192         talloc_free(tmp_ctx);
2193
2194         /* we now tell the backend to replace all existing values
2195            with the one we have constructed */
2196         el->flags = LDB_FLAG_MOD_REPLACE;
2197
2198         return LDB_SUCCESS;
2199 }
2200
2201 /*
2202   handle replacing a linked attribute
2203  */
2204 static int replmd_modify_la_replace(struct ldb_module *module,
2205                                     const struct dsdb_schema *schema,
2206                                     struct ldb_message *msg,
2207                                     struct ldb_message_element *el,
2208                                     struct ldb_message_element *old_el,
2209                                     const struct dsdb_attribute *schema_attr,
2210                                     uint64_t seq_num,
2211                                     time_t t,
2212                                     struct GUID *msg_guid,
2213                                     struct ldb_request *parent)
2214 {
2215         unsigned int i;
2216         struct parsed_dn *dns, *old_dns;
2217         TALLOC_CTX *tmp_ctx = talloc_new(msg);
2218         int ret;
2219         const struct GUID *invocation_id;
2220         struct ldb_context *ldb = ldb_module_get_ctx(module);
2221         struct ldb_val *new_values = NULL;
2222         unsigned int num_new_values = 0;
2223         unsigned int old_num_values = old_el?old_el->num_values:0;
2224         NTTIME now;
2225
2226         unix_to_nt_time(&now, t);
2227
2228         /* check if there is nothing to replace */
2229         if ((!old_el || old_el->num_values == 0) &&
2230             el->num_values == 0) {
2231                 return LDB_SUCCESS;
2232         }
2233
2234         ret = get_parsed_dns(module, tmp_ctx, el, &dns, schema_attr->syntax->ldap_oid, parent);
2235         if (ret != LDB_SUCCESS) {
2236                 talloc_free(tmp_ctx);
2237                 return ret;
2238         }
2239
2240         ret = get_parsed_dns(module, tmp_ctx, old_el, &old_dns, schema_attr->syntax->ldap_oid, parent);
2241         if (ret != LDB_SUCCESS) {
2242                 talloc_free(tmp_ctx);
2243                 return ret;
2244         }
2245
2246         invocation_id = samdb_ntds_invocation_id(ldb);
2247         if (!invocation_id) {
2248                 return LDB_ERR_OPERATIONS_ERROR;
2249         }
2250
2251         ret = replmd_check_upgrade_links(old_dns, old_num_values, old_el, invocation_id);
2252         if (ret != LDB_SUCCESS) {
2253                 talloc_free(tmp_ctx);
2254                 return ret;
2255         }
2256
2257         /* mark all the old ones as deleted */
2258         for (i=0; i<old_num_values; i++) {
2259                 struct parsed_dn *old_p = &old_dns[i];
2260                 struct parsed_dn *p;
2261                 uint32_t rmd_flags = dsdb_dn_rmd_flags(old_p->dsdb_dn->dn);
2262
2263                 if (rmd_flags & DSDB_RMD_FLAG_DELETED) continue;
2264
2265                 ret = replmd_add_backlink(module, schema, msg_guid, old_dns[i].guid, false, schema_attr, false);
2266                 if (ret != LDB_SUCCESS) {
2267                         talloc_free(tmp_ctx);
2268                         return ret;
2269                 }
2270
2271                 p = parsed_dn_find(dns, el->num_values, old_p->guid, NULL);
2272                 if (p) {
2273                         /* we don't delete it if we are re-adding it */
2274                         continue;
2275                 }
2276
2277                 ret = replmd_update_la_val(old_el->values, old_p->v, old_p->dsdb_dn, old_p->dsdb_dn,
2278                                            invocation_id, seq_num, seq_num, now, 0, true);
2279                 if (ret != LDB_SUCCESS) {
2280                         talloc_free(tmp_ctx);
2281                         return ret;
2282                 }
2283         }
2284
2285         /* for each new value, either update its meta-data, or add it
2286          * to old_el
2287         */
2288         for (i=0; i<el->num_values; i++) {
2289                 struct parsed_dn *p = &dns[i], *old_p;
2290
2291                 if (old_dns &&
2292                     (old_p = parsed_dn_find(old_dns,
2293                                             old_num_values, p->guid, NULL)) != NULL) {
2294                         /* update in place */
2295                         ret = replmd_update_la_val(old_el->values, old_p->v, p->dsdb_dn,
2296                                                    old_p->dsdb_dn, invocation_id,
2297                                                    seq_num, seq_num, now, 0, false);
2298                         if (ret != LDB_SUCCESS) {
2299                                 talloc_free(tmp_ctx);
2300                                 return ret;
2301                         }
2302                 } else {
2303                         /* add a new one */
2304                         new_values = talloc_realloc(tmp_ctx, new_values, struct ldb_val,
2305                                                     num_new_values+1);
2306                         if (new_values == NULL) {
2307                                 ldb_module_oom(module);
2308                                 talloc_free(tmp_ctx);
2309                                 return LDB_ERR_OPERATIONS_ERROR;
2310                         }
2311                         ret = replmd_build_la_val(new_values, &new_values[num_new_values], dns[i].dsdb_dn,
2312                                                   invocation_id, seq_num, seq_num, now, 0, false);
2313                         if (ret != LDB_SUCCESS) {
2314                                 talloc_free(tmp_ctx);
2315                                 return ret;
2316                         }
2317                         num_new_values++;
2318                 }
2319
2320                 ret = replmd_add_backlink(module, schema, msg_guid, dns[i].guid, true, schema_attr, false);
2321                 if (ret != LDB_SUCCESS) {
2322                         talloc_free(tmp_ctx);
2323                         return ret;
2324                 }
2325         }
2326
2327         /* add the new values to the end of old_el */
2328         if (num_new_values != 0) {
2329                 el->values = talloc_realloc(msg->elements, old_el?old_el->values:NULL,
2330                                             struct ldb_val, old_num_values+num_new_values);
2331                 if (el->values == NULL) {
2332                         ldb_module_oom(module);
2333                         return LDB_ERR_OPERATIONS_ERROR;
2334                 }
2335                 memcpy(&el->values[old_num_values], &new_values[0],
2336                        sizeof(struct ldb_val)*num_new_values);
2337                 el->num_values = old_num_values + num_new_values;
2338                 talloc_steal(msg->elements, new_values);
2339         } else {
2340                 el->values = old_el->values;
2341                 el->num_values = old_el->num_values;
2342                 talloc_steal(msg->elements, el->values);
2343         }
2344
2345         talloc_free(tmp_ctx);
2346
2347         /* we now tell the backend to replace all existing values
2348            with the one we have constructed */
2349         el->flags = LDB_FLAG_MOD_REPLACE;
2350
2351         return LDB_SUCCESS;
2352 }
2353
2354
2355 /*
2356   handle linked attributes in modify requests
2357  */
2358 static int replmd_modify_handle_linked_attribs(struct ldb_module *module,
2359                                                struct ldb_message *msg,
2360                                                uint64_t seq_num, time_t t,
2361                                                struct ldb_request *parent)
2362 {
2363         struct ldb_result *res;
2364         unsigned int i;
2365         int ret;
2366         struct ldb_context *ldb = ldb_module_get_ctx(module);
2367         struct ldb_message *old_msg;
2368
2369         const struct dsdb_schema *schema;
2370         struct GUID old_guid;
2371
2372         if (seq_num == 0) {
2373                 /* there the replmd_update_rpmd code has already
2374                  * checked and saw that there are no linked
2375                  * attributes */
2376                 return LDB_SUCCESS;
2377         }
2378
2379         if (dsdb_functional_level(ldb) == DS_DOMAIN_FUNCTION_2000) {
2380                 /* don't do anything special for linked attributes */
2381                 return LDB_SUCCESS;
2382         }
2383
2384         ret = dsdb_module_search_dn(module, msg, &res, msg->dn, NULL,
2385                                     DSDB_FLAG_NEXT_MODULE |
2386                                     DSDB_SEARCH_SHOW_RECYCLED |
2387                                     DSDB_SEARCH_REVEAL_INTERNALS |
2388                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
2389                                     parent);
2390         if (ret != LDB_SUCCESS) {
2391                 return ret;
2392         }
2393         schema = dsdb_get_schema(ldb, res);
2394         if (!schema) {
2395                 return LDB_ERR_OPERATIONS_ERROR;
2396         }
2397
2398         old_msg = res->msgs[0];
2399
2400         old_guid = samdb_result_guid(old_msg, "objectGUID");
2401
2402         for (i=0; i<msg->num_elements; i++) {
2403                 struct ldb_message_element *el = &msg->elements[i];
2404                 struct ldb_message_element *old_el, *new_el;
2405                 const struct dsdb_attribute *schema_attr
2406                         = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
2407                 if (!schema_attr) {
2408                         ldb_asprintf_errstring(ldb,
2409                                                "%s: attribute %s is not a valid attribute in schema",
2410                                                __FUNCTION__, el->name);
2411                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
2412                 }
2413                 if (schema_attr->linkID == 0) {
2414                         continue;
2415                 }
2416                 if ((schema_attr->linkID & 1) == 1) {
2417                         if (parent && ldb_request_get_control(parent, DSDB_CONTROL_DBCHECK)) {
2418                                 continue;
2419                         }
2420                         /* Odd is for the target.  Illegal to modify */
2421                         ldb_asprintf_errstring(ldb,
2422                                                "attribute %s must not be modified directly, it is a linked attribute", el->name);
2423                         return LDB_ERR_UNWILLING_TO_PERFORM;
2424                 }
2425                 old_el = ldb_msg_find_element(old_msg, el->name);
2426                 switch (el->flags & LDB_FLAG_MOD_MASK) {
2427                 case LDB_FLAG_MOD_REPLACE:
2428                         ret = replmd_modify_la_replace(module, schema, msg, el, old_el, schema_attr, seq_num, t, &old_guid, parent);
2429                         break;
2430                 case LDB_FLAG_MOD_DELETE:
2431                         ret = replmd_modify_la_delete(module, schema, msg, el, old_el, schema_attr, seq_num, t, &old_guid, parent);
2432                         break;
2433                 case LDB_FLAG_MOD_ADD:
2434                         ret = replmd_modify_la_add(module, schema, msg, el, old_el, schema_attr, seq_num, t, &old_guid, parent);
2435                         break;
2436                 default:
2437                         ldb_asprintf_errstring(ldb,
2438                                                "invalid flags 0x%x for %s linked attribute",
2439                                                el->flags, el->name);
2440                         return LDB_ERR_UNWILLING_TO_PERFORM;
2441                 }
2442                 if (dsdb_check_single_valued_link(schema_attr, el) != LDB_SUCCESS) {
2443                         ldb_asprintf_errstring(ldb,
2444                                                "Attribute %s is single valued but more than one value has been supplied",
2445                                                el->name);
2446                         return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
2447                 } else {
2448                         el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
2449                 }
2450
2451
2452
2453                 if (ret != LDB_SUCCESS) {
2454                         return ret;
2455                 }
2456                 if (old_el) {
2457                         ldb_msg_remove_attr(old_msg, el->name);
2458                 }
2459                 ldb_msg_add_empty(old_msg, el->name, 0, &new_el);
2460                 new_el->num_values = el->num_values;
2461                 new_el->values = talloc_steal(msg->elements, el->values);
2462
2463                 /* TODO: this relises a bit too heavily on the exact
2464                    behaviour of ldb_msg_find_element and
2465                    ldb_msg_remove_element */
2466                 old_el = ldb_msg_find_element(msg, el->name);
2467                 if (old_el != el) {
2468                         ldb_msg_remove_element(msg, old_el);
2469                         i--;
2470                 }
2471         }
2472
2473         talloc_free(res);
2474         return ret;
2475 }
2476
2477
2478
2479 static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
2480 {
2481         struct samldb_msds_intid_persistant *msds_intid_struct;
2482         struct ldb_context *ldb;
2483         struct replmd_replicated_request *ac;
2484         struct ldb_request *down_req;
2485         struct ldb_message *msg;
2486         time_t t = time(NULL);
2487         int ret;
2488         bool is_urgent = false, rodc = false;
2489         unsigned int functional_level;
2490         const struct ldb_message_element *guid_el = NULL;
2491         struct ldb_control *sd_propagation_control;
2492         struct replmd_private *replmd_private =
2493                 talloc_get_type(ldb_module_get_private(module), struct replmd_private);
2494
2495         /* do not manipulate our control entries */
2496         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2497                 return ldb_next_request(module, req);
2498         }
2499
2500         sd_propagation_control = ldb_request_get_control(req,
2501                                         DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
2502         if (sd_propagation_control != NULL) {
2503                 if (req->op.mod.message->num_elements != 1) {
2504                         return ldb_module_operr(module);
2505                 }
2506                 ret = strcmp(req->op.mod.message->elements[0].name,
2507                              "nTSecurityDescriptor");
2508                 if (ret != 0) {
2509                         return ldb_module_operr(module);
2510                 }
2511
2512                 return ldb_next_request(module, req);
2513         }
2514
2515         ldb = ldb_module_get_ctx(module);
2516
2517         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_modify\n");
2518
2519         guid_el = ldb_msg_find_element(req->op.mod.message, "objectGUID");
2520         if (guid_el != NULL) {
2521                 ldb_set_errstring(ldb,
2522                                   "replmd_modify: it's not allowed to change the objectGUID!");
2523                 return LDB_ERR_CONSTRAINT_VIOLATION;
2524         }
2525
2526         ac = replmd_ctx_init(module, req);
2527         if (ac == NULL) {
2528                 return ldb_module_oom(module);
2529         }
2530
2531         functional_level = dsdb_functional_level(ldb);
2532
2533         /* we have to copy the message as the caller might have it as a const */
2534         msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
2535         if (msg == NULL) {
2536                 ldb_oom(ldb);
2537                 talloc_free(ac);
2538                 return LDB_ERR_OPERATIONS_ERROR;
2539         }
2540
2541         ldb_msg_remove_attr(msg, "whenChanged");
2542         ldb_msg_remove_attr(msg, "uSNChanged");
2543
2544         ret = replmd_update_rpmd(module, ac->schema, req, NULL,
2545                                  msg, &ac->seq_num, t, &is_urgent, &rodc);
2546         if (rodc && (ret == LDB_ERR_REFERRAL)) {
2547                 struct loadparm_context *lp_ctx;
2548                 char *referral;
2549
2550                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2551                                          struct loadparm_context);
2552
2553                 referral = talloc_asprintf(req,
2554                                            "ldap://%s/%s",
2555                                            lpcfg_dnsdomain(lp_ctx),
2556                                            ldb_dn_get_linearized(msg->dn));
2557                 ret = ldb_module_send_referral(req, referral);
2558                 talloc_free(ac);
2559                 return ret;
2560         }
2561
2562         if (ret != LDB_SUCCESS) {
2563                 talloc_free(ac);
2564                 return ret;
2565         }
2566
2567         ret = replmd_modify_handle_linked_attribs(module, msg, ac->seq_num, t, req);
2568         if (ret != LDB_SUCCESS) {
2569                 talloc_free(ac);
2570                 return ret;
2571         }
2572
2573         /* TODO:
2574          * - replace the old object with the newly constructed one
2575          */
2576
2577         ac->is_urgent = is_urgent;
2578
2579         ret = ldb_build_mod_req(&down_req, ldb, ac,
2580                                 msg,
2581                                 req->controls,
2582                                 ac, replmd_op_callback,
2583                                 req);
2584         LDB_REQ_SET_LOCATION(down_req);
2585         if (ret != LDB_SUCCESS) {
2586                 talloc_free(ac);
2587                 return ret;
2588         }
2589
2590         /* current partition control is needed by "replmd_op_callback" */
2591         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
2592                 ret = ldb_request_add_control(down_req,
2593                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
2594                                               false, NULL);
2595                 if (ret != LDB_SUCCESS) {
2596                         talloc_free(ac);
2597                         return ret;
2598                 }
2599         }
2600
2601         /* If we are in functional level 2000, then
2602          * replmd_modify_handle_linked_attribs will have done
2603          * nothing */
2604         if (functional_level == DS_DOMAIN_FUNCTION_2000) {
2605                 ret = ldb_request_add_control(down_req, DSDB_CONTROL_APPLY_LINKS, false, NULL);
2606                 if (ret != LDB_SUCCESS) {
2607                         talloc_free(ac);
2608                         return ret;
2609                 }
2610         }
2611
2612         talloc_steal(down_req, msg);
2613
2614         /* we only change whenChanged and uSNChanged if the seq_num
2615            has changed */
2616         if (ac->seq_num != 0) {
2617                 ret = add_time_element(msg, "whenChanged", t);
2618                 if (ret != LDB_SUCCESS) {
2619                         talloc_free(ac);
2620                         ldb_operr(ldb);
2621                         return ret;
2622                 }
2623
2624                 ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
2625                 if (ret != LDB_SUCCESS) {
2626                         talloc_free(ac);
2627                         ldb_operr(ldb);
2628                         return ret;
2629                 }
2630         }
2631
2632         if (!ldb_dn_compare_base(replmd_private->schema_dn, msg->dn)) {
2633                 /* Update the usn in the SAMLDB_MSDS_INTID_OPAQUE opaque */
2634                 msds_intid_struct = (struct samldb_msds_intid_persistant *) ldb_get_opaque(ldb, SAMLDB_MSDS_INTID_OPAQUE);
2635                 if (msds_intid_struct) {
2636                         msds_intid_struct->usn = ac->seq_num;
2637                 }
2638         }
2639
2640         /* go on with the call chain */
2641         return ldb_next_request(module, down_req);
2642 }
2643
2644 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares);
2645
2646 /*
2647   handle a rename request
2648
2649   On a rename we need to do an extra ldb_modify which sets the
2650   whenChanged and uSNChanged attributes.  We do this in a callback after the success.
2651  */
2652 static int replmd_rename(struct ldb_module *module, struct ldb_request *req)
2653 {
2654         struct ldb_context *ldb;
2655         struct replmd_replicated_request *ac;
2656         int ret;
2657         struct ldb_request *down_req;
2658
2659         /* do not manipulate our control entries */
2660         if (ldb_dn_is_special(req->op.mod.message->dn)) {
2661                 return ldb_next_request(module, req);
2662         }
2663
2664         ldb = ldb_module_get_ctx(module);
2665
2666         ldb_debug(ldb, LDB_DEBUG_TRACE, "replmd_rename\n");
2667
2668         ac = replmd_ctx_init(module, req);
2669         if (ac == NULL) {
2670                 return ldb_module_oom(module);
2671         }
2672
2673         ret = ldb_build_rename_req(&down_req, ldb, ac,
2674                                    ac->req->op.rename.olddn,
2675                                    ac->req->op.rename.newdn,
2676                                    ac->req->controls,
2677                                    ac, replmd_rename_callback,
2678                                    ac->req);
2679         LDB_REQ_SET_LOCATION(down_req);
2680         if (ret != LDB_SUCCESS) {
2681                 talloc_free(ac);
2682                 return ret;
2683         }
2684
2685         /* go on with the call chain */
2686         return ldb_next_request(module, down_req);
2687 }
2688
2689 /* After the rename is compleated, update the whenchanged etc */
2690 static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
2691 {
2692         struct ldb_context *ldb;
2693         struct replmd_replicated_request *ac;
2694         struct ldb_request *down_req;
2695         struct ldb_message *msg;
2696         const struct dsdb_attribute *rdn_attr;
2697         const char *rdn_name;
2698         const struct ldb_val *rdn_val;
2699         const char *attrs[5] = { NULL, };
2700         time_t t = time(NULL);
2701         int ret;
2702         bool is_urgent = false, rodc = false;
2703
2704         ac = talloc_get_type(req->context, struct replmd_replicated_request);
2705         ldb = ldb_module_get_ctx(ac->module);
2706
2707         if (ares->error != LDB_SUCCESS) {
2708                 return ldb_module_done(ac->req, ares->controls,
2709                                         ares->response, ares->error);
2710         }
2711
2712         if (ares->type != LDB_REPLY_DONE) {
2713                 ldb_set_errstring(ldb,
2714                                   "invalid ldb_reply_type in callback");
2715                 talloc_free(ares);
2716                 return ldb_module_done(ac->req, NULL, NULL,
2717                                         LDB_ERR_OPERATIONS_ERROR);
2718         }
2719
2720         /* TODO:
2721          * - replace the old object with the newly constructed one
2722          */
2723
2724         msg = ldb_msg_new(ac);
2725         if (msg == NULL) {
2726                 ldb_oom(ldb);
2727                 return LDB_ERR_OPERATIONS_ERROR;
2728         }
2729
2730         msg->dn = ac->req->op.rename.newdn;
2731
2732         rdn_name = ldb_dn_get_rdn_name(msg->dn);
2733         if (rdn_name == NULL) {
2734                 talloc_free(ares);
2735                 return ldb_module_done(ac->req, NULL, NULL,
2736                                        ldb_operr(ldb));
2737         }
2738
2739         /* normalize the rdn attribute name */
2740         rdn_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rdn_name);
2741         if (rdn_attr == NULL) {
2742                 talloc_free(ares);
2743                 return ldb_module_done(ac->req, NULL, NULL,
2744                                        ldb_operr(ldb));
2745         }
2746         rdn_name = rdn_attr->lDAPDisplayName;
2747
2748         rdn_val = ldb_dn_get_rdn_val(msg->dn);
2749         if (rdn_val == NULL) {
2750                 talloc_free(ares);
2751                 return ldb_module_done(ac->req, NULL, NULL,
2752                                        ldb_operr(ldb));
2753         }
2754
2755         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
2756                 talloc_free(ares);
2757                 return ldb_module_done(ac->req, NULL, NULL,
2758                                        ldb_oom(ldb));
2759         }
2760         if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
2761                 talloc_free(ares);
2762                 return ldb_module_done(ac->req, NULL, NULL,
2763                                        ldb_oom(ldb));
2764         }
2765         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
2766                 talloc_free(ares);
2767                 return ldb_module_done(ac->req, NULL, NULL,
2768                                        ldb_oom(ldb));
2769         }
2770         if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
2771                 talloc_free(ares);
2772                 return ldb_module_done(ac->req, NULL, NULL,
2773                                        ldb_oom(ldb));
2774         }
2775
2776         /*
2777          * here we let replmd_update_rpmd() only search for
2778          * the existing "replPropertyMetaData" and rdn_name attributes.
2779          *
2780          * We do not want the existing "name" attribute as
2781          * the "name" attribute needs to get the version
2782          * updated on rename even if the rdn value hasn't changed.
2783          *
2784          * This is the diff of the meta data, for a moved user
2785          * on a w2k8r2 server:
2786          *
2787          * # record 1
2788          * -dn: CN=sdf df,CN=Users,DC=bla,DC=base
2789          * +dn: CN=sdf df,OU=TestOU,DC=bla,DC=base
2790          *  replPropertyMetaData:     NDR: struct replPropertyMetaDataBlob
2791          *         version                  : 0x00000001 (1)
2792          *         reserved                 : 0x00000000 (0)
2793          * @@ -66,11 +66,11 @@ replPropertyMetaData:     NDR: struct re
2794          *                      local_usn                : 0x00000000000037a5 (14245)
2795          *                 array: struct replPropertyMetaData1
2796          *                      attid                    : DRSUAPI_ATTID_name (0x90001)
2797          * -                    version                  : 0x00000001 (1)
2798          * -                    originating_change_time  : Wed Feb  9 17:20:49 2011 CET
2799          * +                    version                  : 0x00000002 (2)
2800          * +                    originating_change_time  : Wed Apr  6 15:21:01 2011 CEST
2801          *                      originating_invocation_id: 0d36ca05-5507-4e62-aca3-354bab0d39e1
2802          * -                    originating_usn          : 0x00000000000037a5 (14245)
2803          * -                    local_usn                : 0x00000000000037a5 (14245)
2804          * +                    originating_usn          : 0x0000000000003834 (14388)
2805          * +                    local_usn                : 0x0000000000003834 (14388)
2806          *                 array: struct replPropertyMetaData1
2807          *                      attid                    : DRSUAPI_ATTID_userAccountControl (0x90008)
2808          *                      version                  : 0x00000004 (4)
2809          */
2810         attrs[0] = "replPropertyMetaData";
2811         attrs[1] = "objectClass";
2812         attrs[2] = "instanceType";
2813         attrs[3] = rdn_name;
2814         attrs[4] = NULL;
2815
2816         ret = replmd_update_rpmd(ac->module, ac->schema, req, attrs,
2817                                  msg, &ac->seq_num, t, &is_urgent, &rodc);
2818         if (rodc && (ret == LDB_ERR_REFERRAL)) {
2819                 struct ldb_dn *olddn = ac->req->op.rename.olddn;
2820                 struct loadparm_context *lp_ctx;
2821                 char *referral;
2822
2823                 lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
2824                                          struct loadparm_context);
2825
2826                 referral = talloc_asprintf(req,
2827                                            "ldap://%s/%s",
2828                                            lpcfg_dnsdomain(lp_ctx),
2829                                            ldb_dn_get_linearized(olddn));
2830                 ret = ldb_module_send_referral(req, referral);
2831                 talloc_free(ares);
2832                 return ldb_module_done(req, NULL, NULL, ret);
2833         }
2834
2835         if (ret != LDB_SUCCESS) {
2836                 talloc_free(ares);
2837                 return ldb_module_done(ac->req, NULL, NULL, ret);
2838         }
2839
2840         if (ac->seq_num == 0) {
2841                 talloc_free(ares);
2842                 return ldb_module_done(ac->req, NULL, NULL,
2843                                        ldb_error(ldb, ret,
2844                                         "internal error seq_num == 0"));
2845         }
2846         ac->is_urgent = is_urgent;
2847
2848         ret = ldb_build_mod_req(&down_req, ldb, ac,
2849                                 msg,
2850                                 req->controls,
2851                                 ac, replmd_op_callback,
2852                                 req);
2853         LDB_REQ_SET_LOCATION(down_req);
2854         if (ret != LDB_SUCCESS) {
2855                 talloc_free(ac);
2856                 return ret;
2857         }
2858
2859         /* current partition control is needed by "replmd_op_callback" */
2860         if (ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID) == NULL) {
2861                 ret = ldb_request_add_control(down_req,
2862                                               DSDB_CONTROL_CURRENT_PARTITION_OID,
2863                                               false, NULL);
2864                 if (ret != LDB_SUCCESS) {
2865                         talloc_free(ac);
2866                         return ret;
2867                 }
2868         }
2869
2870         talloc_steal(down_req, msg);
2871
2872         ret = add_time_element(msg, "whenChanged", t);
2873         if (ret != LDB_SUCCESS) {
2874                 talloc_free(ac);
2875                 ldb_operr(ldb);
2876                 return ret;
2877         }
2878
2879         ret = add_uint64_element(ldb, msg, "uSNChanged", ac->seq_num);
2880         if (ret != LDB_SUCCESS) {
2881                 talloc_free(ac);
2882                 ldb_operr(ldb);
2883                 return ret;
2884         }
2885
2886         /* go on with the call chain - do the modify after the rename */
2887         return ldb_next_request(ac->module, down_req);
2888 }
2889
2890 /*
2891  * remove links from objects that point at this object when an object
2892  * is deleted.  We remove it from the NEXT module per MS-DRSR 5.160
2893  * RemoveObj which states that link removal due to the object being
2894  * deleted is NOT an originating update - they just go away!
2895  *
2896  */
2897 static int replmd_delete_remove_link(struct ldb_module *module,
2898                                      const struct dsdb_schema *schema,
2899                                      struct ldb_dn *dn,
2900                                      struct ldb_message_element *el,
2901                                      const struct dsdb_attribute *sa,
2902                                      struct ldb_request *parent)
2903 {
2904         unsigned int i;
2905         TALLOC_CTX *tmp_ctx = talloc_new(module);
2906         struct ldb_context *ldb = ldb_module_get_ctx(module);
2907
2908         for (i=0; i<el->num_values; i++) {
2909                 struct dsdb_dn *dsdb_dn;
2910                 NTSTATUS status;
2911                 int ret;
2912                 struct GUID guid2;
2913                 struct ldb_message *msg;
2914                 const struct dsdb_attribute *target_attr;
2915                 struct ldb_message_element *el2;
2916                 struct ldb_val dn_val;
2917
2918                 if (dsdb_dn_is_deleted_val(&el->values[i])) {
2919                         continue;
2920                 }
2921
2922                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], sa->syntax->ldap_oid);
2923                 if (!dsdb_dn) {
2924                         talloc_free(tmp_ctx);
2925                         return LDB_ERR_OPERATIONS_ERROR;
2926                 }
2927
2928                 status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid2, "GUID");
2929                 if (!NT_STATUS_IS_OK(status)) {
2930                         talloc_free(tmp_ctx);
2931                         return LDB_ERR_OPERATIONS_ERROR;
2932                 }
2933
2934                 /* remove the link */
2935                 msg = ldb_msg_new(tmp_ctx);
2936                 if (!msg) {
2937                         ldb_module_oom(module);
2938                         talloc_free(tmp_ctx);
2939                         return LDB_ERR_OPERATIONS_ERROR;
2940                 }
2941
2942
2943                 msg->dn = dsdb_dn->dn;
2944
2945                 target_attr = dsdb_attribute_by_linkID(schema, sa->linkID ^ 1);
2946                 if (target_attr == NULL) {
2947                         continue;
2948                 }
2949
2950                 ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName, LDB_FLAG_MOD_DELETE, &el2);
2951                 if (ret != LDB_SUCCESS) {
2952                         ldb_module_oom(module);
2953                         talloc_free(tmp_ctx);
2954                         return LDB_ERR_OPERATIONS_ERROR;
2955                 }
2956                 dn_val = data_blob_string_const(ldb_dn_get_linearized(dn));
2957                 el2->values = &dn_val;
2958                 el2->num_values = 1;
2959
2960                 ret = dsdb_module_modify(module, msg, DSDB_FLAG_OWN_MODULE, parent);
2961                 if (ret != LDB_SUCCESS) {
2962                         talloc_free(tmp_ctx);
2963                         return ret;
2964                 }
2965         }
2966         talloc_free(tmp_ctx);
2967         return LDB_SUCCESS;
2968 }
2969
2970
2971 /*
2972   handle update of replication meta data for deletion of objects
2973
2974   This also handles the mapping of delete to a rename operation
2975   to allow deletes to be replicated.
2976
2977   It also handles the incoming deleted objects, to ensure they are
2978   fully deleted here.  In that case re_delete is true, and we do not
2979   use this as a signal to change the deleted state, just reinforce it.
2980
2981  */
2982 static int replmd_delete_internals(struct ldb_module *module, struct ldb_request *req, bool re_delete)
2983 {
2984         int ret = LDB_ERR_OTHER;
2985         bool retb, disallow_move_on_delete;
2986         struct ldb_dn *old_dn, *new_dn;
2987         const char *rdn_name;
2988         const struct ldb_val *rdn_value, *new_rdn_value;
2989         struct GUID guid;
2990         struct ldb_context *ldb = ldb_module_get_ctx(module);
2991         const struct dsdb_schema *schema;
2992         struct ldb_message *msg, *old_msg;
2993         struct ldb_message_element *el;
2994         TALLOC_CTX *tmp_ctx;
2995         struct ldb_result *res, *parent_res;
2996         const char *preserved_attrs[] = {
2997                 /* yes, this really is a hard coded list. See MS-ADTS
2998                    section 3.1.1.5.5.1.1 */
2999                 "nTSecurityDescriptor", "attributeID", "attributeSyntax", "dNReferenceUpdate", "dNSHostName",
3000                 "flatName", "governsID", "groupType", "instanceType", "lDAPDisplayName", "legacyExchangeDN",
3001                 "isDeleted", "isRecycled", "lastKnownParent", "msDS-LastKnownRDN", "mS-DS-CreatorSID",
3002                 "mSMQOwnerID", "nCName", "objectClass", "distinguishedName", "objectGUID", "objectSid",
3003                 "oMSyntax", "proxiedObjectName", "name", "replPropertyMetaData", "sAMAccountName",
3004                 "securityIdentifier", "sIDHistory", "subClassOf", "systemFlags", "trustPartner", "trustDirection",
3005                 "trustType", "trustAttributes", "userAccountControl", "uSNChanged", "uSNCreated", "whenCreated",
3006                 "whenChanged", NULL};
3007         unsigned int i, el_count = 0;
3008         enum deletion_state deletion_state, next_deletion_state;
3009
3010         if (ldb_dn_is_special(req->op.del.dn)) {
3011                 return ldb_next_request(module, req);
3012         }
3013
3014         /*
3015          * We have to allow dbcheck to remove an object that
3016          * is beyond repair, and to do so totally.  This could
3017          * mean we we can get a partial object from the other
3018          * DC, causing havoc, so dbcheck suggests
3019          * re-replication first.  dbcheck sets both DBCHECK
3020          * and RELAX in this situation.
3021          */
3022         if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)
3023             && ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
3024                 /* really, really remove it */
3025                 return ldb_next_request(module, req);
3026         }
3027
3028         tmp_ctx = talloc_new(ldb);
3029         if (!tmp_ctx) {
3030                 ldb_oom(ldb);
3031                 return LDB_ERR_OPERATIONS_ERROR;
3032         }
3033
3034         schema = dsdb_get_schema(ldb, tmp_ctx);
3035         if (!schema) {
3036                 talloc_free(tmp_ctx);
3037                 return LDB_ERR_OPERATIONS_ERROR;
3038         }
3039
3040         old_dn = ldb_dn_copy(tmp_ctx, req->op.del.dn);
3041
3042         /* we need the complete msg off disk, so we can work out which
3043            attributes need to be removed */
3044         ret = dsdb_module_search_dn(module, tmp_ctx, &res, old_dn, NULL,
3045                                     DSDB_FLAG_NEXT_MODULE |
3046                                     DSDB_SEARCH_SHOW_RECYCLED |
3047                                     DSDB_SEARCH_REVEAL_INTERNALS |
3048                                     DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, req);
3049         if (ret != LDB_SUCCESS) {
3050                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
3051                                        "repmd_delete: Failed to %s %s, because we failed to find it: %s",
3052                                        re_delete ? "re-delete" : "delete",
3053                                        ldb_dn_get_linearized(old_dn),
3054                                        ldb_errstring(ldb_module_get_ctx(module)));
3055                 talloc_free(tmp_ctx);
3056                 return ret;
3057         }
3058         old_msg = res->msgs[0];
3059
3060         replmd_deletion_state(module, old_msg,
3061                               &deletion_state,
3062                               &next_deletion_state);
3063
3064         /* This supports us noticing an incoming isDeleted and acting on it */
3065         if (re_delete) {
3066                 SMB_ASSERT(deletion_state > OBJECT_NOT_DELETED);
3067                 next_deletion_state = deletion_state;
3068         }
3069
3070         if (next_deletion_state == OBJECT_REMOVED) {
3071                 /*
3072                  * We have to prevent objects being deleted, even if
3073                  * the administrator really wants them gone, as
3074                  * without the tombstone, we can get a partial object
3075                  * from the other DC, causing havoc.
3076                  *
3077                  * The only other valid case is when the 180 day
3078                  * timeout has expired, when relax is specified.
3079                  */
3080                 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
3081                         /* it is already deleted - really remove it this time */
3082                         talloc_free(tmp_ctx);
3083                         return ldb_next_request(module, req);
3084                 }
3085
3086                 ldb_asprintf_errstring(ldb, "Refusing to delete tombstone object %s.  "
3087                                        "This check is to prevent corruption of the replicated state.",
3088                                        ldb_dn_get_linearized(old_msg->dn));
3089                 return LDB_ERR_UNWILLING_TO_PERFORM;
3090         }
3091
3092         rdn_name = ldb_dn_get_rdn_name(old_dn);
3093         rdn_value = ldb_dn_get_rdn_val(old_dn);
3094         if ((rdn_name == NULL) || (rdn_value == NULL)) {
3095                 talloc_free(tmp_ctx);
3096                 return ldb_operr(ldb);
3097         }
3098
3099         msg = ldb_msg_new(tmp_ctx);
3100         if (msg == NULL) {
3101                 ldb_module_oom(module);
3102                 talloc_free(tmp_ctx);
3103                 return LDB_ERR_OPERATIONS_ERROR;
3104         }
3105
3106         msg->dn = old_dn;
3107
3108         /* consider the SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE flag */
3109         disallow_move_on_delete =
3110                 (ldb_msg_find_attr_as_int(old_msg, "systemFlags", 0)
3111                  & SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETE);
3112
3113         /* work out where we will be renaming this object to */
3114         if (!disallow_move_on_delete) {
3115                 struct ldb_dn *deleted_objects_dn;
3116                 ret = dsdb_get_deleted_objects_dn(ldb, tmp_ctx, old_dn,
3117                                                   &deleted_objects_dn);
3118
3119                 /*
3120                  * We should not move objects if we can't find the
3121                  * deleted objects DN.  Not moving (or otherwise
3122                  * harming) the Deleted Objects DN itself is handled
3123                  * in the caller.
3124                  */
3125                 if (re_delete && (ret != LDB_SUCCESS)) {
3126                         new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
3127                         if (new_dn == NULL) {
3128                                 ldb_module_oom(module);
3129                                 talloc_free(tmp_ctx);
3130                                 return LDB_ERR_OPERATIONS_ERROR;
3131                         }
3132                 } else if (ret != LDB_SUCCESS) {
3133                         /* this is probably an attempted delete on a partition
3134                          * that doesn't allow delete operations, such as the
3135                          * schema partition */
3136                         ldb_asprintf_errstring(ldb, "No Deleted Objects container for DN %s",
3137                                                ldb_dn_get_linearized(old_dn));
3138                         talloc_free(tmp_ctx);
3139                         return LDB_ERR_UNWILLING_TO_PERFORM;
3140                 } else {
3141                         new_dn = deleted_objects_dn;
3142                 }
3143         } else {
3144                 new_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
3145                 if (new_dn == NULL) {
3146                         ldb_module_oom(module);
3147                         talloc_free(tmp_ctx);
3148                         return LDB_ERR_OPERATIONS_ERROR;
3149                 }
3150         }
3151
3152         if (deletion_state == OBJECT_NOT_DELETED) {
3153                 /* get the objects GUID from the search we just did */
3154                 guid = samdb_result_guid(old_msg, "objectGUID");
3155
3156                 /* Add a formatted child */
3157                 retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s",
3158                                             rdn_name,
3159                                             ldb_dn_escape_value(tmp_ctx, *rdn_value),
3160                                             GUID_string(tmp_ctx, &guid));
3161                 if (!retb) {
3162                         ldb_asprintf_errstring(ldb, __location__
3163                                                ": Unable to add a formatted child to dn: %s",
3164                                                ldb_dn_get_linearized(new_dn));
3165                         talloc_free(tmp_ctx);
3166                         return LDB_ERR_OPERATIONS_ERROR;
3167                 }
3168
3169                 ret = ldb_msg_add_string(msg, "isDeleted", "TRUE");
3170                 if (ret != LDB_SUCCESS) {
3171                         ldb_asprintf_errstring(ldb, __location__
3172                                                ": Failed to add isDeleted string to the msg");
3173                         talloc_free(tmp_ctx);
3174                         return ret;
3175                 }
3176                 msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
3177         } else {
3178                 /*
3179                  * No matter what has happened with other renames etc, try again to
3180                  * get this to be under the deleted DN. See MS-DRSR 5.160 RemoveObj
3181                  */
3182
3183                 struct ldb_dn *rdn = ldb_dn_copy(tmp_ctx, old_dn);
3184                 retb = ldb_dn_remove_base_components(rdn, ldb_dn_get_comp_num(rdn) - 1);
3185                 if (!retb) {
3186                         ldb_asprintf_errstring(ldb, __location__
3187                                                ": Unable to add a prepare rdn of %s",
3188                                                ldb_dn_get_linearized(rdn));
3189                         talloc_free(tmp_ctx);
3190                         return LDB_ERR_OPERATIONS_ERROR;
3191                 }
3192                 SMB_ASSERT(ldb_dn_get_comp_num(rdn) == 1);
3193
3194                 retb = ldb_dn_add_child(new_dn, rdn);
3195                 if (!retb) {
3196                         ldb_asprintf_errstring(ldb, __location__
3197                                                ": Unable to add rdn %s to base dn: %s",
3198                                                ldb_dn_get_linearized(rdn),
3199                                                ldb_dn_get_linearized(new_dn));
3200                         talloc_free(tmp_ctx);
3201                         return LDB_ERR_OPERATIONS_ERROR;
3202                 }
3203         }
3204
3205         /*
3206           now we need to modify the object in the following ways:
3207
3208           - add isDeleted=TRUE
3209           - update rDN and name, with new rDN
3210           - remove linked attributes
3211           - remove objectCategory and sAMAccountType
3212           - remove attribs not on the preserved list
3213              - preserved if in above list, or is rDN
3214           - remove all linked attribs from this object
3215           - remove all links from other objects to this object
3216           - add lastKnownParent
3217           - update replPropertyMetaData?
3218
3219           see MS-ADTS "Tombstone Requirements" section 3.1.1.5.5.1.1
3220          */
3221
3222         if (deletion_state == OBJECT_NOT_DELETED) {
3223                 struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
3224                 char *parent_dn_str = NULL;
3225
3226                 /* we need the storage form of the parent GUID */
3227                 ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
3228                                             parent_dn, NULL,
3229                                             DSDB_FLAG_NEXT_MODULE |
3230                                             DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
3231                                             DSDB_SEARCH_REVEAL_INTERNALS|
3232                                             DSDB_SEARCH_SHOW_RECYCLED, req);
3233                 if (ret != LDB_SUCCESS) {
3234                         ldb_asprintf_errstring(ldb_module_get_ctx(module),
3235                                                "repmd_delete: Failed to %s %s, "
3236                                                "because we failed to find it's parent (%s): %s",
3237                                                re_delete ? "re-delete" : "delete",
3238                                                ldb_dn_get_linearized(old_dn),
3239                                                ldb_dn_get_linearized(parent_dn),
3240                                                ldb_errstring(ldb_module_get_ctx(module)));
3241                         talloc_free(tmp_ctx);
3242                         return ret;
3243                 }
3244
3245                 /*
3246                  * Now we can use the DB version,
3247                  * it will have the extended DN info in it
3248                  */
3249                 parent_dn = parent_res->msgs[0]->dn;
3250                 parent_dn_str = ldb_dn_get_extended_linearized(tmp_ctx,
3251                                                                parent_dn,
3252                                                                1);
3253                 if (parent_dn_str == NULL) {
3254                         talloc_free(tmp_ctx);
3255              &nb