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