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