lib/util: remove extra safe_string.h file
[bbaumbach/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / linked_attributes.c
1 /*
2    ldb database library
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
5    Copyright (C) Simo Sorce <idra@samba.org> 2008
6    Copyright (C) Matthieu Patou <mat@matws.net> 2011
7    Copyright (C) Andrew Tridgell 2009
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  *  Name: ldb
25  *
26  *  Component: ldb linked_attributes module
27  *
28  *  Description: Module to ensure linked attribute pairs (i.e. forward-links
29  *  and backlinks) remain in sync.
30  *
31  *  Backlinks are 'plain' links (without extra metadata). When the link target
32  *  object is modified (e.g. renamed), we use the backlinks to keep the link
33  *  source object updated. Note there are some cases where we can't do this:
34  *    - one-way links, which don't have a corresponding backlink
35  *    - two-way deactivated links, i.e. when a user is removed from a group,
36  *      the forward 'member' link still exists (but is inactive), however, the
37  *      'memberOf' backlink is deleted.
38  *  In these cases, we can end up with a dangling forward link which is
39  *  incorrect (i.e. the target has been renamed or deleted). We have dbcheck
40  *  rules to detect and fix this, and cope otherwise by filtering at runtime
41  *  (i.e. in the extended_dn module).
42  *
43  *  See also repl_meta_data.c, which handles updating links for deleted
44  *  objects, as well as link changes received from another DC.
45  *
46  *  Author: Andrew Bartlett
47  */
48
49 #include "includes.h"
50 #include "ldb_module.h"
51 #include "util/dlinklist.h"
52 #include "dsdb/samdb/samdb.h"
53 #include "librpc/gen_ndr/ndr_misc.h"
54 #include "dsdb/samdb/ldb_modules/util.h"
55
56 #undef strcasecmp
57
58 struct la_private_transaction {
59         struct la_context *la_list;
60 };
61
62
63 struct la_private {
64         struct la_private_transaction *transaction;
65         bool sorted_links;
66 };
67
68 struct la_op_store {
69         struct la_op_store *next;
70         struct la_op_store *prev;
71         enum la_op {LA_OP_ADD, LA_OP_DEL} op;
72         struct GUID guid;
73         char *name;
74 };
75
76 struct replace_context {
77         struct la_context *ac;
78         unsigned int num_elements;
79         struct ldb_message_element *el;
80 };
81
82 struct la_context {
83         struct la_context *next, *prev;
84         const struct dsdb_schema *schema;
85         struct ldb_module *module;
86         struct ldb_request *req;
87         struct ldb_dn *mod_dn;
88         struct replace_context *rc;
89         struct la_op_store *ops;
90         struct ldb_extended *op_response;
91         struct ldb_control **op_controls;
92         /*
93          * For futur use
94          * will tell which GC to use for resolving links
95          */
96         char *gc_dns_name;
97 };
98
99
100 static int handle_verify_name_control(TALLOC_CTX *ctx, struct ldb_context *ldb,
101                                         struct ldb_control *control, struct la_context *ac)
102 {
103         /*
104          * If we are a GC let's remove the control,
105          * if there is a specified GC check that is us.
106          */
107         struct ldb_verify_name_control *lvnc = (struct ldb_verify_name_control *)control->data;
108         if (samdb_is_gc(ldb)) {
109                 /* Because we can't easily talloc a struct ldb_dn*/
110                 struct ldb_dn **dn = talloc_array(ctx, struct ldb_dn *, 1);
111                 int ret = samdb_server_reference_dn(ldb, ctx, dn);
112                 const char *dns;
113
114                 if (ret != LDB_SUCCESS) {
115                         return ldb_operr(ldb);
116                 }
117
118                 dns = samdb_dn_to_dnshostname(ldb, ctx, *dn);
119                 if (!dns) {
120                         return ldb_operr(ldb);
121                 }
122                 if (!lvnc->gc || strcasecmp(dns, lvnc->gc) == 0) {
123                         if (!ldb_save_controls(control, ctx, NULL)) {
124                                 return ldb_operr(ldb);
125                         }
126                 } else {
127                         control->critical = true;
128                 }
129                 talloc_free(dn);
130         } else {
131                 /* For the moment we don't remove the control is this case in order
132                  * to fail the request. It's better than having the client thinking
133                  * that we honnor its control.
134                  * Hopefully only a very small set of usecase should hit this problem.
135                  */
136                 if (lvnc->gc) {
137                         ac->gc_dns_name = talloc_strdup(ac, lvnc->gc);
138                 }
139                 control->critical = true;
140         }
141
142         return LDB_SUCCESS;
143 }
144
145 static struct la_context *linked_attributes_init(struct ldb_module *module,
146                                                  struct ldb_request *req)
147 {
148         struct ldb_context *ldb;
149         struct la_context *ac;
150
151         ldb = ldb_module_get_ctx(module);
152
153         ac = talloc_zero(req, struct la_context);
154         if (ac == NULL) {
155                 ldb_oom(ldb);
156                 return NULL;
157         }
158
159         ac->schema = dsdb_get_schema(ldb, ac);
160         ac->module = module;
161         ac->req = req;
162
163         return ac;
164 }
165
166 /*
167   turn a DN into a GUID
168  */
169 static int la_guid_from_dn(struct ldb_module *module,
170                            struct ldb_request *parent,
171                            struct ldb_dn *dn, struct GUID *guid)
172 {
173         NTSTATUS status;
174         int ret;
175
176         status = dsdb_get_extended_dn_guid(dn, guid, "GUID");
177         if (NT_STATUS_IS_OK(status)) {
178                 return LDB_SUCCESS;
179         }
180         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
181                 DEBUG(4,(__location__ ": Unable to parse GUID for dn %s\n",
182                          ldb_dn_get_linearized(dn)));
183                 return ldb_operr(ldb_module_get_ctx(module));
184         }
185
186         ret = dsdb_module_guid_by_dn(module, dn, guid, parent);
187         if (ret != LDB_SUCCESS) {
188                 DEBUG(4,(__location__ ": Failed to find GUID for dn %s\n",
189                          ldb_dn_get_linearized(dn)));
190                 return ret;
191         }
192         return LDB_SUCCESS;
193 }
194
195
196 /* Common routine to handle reading the attributes and creating a
197  * series of modify requests */
198 static int la_store_op(struct la_context *ac,
199                        enum la_op op, 
200                        const struct dsdb_attribute *schema_attr,
201                        struct ldb_val *dn,
202                        const char *name)
203 {
204         struct ldb_context *ldb;
205         struct la_op_store *os;
206         struct ldb_dn *op_dn;
207         struct dsdb_dn *dsdb_dn;
208         int ret;
209
210         ldb = ldb_module_get_ctx(ac->module);
211
212
213         os = talloc_zero(ac, struct la_op_store);
214         if (!os) {
215                 return ldb_oom(ldb);
216         }
217
218         dsdb_dn = dsdb_dn_parse(os, ldb, dn, schema_attr->syntax->ldap_oid);
219
220         if (!dsdb_dn) {
221                 ldb_asprintf_errstring(ldb,
222                                        "could not parse attribute as a DN");
223                 TALLOC_FREE(os);
224                 return LDB_ERR_INVALID_DN_SYNTAX;
225         }
226
227         op_dn = dsdb_dn->dn;
228
229         os->op = op;
230
231         ret = la_guid_from_dn(ac->module, ac->req, op_dn, &os->guid);
232         talloc_free(op_dn);
233         if (ret == LDB_ERR_NO_SUCH_OBJECT && ac->req->operation == LDB_DELETE) {
234                 /* we are deleting an object, and we've found it has a
235                  * forward link to a target that no longer
236                  * exists. This is not an error in the delete, and we
237                  * should just not do the deferred delete of the
238                  * target attribute
239                  */
240                 talloc_free(os);
241                 return LDB_SUCCESS;
242         }
243         if (ret != LDB_SUCCESS) {
244                 return ret;
245         }
246
247         os->name = talloc_strdup(os, name);
248         if (!os->name) {
249                 return ldb_oom(ldb);
250         }
251
252         /* Do deletes before adds */
253         if (op == LA_OP_ADD) {
254                 DLIST_ADD_END(ac->ops, os);
255         } else {
256                 /* By adding to the head of the list, we do deletes before
257                  * adds when processing a replace */
258                 DLIST_ADD(ac->ops, os);
259         }
260
261         return LDB_SUCCESS;
262 }
263
264 static int la_queue_mod_request(struct la_context *ac);
265 static int la_down_req(struct la_context *ac);
266
267
268
269 /* add */
270 static int linked_attributes_add(struct ldb_module *module, struct ldb_request *req)
271 {
272         struct ldb_context *ldb;
273         const struct dsdb_attribute *target_attr;
274         struct la_context *ac;
275         const char *attr_name;
276         struct ldb_control *ctrl;
277         unsigned int i, j;
278         struct ldb_control *control;
279         int ret;
280
281         ldb = ldb_module_get_ctx(module);
282
283         if (ldb_dn_is_special(req->op.add.message->dn)) {
284                 /* do not manipulate our control entries */
285                 return ldb_next_request(module, req);
286         }
287
288         ac = linked_attributes_init(module, req);
289         if (!ac) {
290                 return ldb_operr(ldb);
291         }
292
293         control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID);
294         if (control != NULL && control->data != NULL) {
295                 ret = handle_verify_name_control(req, ldb, control, ac);
296                 if (ret != LDB_SUCCESS) {
297                         return ldb_operr(ldb);
298                 }
299         }
300
301         if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {
302                 /* don't do anything special for linked attributes, repl_meta_data has done it */
303                 talloc_free(ac);
304                 return ldb_next_request(module, req);
305         }
306         ctrl->critical = false;
307
308         if (!ac->schema) {
309                 /* without schema, this doesn't make any sense */
310                 talloc_free(ac);
311                 return ldb_next_request(module, req);
312         }
313
314
315         /* Need to ensure we only have forward links being specified */
316         for (i=0; i < req->op.add.message->num_elements; i++) {
317                 const struct ldb_message_element *el = &req->op.add.message->elements[i];
318                 const struct dsdb_attribute *schema_attr
319                         = dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name);
320                 if (!schema_attr) {
321                         ldb_asprintf_errstring(ldb,
322                                                "%s: attribute %s is not a valid attribute in schema",
323                                                __FUNCTION__,
324                                                el->name);
325                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
326                 }
327
328                 /* this could be a link with no partner, in which case
329                    there is no special work to do */
330                 if (schema_attr->linkID == 0) {
331                         continue;
332                 }
333
334                 /* this part of the code should only be handling forward links */
335                 SMB_ASSERT((schema_attr->linkID & 1) == 0);
336
337                 /* Even link IDs are for the originating attribute */
338                 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1);
339                 if (!target_attr) {
340                         /*
341                          * windows 2003 has a broken schema where
342                          * the definition of msDS-IsDomainFor
343                          * is missing (which is supposed to be
344                          * the backlink of the msDS-HasDomainNCs
345                          * attribute
346                          */
347                         continue;
348                 }
349
350                 attr_name = target_attr->lDAPDisplayName;
351
352                 for (j = 0; j < el->num_values; j++) {
353                         ret = la_store_op(ac, LA_OP_ADD,
354                                           schema_attr,
355                                           &el->values[j],
356                                           attr_name);
357                         if (ret != LDB_SUCCESS) {
358                                 return ret;
359                         }
360                 }
361         }
362
363         /* if no linked attributes are present continue */
364         if (ac->ops == NULL) {
365                 /* nothing to do for this module, proceed */
366                 talloc_free(ac);
367                 return ldb_next_request(module, req);
368         }
369
370         /* start with the original request */
371         return la_down_req(ac);
372 }
373
374 /* For a delete or rename, we need to find out what linked attributes
375  * are currently on this DN, and then deal with them.  This is the
376  * callback to the base search */
377
378 static int la_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
379 {
380         struct ldb_context *ldb;
381         const struct dsdb_attribute *schema_attr;
382         const struct dsdb_attribute *target_attr;
383         struct ldb_message_element *search_el;
384         struct replace_context *rc;
385         struct la_context *ac;
386         const char *attr_name;
387         unsigned int i, j;
388         int ret = LDB_SUCCESS;
389
390         ac = talloc_get_type(req->context, struct la_context);
391         ldb = ldb_module_get_ctx(ac->module);
392         rc = ac->rc;
393
394         if (!ares) {
395                 return ldb_module_done(ac->req, NULL, NULL,
396                                         LDB_ERR_OPERATIONS_ERROR);
397         }
398         if (ares->error != LDB_SUCCESS) {
399                 return ldb_module_done(ac->req, ares->controls,
400                                         ares->response, ares->error);
401         }
402
403         /* Only entries are interesting, and we only want the olddn */
404         switch (ares->type) {
405         case LDB_REPLY_ENTRY:
406
407                 if (ldb_dn_compare(ares->message->dn, ac->req->op.mod.message->dn) != 0) {
408                         ldb_asprintf_errstring(ldb,
409                                                "linked_attributes: %s is not the DN we were looking for",
410                                                ldb_dn_get_linearized(ares->message->dn));
411                         /* Guh?  We only asked for this DN */
412                         talloc_free(ares);
413                         return ldb_module_done(ac->req, NULL, NULL,
414                                                 LDB_ERR_OPERATIONS_ERROR);
415                 }
416
417                 ac->mod_dn = talloc_steal(ac, ares->message->dn);
418
419                 /* We don't populate 'rc' for ADD - it can't be deleting elements anyway */
420                 for (i = 0; rc && i < rc->num_elements; i++) {
421
422                         schema_attr = dsdb_attribute_by_lDAPDisplayName(ac->schema, rc->el[i].name);
423                         if (!schema_attr) {
424                                 ldb_asprintf_errstring(ldb,
425                                         "%s: attribute %s is not a valid attribute in schema",
426                                         __FUNCTION__,
427                                         rc->el[i].name);
428                                 talloc_free(ares);
429                                 return ldb_module_done(ac->req, NULL, NULL,
430                                                 LDB_ERR_OBJECT_CLASS_VIOLATION);
431                         }
432
433                         search_el = ldb_msg_find_element(ares->message,
434                                                          rc->el[i].name);
435
436                         /* See if this element already exists */
437                         /* otherwise just ignore as
438                          * the add has already been scheduled */
439                         if ( ! search_el) {
440                                 continue;
441                         }
442
443                         target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1);
444                         if (!target_attr) {
445                                 /*
446                                  * windows 2003 has a broken schema where
447                                  * the definition of msDS-IsDomainFor
448                                  * is missing (which is supposed to be
449                                  * the backlink of the msDS-HasDomainNCs
450                                  * attribute
451                                  */
452                                 continue;
453                         }
454                         attr_name = target_attr->lDAPDisplayName;
455
456                         /* Now we know what was there, we can remove it for the re-add */
457                         for (j = 0; j < search_el->num_values; j++) {
458                                 ret = la_store_op(ac, LA_OP_DEL,
459                                                   schema_attr, 
460                                                   &search_el->values[j],
461                                                   attr_name);
462                                 if (ret != LDB_SUCCESS) {
463                                         talloc_free(ares);
464                                         return ldb_module_done(ac->req,
465                                                                NULL, NULL, ret);
466                                 }
467                         }
468                 }
469
470                 break;
471
472         case LDB_REPLY_REFERRAL:
473                 /* ignore */
474                 break;
475
476         case LDB_REPLY_DONE:
477
478                 talloc_free(ares);
479
480                 if (ac->req->operation == LDB_ADD) {
481                         /* Start the modifies to the backlinks */
482                         ret = la_queue_mod_request(ac);
483
484                         if (ret != LDB_SUCCESS) {
485                                 return ldb_module_done(ac->req, NULL, NULL,
486                                                        ret);
487                         }
488                 } else {
489                         /* Start with the original request */
490                         ret = la_down_req(ac);
491                         if (ret != LDB_SUCCESS) {
492                                 return ldb_module_done(ac->req, NULL, NULL, ret);
493                         }
494                 }
495                 return LDB_SUCCESS;
496         }
497
498         talloc_free(ares);
499         return ret;
500 }
501
502
503 /* modify */
504 static int linked_attributes_modify(struct ldb_module *module, struct ldb_request *req)
505 {
506         /* Look over list of modifications */
507         /* Find if any are for linked attributes */
508         /* Determine the effect of the modification */
509         /* Apply the modify to the linked entry */
510
511         struct ldb_control *control;
512         struct ldb_context *ldb;
513         unsigned int i, j;
514         struct la_context *ac;
515         struct ldb_request *search_req;
516         const char **attrs;
517         struct ldb_control *ctrl;
518         int ret;
519
520         ldb = ldb_module_get_ctx(module);
521
522         if (ldb_dn_is_special(req->op.mod.message->dn)) {
523                 /* do not manipulate our control entries */
524                 return ldb_next_request(module, req);
525         }
526
527         ac = linked_attributes_init(module, req);
528         if (!ac) {
529                 return ldb_operr(ldb);
530         }
531
532         control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID);
533         if (control != NULL && control->data != NULL) {
534                 ret = handle_verify_name_control(req, ldb, control, ac);
535                 if (ret != LDB_SUCCESS) {
536                         return ldb_operr(ldb);
537                 }
538         }
539
540         if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {
541                 /* don't do anything special for linked attributes, repl_meta_data has done it */
542                 talloc_free(ac);
543                 return ldb_next_request(module, req);
544         }
545         ctrl->critical = false;
546
547         if (!ac->schema) {
548                 /* without schema, this doesn't make any sense */
549                 return ldb_next_request(module, req);
550         }
551
552         ac->rc = talloc_zero(ac, struct replace_context);
553         if (!ac->rc) {
554                 return ldb_oom(ldb);
555         }
556
557         for (i=0; i < req->op.mod.message->num_elements; i++) {
558                 bool store_el = false;
559                 const char *attr_name;
560                 const struct dsdb_attribute *target_attr;
561                 const struct ldb_message_element *el = &req->op.mod.message->elements[i];
562                 const struct dsdb_attribute *schema_attr
563                         = dsdb_attribute_by_lDAPDisplayName(ac->schema, el->name);
564                 if (!schema_attr) {
565                         ldb_asprintf_errstring(ldb,
566                                                "%s: attribute %s is not a valid attribute in schema",
567                                                __FUNCTION__,
568                                                el->name);
569                         return LDB_ERR_OBJECT_CLASS_VIOLATION;
570                 }
571                 /* We have a valid attribute, now find out if it is a forward link
572                    (Even link IDs are for the originating attribute) */
573                 if (schema_attr->linkID == 0) {
574                         continue;
575                 }
576
577                 /* this part of the code should only be handling forward links */
578                 SMB_ASSERT((schema_attr->linkID & 1) == 0);
579
580                 /* Now find the target attribute */
581                 target_attr = dsdb_attribute_by_linkID(ac->schema, schema_attr->linkID ^ 1);
582                 if (!target_attr) {
583                         /*
584                          * windows 2003 has a broken schema where
585                          * the definition of msDS-IsDomainFor
586                          * is missing (which is supposed to be
587                          * the backlink of the msDS-HasDomainNCs
588                          * attribute
589                          */
590                         continue;
591                 }
592
593                 attr_name = target_attr->lDAPDisplayName;
594
595                 switch (el->flags & LDB_FLAG_MOD_MASK) {
596                 case LDB_FLAG_MOD_REPLACE:
597                         /* treat as just a normal add the delete part is handled by the callback */
598                         store_el = true;
599
600                         FALL_THROUGH;
601                 case LDB_FLAG_MOD_ADD:
602
603                         /* For each value being added, we need to setup the adds */
604                         for (j = 0; j < el->num_values; j++) {
605                                 ret = la_store_op(ac, LA_OP_ADD,
606                                                   schema_attr,
607                                                   &el->values[j],
608                                                   attr_name);
609                                 if (ret != LDB_SUCCESS) {
610                                         return ret;
611                                 }
612                         }
613                         break;
614
615                 case LDB_FLAG_MOD_DELETE:
616
617                         if (el->num_values) {
618                                 /* For each value being deleted, we need to setup the delete */
619                                 for (j = 0; j < el->num_values; j++) {
620                                         ret = la_store_op(ac, LA_OP_DEL,
621                                                           schema_attr,
622                                                           &el->values[j],
623                                                           attr_name);
624                                         if (ret != LDB_SUCCESS) {
625                                                 return ret;
626                                         }
627                                 }
628                         } else {
629                                 /* Flag that there was a DELETE
630                                  * without a value specified, so we
631                                  * need to look for the old value */
632                                 store_el = true;
633                         }
634
635                         break;
636                 }
637
638                 if (store_el) {
639                         struct ldb_message_element *search_el;
640
641                         search_el = talloc_realloc(ac->rc, ac->rc->el,
642                                                    struct ldb_message_element,
643                                                    ac->rc->num_elements +1);
644                         if (!search_el) {
645                                 return ldb_oom(ldb);
646                         }
647                         ac->rc->el = search_el;
648
649                         ac->rc->el[ac->rc->num_elements] = *el;
650                         ac->rc->num_elements++;
651                 }
652         }
653
654         if (ac->ops || ac->rc->el) {
655                 /* both replace and delete without values are handled in the callback
656                  * after the search on the entry to be modified is performed */
657
658                 attrs = talloc_array(ac->rc, const char *, ac->rc->num_elements + 1);
659                 if (!attrs) {
660                         return ldb_oom(ldb);
661                 }
662                 for (i = 0; i < ac->rc->num_elements; i++) {
663                         attrs[i] = ac->rc->el[i].name;
664                 }
665                 attrs[i] = NULL;
666
667                 /* The callback does all the hard work here */
668                 ret = ldb_build_search_req(&search_req, ldb, ac,
669                                            req->op.mod.message->dn,
670                                            LDB_SCOPE_BASE,
671                                            "(objectClass=*)", attrs,
672                                            NULL,
673                                            ac, la_mod_search_callback,
674                                            req);
675                 LDB_REQ_SET_LOCATION(search_req);
676
677                 /* We need to figure out our own extended DN, to fill in as the backlink target */
678                 if (ret == LDB_SUCCESS) {
679                         ret = dsdb_request_add_controls(search_req,
680                                                         DSDB_SEARCH_SHOW_RECYCLED |
681                                                         DSDB_SEARCH_SHOW_EXTENDED_DN);
682                 }
683                 if (ret == LDB_SUCCESS) {
684                         talloc_steal(search_req, attrs);
685
686                         ret = ldb_next_request(module, search_req);
687                 }
688
689         } else {
690                 /* nothing to do for this module, proceed */
691                 talloc_free(ac);
692                 ret = ldb_next_request(module, req);
693         }
694
695         return ret;
696 }
697
698
699 static int linked_attributes_fix_link_slow(struct ldb_module *module,
700                                            struct ldb_request *parent,
701                                            struct ldb_message *msg,
702                                            struct ldb_dn *new_dn,
703                                            struct GUID self_guid,
704                                            const char *syntax_oid,
705                                            const char *reverse_syntax_oid)
706 {
707         int ret;
708         unsigned int i;
709         struct GUID link_guid;
710         struct ldb_message_element *el = &msg->elements[0];
711         struct ldb_context *ldb = ldb_module_get_ctx(module);
712         bool has_unique_value = strcmp(reverse_syntax_oid, LDB_SYNTAX_DN) == 0;
713         TALLOC_CTX *tmp_ctx = talloc_new(module);
714         if (tmp_ctx == NULL) {
715                 return LDB_ERR_OPERATIONS_ERROR;
716         }
717         /*
718          * The msg has one element (el) containing links of one particular
719          * type from the remote object. We know that at least one of those
720          * links points to the object being renamed (identified by self_guid,
721          * renamed to new_dn). Usually only one of the links will point back
722          * to renamed object, but there can be more when the reverse link is a
723          * DN+Binary link.
724          *
725          * This is used for unsorted links, which is to say back links and
726          * forward links on old databases. It necessarily involves a linear
727          * search, though when the link is a plain DN link, we can skip
728          * checking as soon as we find it.
729          *
730          * NOTE: if there are duplicate links, the extra ones will end up as
731          * dangling links to the old DN. This may or may not be worse than
732          * leaving them as duplicate links.
733          */
734         for (i = 0; i < el->num_values; i++) {
735                 struct dsdb_dn *dsdb_dn = dsdb_dn_parse(msg,
736                                                         ldb,
737                                                         &el->values[i],
738                                                         syntax_oid);
739                 if (dsdb_dn == NULL) {
740                         talloc_free(tmp_ctx);
741                         return LDB_ERR_INVALID_DN_SYNTAX;
742                 }
743
744                 ret = la_guid_from_dn(module, parent, dsdb_dn->dn, &link_guid);
745                 if (ret != LDB_SUCCESS) {
746                         talloc_free(tmp_ctx);
747                         return ret;
748                 }
749
750                 /*
751                  * By comparing using the GUID we ensure that even if somehow
752                  * the name has got out of sync, this rename will fix it.
753                  *
754                  * If somehow we don't have a GUID on the DN in the DB, the
755                  * la_guid_from_dn call will be more costly, but still give us
756                  * a GUID. dbcheck will fix this if run.
757                  */
758                 if (!GUID_equal(&self_guid, &link_guid)) {
759                         continue;
760                 }
761
762                 ret = ldb_dn_update_components(dsdb_dn->dn, new_dn);
763                 if (ret != LDB_SUCCESS) {
764                         talloc_free(tmp_ctx);
765                         return ret;
766                 }
767
768                 el->values[i] = data_blob_string_const(
769                         dsdb_dn_get_extended_linearized(el->values, dsdb_dn, 1));
770                 if (has_unique_value) {
771                         break;
772                 }
773         }
774
775         talloc_free(tmp_ctx);
776         return LDB_SUCCESS;
777 }
778
779
780 static int linked_attributes_fix_forward_link(struct ldb_module *module,
781                                               struct ldb_message *msg,
782                                               struct ldb_dn *new_dn,
783                                               struct GUID self_guid,
784                                               const char *syntax_oid)
785 {
786         int ret;
787         struct ldb_context *ldb = ldb_module_get_ctx(module);
788         struct parsed_dn *pdn_list = NULL;
789         struct parsed_dn *exact = NULL;
790         struct parsed_dn *next = NULL;
791         bool is_plain_dn;
792         struct ldb_message_element *el = &msg->elements[0];
793         unsigned int num_parsed_dns = el->num_values;
794
795         TALLOC_CTX *tmp_ctx = talloc_new(module);
796         if (tmp_ctx == NULL) {
797                 return LDB_ERR_OPERATIONS_ERROR;
798         }
799
800         /*
801          * The msg has a single element (el) containing forward links which we
802          * trust are sorted in GUID order. We know that at least one of those
803          * links points to the object being renamed (identified by self_guid,
804          * renamed to new_dn), because that object has a backlink pointing
805          * here.
806          *
807          * In most cases we assume there will only be one forward link, which
808          * is found by parsed_dn_find(), but in the case of DN+Binary links
809          * (e.g. msDS-RevealedUsers) there may be many forward links that
810          * share the same DN/GUID but differ in the binary part. For those we
811          * need to look around the link found by parsed_dn_find() and convert
812          * them all -- there is no way to know which forward link belongs to
813          * which backlink.
814          */
815
816         ret = get_parsed_dns_trusted(tmp_ctx, el, &pdn_list);
817         if (ret != LDB_SUCCESS) {
818                 ldb_asprintf_errstring(ldb, "get_parsed_dn_trusted() "
819                                        "error fixing %s links for %s",
820                                        el->name,
821                                        ldb_dn_get_linearized(msg->dn));
822                 talloc_free(tmp_ctx);
823                 return ret;
824         }
825
826         /* find our DN in the values */
827         ret = parsed_dn_find(ldb, pdn_list, num_parsed_dns,
828                              &self_guid,
829                              NULL,
830                              data_blob_null, 0,
831                              &exact, &next,
832                              syntax_oid,
833                              false);
834
835         if (ret != LDB_SUCCESS) {
836                 ldb_asprintf_errstring(ldb, "parsed_dn_find() "
837                                        "error fixing %s links for %s",
838                                        el->name,
839                                        ldb_dn_get_linearized(msg->dn));
840                 talloc_free(tmp_ctx);
841                 return ret;
842         }
843
844         if (exact == NULL) {
845                 ldb_asprintf_errstring(
846                         ldb,
847                         "parsed_dn_find could not find %s link for %s",
848                         el->name,
849                         ldb_dn_get_linearized(msg->dn));
850                 talloc_free(tmp_ctx);
851                 return LDB_ERR_OPERATIONS_ERROR;
852         }
853
854         is_plain_dn = strcmp(syntax_oid, LDB_SYNTAX_DN) == 0;
855
856         if (is_plain_dn) {
857                 /*
858                  *  The common case -- we only have to update a single link
859                  */
860                 ret = ldb_dn_update_components(exact->dsdb_dn->dn, new_dn);
861                 if (ret != LDB_SUCCESS) {
862                         DBG_ERR("could not update components  %s  %s\n",
863                                 ldb_dn_get_linearized(exact->dsdb_dn->dn),
864                                 ldb_dn_get_linearized(new_dn)
865                                 );
866
867                         talloc_free(tmp_ctx);
868                         return ret;
869                 }
870                 *(exact->v) = data_blob_string_const(
871                                 dsdb_dn_get_extended_linearized(el->values,
872                                                                 exact->dsdb_dn,
873                                                                 1));
874         } else {
875                 /*
876                  * The forward link is a DN+Binary (or in some alternate
877                  * universes, DN+String), which means the parsed_dns are keyed
878                  * on GUID+Binary. We don't know the binary part, which means
879                  * from our point of view the list can have entries with
880                  * duplicate GUIDs that we can't tell apart. We don't know
881                  * which backlink belongs to which GUID+binary, and the binary
882                  * search will always find the same one. That means one link
883                  * link will get fixed n times, whil n-1 links get fixed
884                  * never.
885                  *
886                  * If we instead fixing all the possible links, we end up
887                  * fixing n links n times, which at least works and is
888                  * probably not too costly because n is probably small.
889                  */
890                 struct parsed_dn *first = exact;
891                 struct parsed_dn *last = exact;
892                 struct parsed_dn *p = NULL;
893                 int cmp;
894                 while (first > pdn_list) {
895                         p = first - 1;
896                         if (p->dsdb_dn == NULL) {
897                                 ret = really_parse_trusted_dn(tmp_ctx,
898                                                               ldb, p,
899                                                               syntax_oid);
900                                 if (ret != LDB_SUCCESS) {
901                                         talloc_free(tmp_ctx);
902                                         return ret;
903                                 }
904                         }
905                         cmp = ndr_guid_compare(&exact->guid, &p->guid);
906                         if (cmp != 0) {
907                                 break;
908                         }
909                         first = p;
910                 }
911
912                 while (last < pdn_list + num_parsed_dns - 1) {
913                         p = last + 1;
914                         if (p->dsdb_dn == NULL) {
915                                 ret = really_parse_trusted_dn(tmp_ctx,
916                                                               ldb, p,
917                                                               syntax_oid);
918                                 if (ret != LDB_SUCCESS) {
919                                         talloc_free(tmp_ctx);
920                                         return ret;
921                                 }
922                         }
923                         cmp = ndr_guid_compare(&exact->guid, &p->guid);
924                         if (cmp != 0) {
925                                 break;
926                         }
927                         last = p;
928                 }
929
930                 for (p = first; p <= last; p++) {
931                         ret = ldb_dn_update_components(p->dsdb_dn->dn, new_dn);
932                         if (ret != LDB_SUCCESS) {
933                                 DBG_ERR("could not update components  %s  %s\n",
934                                         ldb_dn_get_linearized(p->dsdb_dn->dn),
935                                         ldb_dn_get_linearized(new_dn)
936                                         );
937                                 talloc_free(tmp_ctx);
938                                 return ret;
939                         }
940                         *(p->v) = data_blob_string_const(
941                                    dsdb_dn_get_extended_linearized(el->values,
942                                                                    p->dsdb_dn,
943                                                                    1));
944                 }
945         }
946
947         talloc_free(tmp_ctx);
948         return LDB_SUCCESS;
949 }
950
951
952 static int linked_attributes_fix_links(struct ldb_module *module,
953                                        struct GUID self_guid,
954                                        struct ldb_dn *old_dn,
955                                        struct ldb_dn *new_dn,
956                                        struct ldb_message_element *el,
957                                        struct dsdb_schema *schema,
958                                        const struct dsdb_attribute *schema_attr,
959                                        struct ldb_request *parent)
960 {
961         unsigned int i;
962         TALLOC_CTX *tmp_ctx = NULL;
963         struct ldb_context *ldb = ldb_module_get_ctx(module);
964         const struct dsdb_attribute *target = NULL;
965         const char *attrs[2];
966         int ret;
967         struct la_private *la_private = NULL;
968
969         target = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1);
970         if (target == NULL) {
971                 /* there is no counterpart link to change */
972                 return LDB_SUCCESS;
973         }
974
975         tmp_ctx = talloc_new(module);
976         if (tmp_ctx == NULL) {
977                 return LDB_ERR_OPERATIONS_ERROR;
978         }
979
980         la_private = talloc_get_type(ldb_module_get_private(module),
981                                      struct la_private);
982         if (la_private == NULL) {
983                 talloc_free(tmp_ctx);
984                 return LDB_ERR_OPERATIONS_ERROR;
985         }
986
987         attrs[0] = target->lDAPDisplayName;
988         attrs[1] = NULL;
989
990         for (i=0; i<el->num_values; i++) {
991                 struct dsdb_dn *dsdb_dn = NULL;
992                 struct ldb_result *res = NULL;
993                 struct ldb_message *msg  = NULL;
994                 struct ldb_message_element *el2 = NULL;
995                 struct GUID link_guid;
996                 char *link_guid_str = NULL;
997
998                 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i],
999                                         schema_attr->syntax->ldap_oid);
1000                 if (dsdb_dn == NULL) {
1001                         talloc_free(tmp_ctx);
1002                         return LDB_ERR_INVALID_DN_SYNTAX;
1003                 }
1004
1005                 ret = la_guid_from_dn(module, parent, dsdb_dn->dn, &link_guid);
1006                 if (ret != LDB_SUCCESS) {
1007                         ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - GUID not found - %s",
1008                                                el->name, target->lDAPDisplayName,
1009                                                ldb_dn_get_linearized(old_dn),
1010                                                ldb_dn_get_linearized(dsdb_dn->dn),
1011                                                ldb_errstring(ldb));
1012                         talloc_free(tmp_ctx);
1013                         return ret;
1014                 }
1015
1016                 link_guid_str = GUID_string(tmp_ctx, &link_guid);
1017                 if (link_guid_str == NULL) {
1018                         talloc_free(tmp_ctx);
1019                         return LDB_ERR_OPERATIONS_ERROR;
1020                 }
1021
1022                 /*
1023                  * get the existing message from the db for the object with
1024                  * this GUID, returning attribute being modified. We will then
1025                  * use this msg as the basis for a modify call
1026                  */
1027
1028                 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
1029                                          DSDB_FLAG_NEXT_MODULE |
1030                                          DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
1031                                          DSDB_SEARCH_SHOW_RECYCLED |
1032                                          DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
1033                                          DSDB_SEARCH_REVEAL_INTERNALS,
1034                                          parent,
1035                                          "objectGUID=%s", link_guid_str);
1036                 if (ret != LDB_SUCCESS) {
1037                         ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - target GUID %s not found - %s",
1038                                                el->name, target->lDAPDisplayName,
1039                                                ldb_dn_get_linearized(old_dn),
1040                                                ldb_dn_get_linearized(dsdb_dn->dn),
1041                                                link_guid_str,
1042                                                ldb_errstring(ldb));
1043                         talloc_free(tmp_ctx);
1044                         return ret;
1045                 }
1046                 if (res->count == 0) {
1047                         /* Forward link without backlink object remaining - nothing to do here */
1048                         continue;
1049                 }
1050                 if (res->count != 1) {
1051                         ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - target GUID %s found more than once!",
1052                                                el->name, target->lDAPDisplayName,
1053                                                ldb_dn_get_linearized(old_dn),
1054                                                ldb_dn_get_linearized(dsdb_dn->dn),
1055                                                link_guid_str);
1056                         talloc_free(tmp_ctx);
1057                         return LDB_ERR_OPERATIONS_ERROR;
1058                 }
1059
1060                 msg = res->msgs[0];
1061
1062                 if (msg->num_elements == 0) {
1063                         /* Forward link without backlink remaining - nothing to do here */
1064                         continue;
1065                 } else if (msg->num_elements != 1) {
1066                         ldb_asprintf_errstring(ldb, "Bad msg elements - got %u elements, expected one element to be returned in linked_attributes_fix_links for %s",
1067                                                msg->num_elements, ldb_dn_get_linearized(msg->dn));
1068                         talloc_free(tmp_ctx);
1069                         return LDB_ERR_OPERATIONS_ERROR;
1070                 }
1071                 if (ldb_attr_cmp(msg->elements[0].name, target->lDAPDisplayName) != 0) {
1072                         ldb_asprintf_errstring(ldb, "Bad returned attribute in linked_attributes_fix_links: got %s, expected %s for %s", msg->elements[0].name, target->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
1073                         talloc_free(tmp_ctx);
1074                         return LDB_ERR_OPERATIONS_ERROR;
1075                 }
1076                 el2 = &msg->elements[0];
1077
1078                 el2->flags = LDB_FLAG_MOD_REPLACE;
1079
1080                 if (target->linkID & 1 ||
1081                         ! la_private->sorted_links) {
1082                         /* handle backlinks (which aren't sorted in the DB)
1083                            and forward links in old unsorted databases. */
1084                         ret = linked_attributes_fix_link_slow(
1085                                 module,
1086                                 parent,
1087                                 msg,
1088                                 new_dn,
1089                                 self_guid,
1090                                 target->syntax->ldap_oid,
1091                                 schema_attr->syntax->ldap_oid);
1092                 } else {
1093                         /* we can binary search to find forward links */
1094                         ret = linked_attributes_fix_forward_link(
1095                                 module,
1096                                 msg,
1097                                 new_dn,
1098                                 self_guid,
1099                                 target->syntax->ldap_oid);
1100                 }
1101                 ret = dsdb_check_single_valued_link(target, el2);
1102                 if (ret != LDB_SUCCESS) {
1103                         talloc_free(tmp_ctx);
1104                         return ret;
1105                 }
1106
1107                 /* we may be putting multiple values in an attribute -
1108                    disable checking for this attribute */
1109                 el2->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
1110
1111                 ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1112                 if (ret != LDB_SUCCESS) {
1113                         ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - update failed - %s",
1114                                                el->name, target->lDAPDisplayName,
1115                                                ldb_dn_get_linearized(old_dn),
1116                                                ldb_dn_get_linearized(dsdb_dn->dn),
1117                                                ldb_errstring(ldb));
1118                         talloc_free(tmp_ctx);
1119                         return ret;
1120                 }
1121         }
1122
1123         talloc_free(tmp_ctx);
1124         return LDB_SUCCESS;
1125 }
1126
1127
1128 /* rename */
1129 static int linked_attributes_rename(struct ldb_module *module, struct ldb_request *req)
1130 {
1131         struct ldb_result *res;
1132         struct ldb_message *msg;
1133         unsigned int i;
1134         struct ldb_context *ldb = ldb_module_get_ctx(module);
1135         struct dsdb_schema *schema;
1136         int ret;
1137         struct GUID guid;
1138
1139         /*
1140            - load the current msg
1141            - find any linked attributes
1142            - if its a link then find the target object
1143            - modify the target linked attributes with the new DN
1144         */
1145         ret = dsdb_module_search_dn(module, req, &res, req->op.rename.olddn,
1146                                     NULL,
1147                                     DSDB_FLAG_NEXT_MODULE |
1148                                     DSDB_SEARCH_SHOW_EXTENDED_DN |
1149                                     DSDB_SEARCH_SHOW_RECYCLED, req);
1150         if (ret != LDB_SUCCESS) {
1151                 return ret;
1152         }
1153
1154         schema = dsdb_get_schema(ldb, res);
1155         if (!schema) {
1156                 return ldb_oom(ldb);
1157         }
1158
1159         msg = res->msgs[0];
1160
1161         ret = la_guid_from_dn(module, req, msg->dn, &guid);
1162         if (ret != LDB_SUCCESS) {
1163                 return ret;
1164         }
1165
1166         for (i=0; i<msg->num_elements; i++) {
1167                 struct ldb_message_element *el = &msg->elements[i];
1168                 const struct dsdb_attribute *schema_attr
1169                         = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
1170                 if (!schema_attr || schema_attr->linkID == 0) {
1171                         continue;
1172                 }
1173                 ret = linked_attributes_fix_links(module, guid, msg->dn, req->op.rename.newdn, el,
1174                                                   schema, schema_attr, req);
1175                 if (ret != LDB_SUCCESS) {
1176                         talloc_free(res);
1177                         return ret;
1178                 }
1179         }
1180
1181         talloc_free(res);
1182
1183         return ldb_next_request(module, req);
1184 }
1185
1186
1187 /* queue a linked attributes modify request in the la_private
1188    structure */
1189 static int la_queue_mod_request(struct la_context *ac)
1190 {
1191         struct la_private *la_private =
1192                 talloc_get_type(ldb_module_get_private(ac->module),
1193                                 struct la_private);
1194
1195         if (la_private == NULL || la_private->transaction == NULL) {
1196                 ldb_debug(ldb_module_get_ctx(ac->module),
1197                           LDB_DEBUG_ERROR,
1198                           __location__ ": No la_private transaction setup\n");
1199                 return ldb_operr(ldb_module_get_ctx(ac->module));
1200         }
1201
1202         talloc_steal(la_private->transaction, ac);
1203         DLIST_ADD(la_private->transaction->la_list, ac);
1204
1205         return ldb_module_done(ac->req, ac->op_controls,
1206                                ac->op_response, LDB_SUCCESS);
1207 }
1208
1209 /* Having done the original operation, then try to fix up all the linked attributes for modify and delete */
1210 static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares)
1211 {
1212         struct la_context *ac;
1213         struct ldb_context *ldb;
1214         int ret;
1215
1216         ac = talloc_get_type(req->context, struct la_context);
1217         ldb = ldb_module_get_ctx(ac->module);
1218
1219         if (!ares) {
1220                 return ldb_module_done(ac->req, NULL, NULL,
1221                                         LDB_ERR_OPERATIONS_ERROR);
1222         }
1223         if (ares->error != LDB_SUCCESS) {
1224                 return ldb_module_done(ac->req, ares->controls,
1225                                         ares->response, ares->error);
1226         }
1227
1228         if (ares->type != LDB_REPLY_DONE) {
1229                 ldb_set_errstring(ldb,
1230                      "invalid reply type in linked attributes delete callback");
1231                 talloc_free(ares);
1232                 return ldb_module_done(ac->req, NULL, NULL,
1233                                         LDB_ERR_OPERATIONS_ERROR);
1234         }
1235
1236         ac->op_controls = talloc_steal(ac, ares->controls);
1237         ac->op_response = talloc_steal(ac, ares->response);
1238
1239         /* If we have modfies to make, this is the time to do them for modify and delete */
1240         ret = la_queue_mod_request(ac);
1241
1242         if (ret != LDB_SUCCESS) {
1243                 return ldb_module_done(ac->req, NULL, NULL, ret);
1244         }
1245         talloc_free(ares);
1246
1247         /* la_queue_mod_request has already sent the callbacks */
1248         return LDB_SUCCESS;
1249
1250 }
1251
1252 /* Having done the original add, then try to fix up all the linked attributes
1253
1254   This is done after the add so the links can get the extended DNs correctly.
1255  */
1256 static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares)
1257 {
1258         struct la_context *ac;
1259         struct ldb_context *ldb;
1260         int ret;
1261
1262         ac = talloc_get_type(req->context, struct la_context);
1263         ldb = ldb_module_get_ctx(ac->module);
1264
1265         if (!ares) {
1266                 return ldb_module_done(ac->req, NULL, NULL,
1267                                         LDB_ERR_OPERATIONS_ERROR);
1268         }
1269         if (ares->error != LDB_SUCCESS) {
1270                 return ldb_module_done(ac->req, ares->controls,
1271                                         ares->response, ares->error);
1272         }
1273
1274         if (ares->type != LDB_REPLY_DONE) {
1275                 ldb_set_errstring(ldb,
1276                         "invalid reply type in linked attributes add callback");
1277                 talloc_free(ares);
1278                 return ldb_module_done(ac->req, NULL, NULL,
1279                                         LDB_ERR_OPERATIONS_ERROR);
1280         }
1281
1282         if (ac->ops) {
1283                 struct ldb_request *search_req;
1284                 static const char *attrs[] = { NULL };
1285
1286                 /* The callback does all the hard work here - we need
1287                  * the objectGUID and SID of the added record */
1288                 ret = ldb_build_search_req(&search_req, ldb, ac,
1289                                            ac->req->op.add.message->dn,
1290                                            LDB_SCOPE_BASE,
1291                                            "(objectClass=*)", attrs,
1292                                            NULL,
1293                                            ac, la_mod_search_callback,
1294                                            ac->req);
1295                 LDB_REQ_SET_LOCATION(search_req);
1296
1297                 if (ret == LDB_SUCCESS) {
1298                         ret = dsdb_request_add_controls(search_req,
1299                                                         DSDB_SEARCH_SHOW_RECYCLED |
1300                                                         DSDB_SEARCH_SHOW_EXTENDED_DN);
1301                 }
1302                 if (ret != LDB_SUCCESS) {
1303                         return ldb_module_done(ac->req, NULL, NULL,
1304                                                ret);
1305                 }
1306
1307                 ac->op_controls = talloc_steal(ac, ares->controls);
1308                 ac->op_response = talloc_steal(ac, ares->response);
1309
1310                 return ldb_next_request(ac->module, search_req);
1311
1312         } else {
1313                 return ldb_module_done(ac->req, ares->controls,
1314                                        ares->response, ares->error);
1315         }
1316 }
1317
1318 /* Reconstruct the original request, but pointing at our local callback to finish things off */
1319 static int la_down_req(struct la_context *ac)
1320 {
1321         struct ldb_request *down_req;
1322         struct ldb_context *ldb;
1323         int ret;
1324
1325         ldb = ldb_module_get_ctx(ac->module);
1326
1327         switch (ac->req->operation) {
1328         case LDB_ADD:
1329                 ret = ldb_build_add_req(&down_req, ldb, ac,
1330                                         ac->req->op.add.message,
1331                                         ac->req->controls,
1332                                         ac, la_add_callback,
1333                                         ac->req);
1334                 LDB_REQ_SET_LOCATION(down_req);
1335                 break;
1336         case LDB_MODIFY:
1337                 ret = ldb_build_mod_req(&down_req, ldb, ac,
1338                                         ac->req->op.mod.message,
1339                                         ac->req->controls,
1340                                         ac, la_mod_del_callback,
1341                                         ac->req);
1342                 LDB_REQ_SET_LOCATION(down_req);
1343                 break;
1344         default:
1345                 ret = LDB_ERR_OPERATIONS_ERROR;
1346         }
1347         if (ret != LDB_SUCCESS) {
1348                 return ret;
1349         }
1350
1351         return ldb_next_request(ac->module, down_req);
1352 }
1353
1354 /*
1355   use the GUID part of an extended DN to find the target DN, in case
1356   it has moved
1357  */
1358 static int la_find_dn_target(struct ldb_module *module, struct la_context *ac,
1359                              struct GUID *guid, struct ldb_dn **dn)
1360 {
1361         return dsdb_module_dn_by_guid(ac->module, ac, guid, dn, ac->req);
1362 }
1363
1364 /* apply one la_context op change */
1365 static int la_do_op_request(struct ldb_module *module, struct la_context *ac, struct la_op_store *op)
1366 {
1367         struct ldb_message_element *ret_el;
1368         struct ldb_message *new_msg;
1369         struct ldb_context *ldb;
1370         int ret;
1371
1372         if (ac->mod_dn == NULL) {
1373                 /* we didn't find the DN that we searched for */
1374                 return LDB_SUCCESS;
1375         }
1376
1377         ldb = ldb_module_get_ctx(ac->module);
1378
1379         /* Create the modify request */
1380         new_msg = ldb_msg_new(ac);
1381         if (!new_msg) {
1382                 return ldb_oom(ldb);
1383         }
1384
1385         ret = la_find_dn_target(module, ac, &op->guid, &new_msg->dn);
1386         if (ret != LDB_SUCCESS) {
1387                 return ret;
1388         }
1389
1390         if (op->op == LA_OP_ADD) {
1391                 ret = ldb_msg_add_empty(new_msg, op->name,
1392                                         LDB_FLAG_MOD_ADD, &ret_el);
1393         } else {
1394                 ret = ldb_msg_add_empty(new_msg, op->name,
1395                                         LDB_FLAG_MOD_DELETE, &ret_el);
1396         }
1397         if (ret != LDB_SUCCESS) {
1398                 return ret;
1399         }
1400         ret_el->values = talloc_array(new_msg, struct ldb_val, 1);
1401         if (!ret_el->values) {
1402                 return ldb_oom(ldb);
1403         }
1404         ret_el->num_values = 1;
1405         ret_el->values[0] = data_blob_string_const(ldb_dn_get_extended_linearized(new_msg, ac->mod_dn, 1));
1406
1407         /* a backlink should never be single valued. Unfortunately the
1408            exchange schema has a attribute
1409            msExchBridgeheadedLocalConnectorsDNBL which is single
1410            valued and a backlink. We need to cope with that by
1411            ignoring the single value flag */
1412         ret_el->flags |= LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK;
1413
1414 #if 0
1415         ldb_debug(ldb, LDB_DEBUG_WARNING,
1416                   "link on %s %s: %s %s\n",
1417                   ldb_dn_get_linearized(new_msg->dn), ret_el->name,
1418                   ret_el->values[0].data, ac->ops->op == LA_OP_ADD ? "added" : "deleted");
1419 #endif
1420
1421         if (DEBUGLVL(4)) {
1422                 DEBUG(4,("Applying linked attribute change:\n%s\n",
1423                          ldb_ldif_message_redacted_string(ldb, op,
1424                                                           LDB_CHANGETYPE_MODIFY,
1425                                                           new_msg)));
1426         }
1427
1428         ret = dsdb_module_modify(module, new_msg, DSDB_FLAG_NEXT_MODULE, ac->req);
1429         if (ret != LDB_SUCCESS) {
1430                 ldb_debug(ldb, LDB_DEBUG_WARNING, __location__ ": failed to apply linked attribute change '%s'\n%s\n",
1431                           ldb_errstring(ldb),
1432                           ldb_ldif_message_redacted_string(ldb, op,
1433                                                            LDB_CHANGETYPE_MODIFY,
1434                                                            new_msg));
1435         }
1436
1437         return ret;
1438 }
1439
1440 /* apply one set of la_context changes */
1441 static int la_do_mod_request(struct ldb_module *module, struct la_context *ac)
1442 {
1443         struct la_op_store *op;
1444
1445         for (op = ac->ops; op; op=op->next) {
1446                 int ret = la_do_op_request(module, ac, op);
1447                 if (ret != LDB_SUCCESS) {
1448                         if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1449                                 return ret;
1450                         }
1451                 }
1452         }
1453
1454         return LDB_SUCCESS;
1455 }
1456
1457
1458 /*
1459   we hook into the transaction operations to allow us to
1460   perform the linked attribute updates at the end of the whole
1461   transaction. This allows a forward linked attribute to be created
1462   before the target is created, as long as the target is created
1463   in the same transaction
1464  */
1465 static int linked_attributes_start_transaction(struct ldb_module *module)
1466 {
1467         /* create our private structure for this transaction */
1468         struct la_private *la_private =
1469                 talloc_get_type(ldb_module_get_private(module),
1470                                 struct la_private);
1471
1472         if (la_private == NULL) {
1473                 return ldb_oom(ldb_module_get_ctx(module));
1474         }
1475         talloc_free(la_private->transaction);
1476         la_private->transaction = talloc(module, struct la_private_transaction);
1477         if (la_private->transaction == NULL) {
1478                 return ldb_oom(ldb_module_get_ctx(module));
1479         }
1480         la_private->transaction->la_list = NULL;
1481         return ldb_next_start_trans(module);
1482 }
1483
1484 /*
1485   on prepare commit we loop over our queued la_context structures
1486   and apply each of them
1487  */
1488 static int linked_attributes_prepare_commit(struct ldb_module *module)
1489 {
1490         struct la_context *ac;
1491         struct la_private *la_private =
1492                 talloc_get_type(ldb_module_get_private(module),
1493                                 struct la_private);
1494         if (la_private == NULL || la_private->transaction == NULL) {
1495                 DBG_ERR("prepare_commit without begin_transaction\n");
1496                 /* prepare commit without begin_transaction - let someone else
1497                  * return the error, just don't segfault */
1498                 return ldb_next_prepare_commit(module);
1499         }
1500         /* walk the list backwards, to do the first entry first, as we
1501          * added the entries with DLIST_ADD() which puts them at the
1502          * start of the list */
1503
1504         /* Start at the end of the list - so we can start
1505          * there, but ensure we don't create a loop by NULLing
1506          * it out in the first element */
1507         ac = DLIST_TAIL(la_private->transaction->la_list);
1508
1509         for (; ac; ac=DLIST_PREV(ac)) {
1510                 int ret;
1511                 ac->req = NULL;
1512                 ret = la_do_mod_request(module, ac);
1513                 if (ret != LDB_SUCCESS) {
1514                         DEBUG(0,(__location__ ": Failed mod request ret=%d\n", ret));
1515                         TALLOC_FREE(la_private->transaction);
1516                         return ret;
1517                 }
1518         }
1519
1520         TALLOC_FREE(la_private->transaction);
1521
1522         return ldb_next_prepare_commit(module);
1523 }
1524
1525 static int linked_attributes_del_transaction(struct ldb_module *module)
1526 {
1527         struct la_private *la_private =
1528                 talloc_get_type(ldb_module_get_private(module),
1529                                 struct la_private);
1530         TALLOC_FREE(la_private->transaction);
1531         return ldb_next_del_trans(module);
1532 }
1533
1534 static int linked_attributes_ldb_init(struct ldb_module *module)
1535 {
1536         int ret;
1537         struct la_private *la_private = NULL;
1538         struct ldb_context *ldb = ldb_module_get_ctx(module);
1539
1540         ret = ldb_mod_register_control(module, LDB_CONTROL_VERIFY_NAME_OID);
1541         if (ret != LDB_SUCCESS) {
1542                 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
1543                         "verify_name: Unable to register control with rootdse!\n");
1544                 return ldb_operr(ldb_module_get_ctx(module));
1545         }
1546
1547         la_private = talloc_zero(module, struct la_private);
1548         if (la_private == NULL) {
1549                 ldb_oom(ldb);
1550                 return LDB_ERR_OPERATIONS_ERROR;
1551         }
1552
1553         ret = dsdb_check_samba_compatible_feature(module,
1554                                                   SAMBA_SORTED_LINKS_FEATURE,
1555                                                   &la_private->sorted_links);
1556         if (ret != LDB_SUCCESS) {
1557                 talloc_free(la_private);
1558                 return ret;
1559         }
1560
1561         ldb_module_set_private(module, la_private);
1562         return ldb_next_init(module);
1563 }
1564
1565
1566 static const struct ldb_module_ops ldb_linked_attributes_module_ops = {
1567         .name              = "linked_attributes",
1568         .add               = linked_attributes_add,
1569         .modify            = linked_attributes_modify,
1570         .rename            = linked_attributes_rename,
1571         .init_context      = linked_attributes_ldb_init,
1572         .start_transaction = linked_attributes_start_transaction,
1573         .prepare_commit    = linked_attributes_prepare_commit,
1574         .del_transaction   = linked_attributes_del_transaction,
1575 };
1576
1577 int ldb_linked_attributes_module_init(const char *version)
1578 {
1579         LDB_MODULE_CHECK_VERSION(version);
1580         return ldb_register_module(&ldb_linked_attributes_module_ops);
1581 }