s4-dsdb: ensure rIDSetReferences is stored as an extended DN
[amitay/samba.git] / source4 / dsdb / samdb / ldb_modules / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 2009
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7    Copyright (C) Matthieu Patou <mat@matws.net> 2011
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 #include "includes.h"
24 #include "ldb.h"
25 #include "ldb_module.h"
26 #include "librpc/ndr/libndr.h"
27 #include "dsdb/samdb/ldb_modules/util.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "util.h"
30 #include "libcli/security/security.h"
31
32 /*
33   search for attrs on one DN, in the modules below
34  */
35 int dsdb_module_search_dn(struct ldb_module *module,
36                           TALLOC_CTX *mem_ctx,
37                           struct ldb_result **_res,
38                           struct ldb_dn *basedn,
39                           const char * const *attrs,
40                           uint32_t dsdb_flags,
41                           struct ldb_request *parent)
42 {
43         int ret;
44         struct ldb_request *req;
45         TALLOC_CTX *tmp_ctx;
46         struct ldb_result *res;
47
48         tmp_ctx = talloc_new(mem_ctx);
49
50         res = talloc_zero(tmp_ctx, struct ldb_result);
51         if (!res) {
52                 talloc_free(tmp_ctx);
53                 return ldb_oom(ldb_module_get_ctx(module));
54         }
55
56         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
57                                    basedn,
58                                    LDB_SCOPE_BASE,
59                                    NULL,
60                                    attrs,
61                                    NULL,
62                                    res,
63                                    ldb_search_default_callback,
64                                    parent);
65         LDB_REQ_SET_LOCATION(req);
66         if (ret != LDB_SUCCESS) {
67                 talloc_free(tmp_ctx);
68                 return ret;
69         }
70
71         ret = dsdb_request_add_controls(req, dsdb_flags);
72         if (ret != LDB_SUCCESS) {
73                 talloc_free(tmp_ctx);
74                 return ret;
75         }
76
77         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
78                 ldb_req_mark_trusted(req);
79         }
80
81         /* Run the new request */
82         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
83                 ret = ldb_next_request(module, req);
84         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
85                 ret = ldb_request(ldb_module_get_ctx(module), req);
86         } else {
87                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
88                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
89                 ret = ops->search(module, req);
90         }
91         if (ret == LDB_SUCCESS) {
92                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
93         }
94
95         if (ret != LDB_SUCCESS) {
96                 talloc_free(tmp_ctx);
97                 return ret;
98         }
99
100         if (res->count != 1) {
101                 /* we may be reading a DB that does not have the 'check base on search' option... */
102                 ret = LDB_ERR_NO_SUCH_OBJECT;
103                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
104                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
105                                        ldb_dn_get_linearized(basedn), res->count);
106         } else {
107                 *_res = talloc_steal(mem_ctx, res);
108         }
109         talloc_free(tmp_ctx);
110         return ret;
111 }
112
113 int dsdb_module_search_tree(struct ldb_module *module,
114                        TALLOC_CTX *mem_ctx,
115                        struct ldb_result **_res,
116                        struct ldb_dn *basedn,
117                        enum ldb_scope scope,
118                        struct ldb_parse_tree *tree,
119                        const char * const *attrs,
120                        int dsdb_flags,
121                        struct ldb_request *parent)
122 {
123         int ret;
124         struct ldb_request *req;
125         TALLOC_CTX *tmp_ctx;
126         struct ldb_result *res;
127
128         tmp_ctx = talloc_new(mem_ctx);
129
130
131         res = talloc_zero(tmp_ctx, struct ldb_result);
132         if (!res) {
133                 talloc_free(tmp_ctx);
134                 return ldb_oom(ldb_module_get_ctx(module));
135         }
136
137         ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
138                                    basedn,
139                                    scope,
140                                    tree,
141                                    attrs,
142                                    NULL,
143                                    res,
144                                    ldb_search_default_callback,
145                                    parent);
146         LDB_REQ_SET_LOCATION(req);
147         if (ret != LDB_SUCCESS) {
148                 talloc_free(tmp_ctx);
149                 return ret;
150         }
151
152         ret = dsdb_request_add_controls(req, dsdb_flags);
153         if (ret != LDB_SUCCESS) {
154                 talloc_free(tmp_ctx);
155                 return ret;
156         }
157
158         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
159                 ldb_req_mark_trusted(req);
160         }
161
162         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
163                 ret = ldb_next_request(module, req);
164         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
165                 ret = ldb_request(ldb_module_get_ctx(module), req);
166         } else {
167                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
168                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
169                 ret = ops->search(module, req);
170         }
171         if (ret == LDB_SUCCESS) {
172                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
173         }
174
175         talloc_free(req);
176         if (ret == LDB_SUCCESS) {
177                 *_res = talloc_steal(mem_ctx, res);
178         }
179         talloc_free(tmp_ctx);
180         return ret;
181 }
182
183 /*
184   search for attrs in the modules below
185  */
186 int dsdb_module_search(struct ldb_module *module,
187                        TALLOC_CTX *mem_ctx,
188                        struct ldb_result **_res,
189                        struct ldb_dn *basedn, enum ldb_scope scope,
190                        const char * const *attrs,
191                        int dsdb_flags,
192                        struct ldb_request *parent,
193                        const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
194 {
195         int ret;
196         TALLOC_CTX *tmp_ctx;
197         va_list ap;
198         char *expression;
199         struct ldb_parse_tree *tree;
200
201         tmp_ctx = talloc_new(mem_ctx);
202
203         if (format) {
204                 va_start(ap, format);
205                 expression = talloc_vasprintf(tmp_ctx, format, ap);
206                 va_end(ap);
207
208                 if (!expression) {
209                         talloc_free(tmp_ctx);
210                         return ldb_oom(ldb_module_get_ctx(module));
211                 }
212         } else {
213                 expression = NULL;
214         }
215
216         tree = ldb_parse_tree(tmp_ctx, expression);
217         if (tree == NULL) {
218                 talloc_free(tmp_ctx);
219                 ldb_set_errstring(ldb_module_get_ctx(module),
220                                 "Unable to parse search expression");
221                 return LDB_ERR_OPERATIONS_ERROR;
222         }
223
224         ret = dsdb_module_search_tree(module,
225                        mem_ctx,
226                        _res,
227                        basedn,
228                        scope,
229                        tree,
230                        attrs,
231                        dsdb_flags,
232                        parent);
233
234         talloc_free(tmp_ctx);
235         return ret;
236 }
237
238 /*
239   find a DN given a GUID. This searches across all partitions
240  */
241 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
242                            const struct GUID *guid, struct ldb_dn **dn,
243                            struct ldb_request *parent)
244 {
245         struct ldb_result *res;
246         const char *attrs[] = { NULL };
247         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
248         int ret;
249
250         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
251                                  attrs,
252                                  DSDB_FLAG_NEXT_MODULE |
253                                  DSDB_SEARCH_SHOW_RECYCLED |
254                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
255                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
256                                  parent,
257                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
258         if (ret != LDB_SUCCESS) {
259                 talloc_free(tmp_ctx);
260                 return ret;
261         }
262         if (res->count == 0) {
263                 talloc_free(tmp_ctx);
264                 return LDB_ERR_NO_SUCH_OBJECT;
265         }
266         if (res->count != 1) {
267                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
268                                        GUID_string(tmp_ctx, guid));
269                 talloc_free(tmp_ctx);
270                 return LDB_ERR_OPERATIONS_ERROR;
271         }
272
273         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
274
275         talloc_free(tmp_ctx);
276         return LDB_SUCCESS;
277 }
278
279 /*
280   find a GUID given a DN.
281  */
282 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
283                            struct ldb_request *parent)
284 {
285         const char *attrs[] = { NULL };
286         struct ldb_result *res;
287         TALLOC_CTX *tmp_ctx = talloc_new(module);
288         int ret;
289         NTSTATUS status;
290
291         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
292                                     DSDB_FLAG_NEXT_MODULE |
293                                     DSDB_SEARCH_SHOW_RECYCLED |
294                                     DSDB_SEARCH_SHOW_EXTENDED_DN,
295                                     parent);
296         if (ret != LDB_SUCCESS) {
297                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
298                                        ldb_dn_get_linearized(dn));
299                 talloc_free(tmp_ctx);
300                 return ret;
301         }
302
303         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
304         if (!NT_STATUS_IS_OK(status)) {
305                 talloc_free(tmp_ctx);
306                 return ldb_operr(ldb_module_get_ctx(module));
307         }
308
309         talloc_free(tmp_ctx);
310         return LDB_SUCCESS;
311 }
312 /*
313   a ldb_extended request operating on modules below the
314   current module
315  */
316 int dsdb_module_extended(struct ldb_module *module,
317                        const char* oid, void* data,
318                        uint32_t dsdb_flags,
319                        struct ldb_request *parent)
320 {
321         struct ldb_request *req;
322         int ret;
323         struct ldb_context *ldb = ldb_module_get_ctx(module);
324         TALLOC_CTX *tmp_ctx = talloc_new(module);
325         struct ldb_result *res;
326
327         res = talloc_zero(tmp_ctx, struct ldb_result);
328         if (!res) {
329                 talloc_free(tmp_ctx);
330                 return ldb_oom(ldb_module_get_ctx(module));
331         }
332
333         ret = ldb_build_extended_req(&req, ldb,
334                         tmp_ctx,
335                         oid,
336                         data,
337                         NULL,
338                         res, ldb_extended_default_callback,
339                         parent);
340
341         LDB_REQ_SET_LOCATION(req);
342         if (ret != LDB_SUCCESS) {
343                 talloc_free(tmp_ctx);
344                 return ret;
345         }
346
347         ret = dsdb_request_add_controls(req, dsdb_flags);
348         if (ret != LDB_SUCCESS) {
349                 talloc_free(tmp_ctx);
350                 return ret;
351         }
352
353         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
354                 ldb_req_mark_trusted(req);
355         }
356
357         /* Run the new request */
358         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
359                 ret = ldb_next_request(module, req);
360         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
361                 ret = ldb_request(ldb_module_get_ctx(module), req);
362         } else {
363                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
364                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
365                 ret = ops->extended(module, req);
366         }
367         if (ret == LDB_SUCCESS) {
368                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
369         }
370
371         talloc_free(tmp_ctx);
372         return ret;
373 }
374 /*
375   a ldb_modify request operating on modules below the
376   current module
377  */
378 int dsdb_module_modify(struct ldb_module *module,
379                        const struct ldb_message *message,
380                        uint32_t dsdb_flags,
381                        struct ldb_request *parent)
382 {
383         struct ldb_request *mod_req;
384         int ret;
385         struct ldb_context *ldb = ldb_module_get_ctx(module);
386         TALLOC_CTX *tmp_ctx = talloc_new(module);
387         struct ldb_result *res;
388
389         res = talloc_zero(tmp_ctx, struct ldb_result);
390         if (!res) {
391                 talloc_free(tmp_ctx);
392                 return ldb_oom(ldb_module_get_ctx(module));
393         }
394
395         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
396                                 message,
397                                 NULL,
398                                 res,
399                                 ldb_modify_default_callback,
400                                 parent);
401         LDB_REQ_SET_LOCATION(mod_req);
402         if (ret != LDB_SUCCESS) {
403                 talloc_free(tmp_ctx);
404                 return ret;
405         }
406
407         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
408         if (ret != LDB_SUCCESS) {
409                 talloc_free(tmp_ctx);
410                 return ret;
411         }
412
413         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
414                 ldb_req_mark_trusted(mod_req);
415         }
416
417         /* Run the new request */
418         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
419                 ret = ldb_next_request(module, mod_req);
420         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
421                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
422         } else {
423                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
424                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
425                 ret = ops->modify(module, mod_req);
426         }
427         if (ret == LDB_SUCCESS) {
428                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
429         }
430
431         talloc_free(tmp_ctx);
432         return ret;
433 }
434
435
436
437 /*
438   a ldb_rename request operating on modules below the
439   current module
440  */
441 int dsdb_module_rename(struct ldb_module *module,
442                        struct ldb_dn *olddn, struct ldb_dn *newdn,
443                        uint32_t dsdb_flags,
444                        struct ldb_request *parent)
445 {
446         struct ldb_request *req;
447         int ret;
448         struct ldb_context *ldb = ldb_module_get_ctx(module);
449         TALLOC_CTX *tmp_ctx = talloc_new(module);
450         struct ldb_result *res;
451
452         res = talloc_zero(tmp_ctx, struct ldb_result);
453         if (!res) {
454                 talloc_free(tmp_ctx);
455                 return ldb_oom(ldb_module_get_ctx(module));
456         }
457
458         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
459                                    olddn,
460                                    newdn,
461                                    NULL,
462                                    res,
463                                    ldb_modify_default_callback,
464                                    parent);
465         LDB_REQ_SET_LOCATION(req);
466         if (ret != LDB_SUCCESS) {
467                 talloc_free(tmp_ctx);
468                 return ret;
469         }
470
471         ret = dsdb_request_add_controls(req, dsdb_flags);
472         if (ret != LDB_SUCCESS) {
473                 talloc_free(tmp_ctx);
474                 return ret;
475         }
476
477         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
478                 ldb_req_mark_trusted(req);
479         }
480
481         /* Run the new request */
482         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
483                 ret = ldb_next_request(module, req);
484         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
485                 ret = ldb_request(ldb_module_get_ctx(module), req);
486         } else {
487                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
488                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
489                 ret = ops->rename(module, req);
490         }
491         if (ret == LDB_SUCCESS) {
492                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
493         }
494
495         talloc_free(tmp_ctx);
496         return ret;
497 }
498
499 /*
500   a ldb_add request operating on modules below the
501   current module
502  */
503 int dsdb_module_add(struct ldb_module *module,
504                     const struct ldb_message *message,
505                     uint32_t dsdb_flags,
506                     struct ldb_request *parent)
507 {
508         struct ldb_request *req;
509         int ret;
510         struct ldb_context *ldb = ldb_module_get_ctx(module);
511         TALLOC_CTX *tmp_ctx = talloc_new(module);
512         struct ldb_result *res;
513
514         res = talloc_zero(tmp_ctx, struct ldb_result);
515         if (!res) {
516                 talloc_free(tmp_ctx);
517                 return ldb_oom(ldb_module_get_ctx(module));
518         }
519
520         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
521                                 message,
522                                 NULL,
523                                 res,
524                                 ldb_modify_default_callback,
525                                 parent);
526         LDB_REQ_SET_LOCATION(req);
527         if (ret != LDB_SUCCESS) {
528                 talloc_free(tmp_ctx);
529                 return ret;
530         }
531
532         ret = dsdb_request_add_controls(req, dsdb_flags);
533         if (ret != LDB_SUCCESS) {
534                 talloc_free(tmp_ctx);
535                 return ret;
536         }
537
538         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
539                 ldb_req_mark_trusted(req);
540         }
541
542         /* Run the new request */
543         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
544                 ret = ldb_next_request(module, req);
545         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
546                 ret = ldb_request(ldb_module_get_ctx(module), req);
547         } else {
548                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
549                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
550                 ret = ops->add(module, req);
551         }
552         if (ret == LDB_SUCCESS) {
553                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
554         }
555
556         talloc_free(tmp_ctx);
557         return ret;
558 }
559
560 /*
561   a ldb_delete request operating on modules below the
562   current module
563  */
564 int dsdb_module_del(struct ldb_module *module,
565                     struct ldb_dn *dn,
566                     uint32_t dsdb_flags,
567                     struct ldb_request *parent)
568 {
569         struct ldb_request *req;
570         int ret;
571         struct ldb_context *ldb = ldb_module_get_ctx(module);
572         TALLOC_CTX *tmp_ctx = talloc_new(module);
573         struct ldb_result *res;
574
575         res = talloc_zero(tmp_ctx, struct ldb_result);
576         if (!res) {
577                 talloc_free(tmp_ctx);
578                 return ldb_oom(ldb);
579         }
580
581         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
582                                 dn,
583                                 NULL,
584                                 res,
585                                 ldb_modify_default_callback,
586                                 parent);
587         LDB_REQ_SET_LOCATION(req);
588         if (ret != LDB_SUCCESS) {
589                 talloc_free(tmp_ctx);
590                 return ret;
591         }
592
593         ret = dsdb_request_add_controls(req, dsdb_flags);
594         if (ret != LDB_SUCCESS) {
595                 talloc_free(tmp_ctx);
596                 return ret;
597         }
598
599         if (dsdb_flags & DSDB_FLAG_TRUSTED) {
600                 ldb_req_mark_trusted(req);
601         }
602
603         /* Run the new request */
604         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
605                 ret = ldb_next_request(module, req);
606         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
607                 ret = ldb_request(ldb_module_get_ctx(module), req);
608         } else {
609                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
610                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
611                 ret = ops->del(module, req);
612         }
613         if (ret == LDB_SUCCESS) {
614                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
615         }
616
617         talloc_free(tmp_ctx);
618         return ret;
619 }
620
621 /*
622   check if a single valued link has multiple non-deleted values
623
624   This is needed when we will be using the RELAX control to stop
625   ldb_tdb from checking single valued links
626  */
627 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
628                                   const struct ldb_message_element *el)
629 {
630         bool found_active = false;
631         unsigned int i;
632
633         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
634             el->num_values < 2) {
635                 return LDB_SUCCESS;
636         }
637
638         for (i=0; i<el->num_values; i++) {
639                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
640                         if (found_active) {
641                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
642                         }
643                         found_active = true;
644                 }
645         }
646
647         return LDB_SUCCESS;
648 }
649
650 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
651                                         struct GUID op_feature_guid, bool *feature_enabled)
652 {
653         TALLOC_CTX *tmp_ctx;
654         struct ldb_context *ldb = ldb_module_get_ctx(module);
655         struct ldb_result *res;
656         struct ldb_dn *search_dn;
657         struct GUID search_guid;
658         const char *attrs[] = {"msDS-EnabledFeature", NULL};
659         int ret;
660         unsigned int i;
661         struct ldb_message_element *el;
662
663         *feature_enabled = false;
664
665         tmp_ctx = talloc_new(ldb);
666
667         ret = ldb_search(ldb, tmp_ctx, &res,
668                                         scope, LDB_SCOPE_BASE, attrs,
669                                         NULL);
670         if (ret != LDB_SUCCESS) {
671                 ldb_asprintf_errstring(ldb,
672                                 "Could no find the scope object - dn: %s\n",
673                                 ldb_dn_get_linearized(scope));
674                 talloc_free(tmp_ctx);
675                 return LDB_ERR_OPERATIONS_ERROR;
676         }
677         if (res->msgs[0]->num_elements > 0) {
678
679                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
680
681                 attrs[0] = "msDS-OptionalFeatureGUID";
682
683                 for (i=0; i<el->num_values; i++) {
684                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
685
686                         ret = ldb_search(ldb, tmp_ctx, &res,
687                                                         search_dn, LDB_SCOPE_BASE, attrs,
688                                                         NULL);
689                         if (ret != LDB_SUCCESS) {
690                                 ldb_asprintf_errstring(ldb,
691                                                 "Could no find object dn: %s\n",
692                                                 ldb_dn_get_linearized(search_dn));
693                                 talloc_free(tmp_ctx);
694                                 return LDB_ERR_OPERATIONS_ERROR;
695                         }
696
697                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
698
699                         if (GUID_compare(&search_guid, &op_feature_guid) == 0){
700                                 *feature_enabled = true;
701                                 break;
702                         }
703                 }
704         }
705         talloc_free(tmp_ctx);
706         return LDB_SUCCESS;
707 }
708
709 /*
710   find the NTDS GUID from a computers DN record
711  */
712 int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
713                                            TALLOC_CTX *mem_ctx,
714                                            struct ldb_dn *computer_dn,
715                                            struct GUID *ntds_guid,
716                                            struct ldb_request *parent)
717 {
718         int ret;
719         struct ldb_dn *dn;
720
721         *ntds_guid = GUID_zero();
722
723         ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
724                                        "serverReferenceBL", &dn, parent);
725         if (ret != LDB_SUCCESS) {
726                 return ret;
727         }
728
729         if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
730                 talloc_free(dn);
731                 return LDB_ERR_OPERATIONS_ERROR;
732         }
733
734         ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
735         talloc_free(dn);
736         return ret;
737 }
738
739 /*
740   find a 'reference' DN that points at another object
741   (eg. serverReference, rIDManagerReference etc)
742  */
743 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
744                              const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
745 {
746         const char *attrs[2];
747         struct ldb_result *res;
748         int ret;
749
750         attrs[0] = attribute;
751         attrs[1] = NULL;
752
753         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
754                                     DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
755         if (ret != LDB_SUCCESS) {
756                 return ret;
757         }
758
759         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
760                                       mem_ctx, res->msgs[0], attribute);
761         if (!*dn) {
762                 ldb_reset_err_string(ldb_module_get_ctx(module));
763                 talloc_free(res);
764                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
765         }
766
767         talloc_free(res);
768         return LDB_SUCCESS;
769 }
770
771 /*
772   find the RID Manager$ DN via the rIDManagerReference attribute in the
773   base DN
774  */
775 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
776                                struct ldb_request *parent)
777 {
778         return dsdb_module_reference_dn(module, mem_ctx,
779                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
780                                         "rIDManagerReference", dn, parent);
781 }
782
783 /*
784   used to chain to the callers callback
785  */
786 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
787 {
788         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
789
790         talloc_steal(up_req, req);
791         return up_req->callback(up_req, ares);
792 }
793
794 /*
795   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
796   object for a partition
797  */
798 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
799                                    uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
800 {
801         struct ldb_context *ldb = ldb_module_get_ctx(module);
802         struct ldb_request *req;
803         int ret;
804         TALLOC_CTX *tmp_ctx = talloc_new(module);
805         struct dsdb_control_current_partition *p_ctrl;
806         struct ldb_result *res;
807
808         res = talloc_zero(tmp_ctx, struct ldb_result);
809         if (!res) {
810                 talloc_free(tmp_ctx);
811                 return ldb_module_oom(module);
812         }
813
814         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
815                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
816                                    LDB_SCOPE_BASE,
817                                    NULL, NULL,
818                                    NULL,
819                                    res, ldb_search_default_callback,
820                                    parent);
821         LDB_REQ_SET_LOCATION(req);
822         if (ret != LDB_SUCCESS) {
823                 talloc_free(tmp_ctx);
824                 return ret;
825         }
826
827         p_ctrl = talloc(req, struct dsdb_control_current_partition);
828         if (p_ctrl == NULL) {
829                 talloc_free(tmp_ctx);
830                 return ldb_module_oom(module);
831         }
832         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
833         p_ctrl->dn = dn;
834
835
836         ret = ldb_request_add_control(req,
837                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
838                                       false, p_ctrl);
839         if (ret != LDB_SUCCESS) {
840                 talloc_free(tmp_ctx);
841                 return ret;
842         }
843
844         /* Run the new request */
845         ret = ldb_next_request(module, req);
846
847         if (ret == LDB_SUCCESS) {
848                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
849         }
850
851         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
852                 /* it hasn't been created yet, which means
853                    an implicit value of zero */
854                 *uSN = 0;
855                 talloc_free(tmp_ctx);
856                 ldb_reset_err_string(ldb);
857                 return LDB_SUCCESS;
858         }
859
860         if (ret != LDB_SUCCESS) {
861                 talloc_free(tmp_ctx);
862                 return ret;
863         }
864
865         if (res->count != 1) {
866                 *uSN = 0;
867                 if (urgent_uSN) {
868                         *urgent_uSN = 0;
869                 }
870         } else {
871                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
872                 if (urgent_uSN) {
873                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
874                 }
875         }
876
877         talloc_free(tmp_ctx);
878
879         return LDB_SUCCESS;
880 }
881
882 /*
883   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
884   partition
885  */
886 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
887                                    uint64_t uSN, uint64_t urgent_uSN,
888                                    struct ldb_request *parent)
889 {
890         struct ldb_context *ldb = ldb_module_get_ctx(module);
891         struct ldb_request *req;
892         struct ldb_message *msg;
893         struct dsdb_control_current_partition *p_ctrl;
894         int ret;
895         struct ldb_result *res;
896
897         msg = ldb_msg_new(module);
898         if (msg == NULL) {
899                 return ldb_module_oom(module);
900         }
901
902         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
903         if (msg->dn == NULL) {
904                 talloc_free(msg);
905                 return ldb_operr(ldb_module_get_ctx(module));
906         }
907
908         res = talloc_zero(msg, struct ldb_result);
909         if (!res) {
910                 talloc_free(msg);
911                 return ldb_module_oom(module);
912         }
913
914         ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
915         if (ret != LDB_SUCCESS) {
916                 talloc_free(msg);
917                 return ret;
918         }
919         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
920
921         /* urgent_uSN is optional so may not be stored */
922         if (urgent_uSN) {
923                 ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
924                                            urgent_uSN);
925                 if (ret != LDB_SUCCESS) {
926                         talloc_free(msg);
927                         return ret;
928                 }
929                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
930         }
931
932
933         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
934         if (p_ctrl == NULL) {
935                 talloc_free(msg);
936                 return ldb_oom(ldb);
937         }
938         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
939         p_ctrl->dn = dn;
940         ret = ldb_build_mod_req(&req, ldb, msg,
941                                 msg,
942                                 NULL,
943                                 res,
944                                 ldb_modify_default_callback,
945                                 parent);
946         LDB_REQ_SET_LOCATION(req);
947 again:
948         if (ret != LDB_SUCCESS) {
949                 talloc_free(msg);
950                 return ret;
951         }
952
953         ret = ldb_request_add_control(req,
954                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
955                                       false, p_ctrl);
956         if (ret != LDB_SUCCESS) {
957                 talloc_free(msg);
958                 return ret;
959         }
960
961         /* Run the new request */
962         ret = ldb_next_request(module, req);
963
964         if (ret == LDB_SUCCESS) {
965                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
966         }
967         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
968                 ret = ldb_build_add_req(&req, ldb, msg,
969                                         msg,
970                                         NULL,
971                                         res,
972                                         ldb_modify_default_callback,
973                                         parent);
974                 LDB_REQ_SET_LOCATION(req);
975                 goto again;
976         }
977
978         talloc_free(msg);
979
980         return ret;
981 }
982
983 bool dsdb_module_am_system(struct ldb_module *module)
984 {
985         struct ldb_context *ldb = ldb_module_get_ctx(module);
986         struct auth_session_info *session_info
987                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
988         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
989 }
990
991 bool dsdb_module_am_administrator(struct ldb_module *module)
992 {
993         struct ldb_context *ldb = ldb_module_get_ctx(module);
994         struct auth_session_info *session_info
995                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
996         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
997 }
998
999 /*
1000   check if the recyclebin is enabled
1001  */
1002 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1003 {
1004         struct ldb_context *ldb = ldb_module_get_ctx(module);
1005         struct ldb_dn *partitions_dn;
1006         struct GUID recyclebin_guid;
1007         int ret;
1008
1009         partitions_dn = samdb_partitions_dn(ldb, module);
1010
1011         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1012
1013         ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
1014         if (ret != LDB_SUCCESS) {
1015                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1016                 talloc_free(partitions_dn);
1017                 return LDB_ERR_UNWILLING_TO_PERFORM;
1018         }
1019
1020         talloc_free(partitions_dn);
1021         return LDB_SUCCESS;
1022 }
1023
1024 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1025                                        struct ldb_message *msg,
1026                                        const char *attr,
1027                                        const int32_t *old_val,
1028                                        const int32_t *new_val)
1029 {
1030         struct ldb_message_element *el;
1031         int ret;
1032         char *vstring;
1033
1034         if (old_val) {
1035                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1036                 if (ret != LDB_SUCCESS) {
1037                         return ret;
1038                 }
1039                 el->num_values = 1;
1040                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1041                 if (!el->values) {
1042                         return ldb_module_oom(module);
1043                 }
1044                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1045                 if (!vstring) {
1046                         return ldb_module_oom(module);
1047                 }
1048                 *el->values = data_blob_string_const(vstring);
1049         }
1050
1051         if (new_val) {
1052                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1053                 if (ret != LDB_SUCCESS) {
1054                         return ret;
1055                 }
1056                 el->num_values = 1;
1057                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1058                 if (!el->values) {
1059                         return ldb_module_oom(module);
1060                 }
1061                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1062                 if (!vstring) {
1063                         return ldb_module_oom(module);
1064                 }
1065                 *el->values = data_blob_string_const(vstring);
1066         }
1067
1068         return LDB_SUCCESS;
1069 }
1070
1071 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1072                                         struct ldb_message *msg,
1073                                         const char *attr,
1074                                         const uint32_t *old_val,
1075                                         const uint32_t *new_val)
1076 {
1077         return dsdb_msg_constrainted_update_int32(module, msg, attr,
1078                                                   (const int32_t *)old_val,
1079                                                   (const int32_t *)new_val);
1080 }
1081
1082 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1083                                        struct ldb_message *msg,
1084                                        const char *attr,
1085                                        const int64_t *old_val,
1086                                        const int64_t *new_val)
1087 {
1088         struct ldb_message_element *el;
1089         int ret;
1090         char *vstring;
1091
1092         if (old_val) {
1093                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1094                 if (ret != LDB_SUCCESS) {
1095                         return ret;
1096                 }
1097                 el->num_values = 1;
1098                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1099                 if (!el->values) {
1100                         return ldb_module_oom(module);
1101                 }
1102                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1103                 if (!vstring) {
1104                         return ldb_module_oom(module);
1105                 }
1106                 *el->values = data_blob_string_const(vstring);
1107         }
1108
1109         if (new_val) {
1110                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1111                 if (ret != LDB_SUCCESS) {
1112                         return ret;
1113                 }
1114                 el->num_values = 1;
1115                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1116                 if (!el->values) {
1117                         return ldb_module_oom(module);
1118                 }
1119                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1120                 if (!vstring) {
1121                         return ldb_module_oom(module);
1122                 }
1123                 *el->values = data_blob_string_const(vstring);
1124         }
1125
1126         return LDB_SUCCESS;
1127 }
1128
1129 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1130                                         struct ldb_message *msg,
1131                                         const char *attr,
1132                                         const uint64_t *old_val,
1133                                         const uint64_t *new_val)
1134 {
1135         return dsdb_msg_constrainted_update_int64(module, msg, attr,
1136                                                   (const int64_t *)old_val,
1137                                                   (const int64_t *)new_val);
1138 }
1139
1140 /*
1141   update an int32 attribute safely via a constrained delete/add
1142  */
1143 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1144                                           struct ldb_dn *dn,
1145                                           const char *attr,
1146                                           const int32_t *old_val,
1147                                           const int32_t *new_val,
1148                                           struct ldb_request *parent)
1149 {
1150         struct ldb_message *msg;
1151         int ret;
1152
1153         msg = ldb_msg_new(module);
1154         msg->dn = dn;
1155
1156         ret = dsdb_msg_constrainted_update_int32(module,
1157                                                  msg, attr,
1158                                                  old_val,
1159                                                  new_val);
1160         if (ret != LDB_SUCCESS) {
1161                 talloc_free(msg);
1162                 return ret;
1163         }
1164
1165         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1166         talloc_free(msg);
1167         return ret;
1168 }
1169
1170 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1171                                            struct ldb_dn *dn,
1172                                            const char *attr,
1173                                            const uint32_t *old_val,
1174                                            const uint32_t *new_val,
1175                                            struct ldb_request *parent)
1176 {
1177         return dsdb_module_constrainted_update_int32(module, dn, attr,
1178                                                      (const int32_t *)old_val,
1179                                                      (const int32_t *)new_val, parent);
1180 }
1181
1182 /*
1183   update an int64 attribute safely via a constrained delete/add
1184  */
1185 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1186                                           struct ldb_dn *dn,
1187                                           const char *attr,
1188                                           const int64_t *old_val,
1189                                           const int64_t *new_val,
1190                                           struct ldb_request *parent)
1191 {
1192         struct ldb_message *msg;
1193         int ret;
1194
1195         msg = ldb_msg_new(module);
1196         msg->dn = dn;
1197
1198         ret = dsdb_msg_constrainted_update_int64(module,
1199                                                  msg, attr,
1200                                                  old_val,
1201                                                  new_val);
1202         if (ret != LDB_SUCCESS) {
1203                 talloc_free(msg);
1204                 return ret;
1205         }
1206
1207         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1208         talloc_free(msg);
1209         return ret;
1210 }
1211
1212 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1213                                            struct ldb_dn *dn,
1214                                            const char *attr,
1215                                            const uint64_t *old_val,
1216                                            const uint64_t *new_val,
1217                                            struct ldb_request *parent)
1218 {
1219         return dsdb_module_constrainted_update_int64(module, dn, attr,
1220                                                      (const int64_t *)old_val,
1221                                                      (const int64_t *)new_val,
1222                                                      parent);
1223 }
1224
1225
1226 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1227                                                     TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1228 {
1229         int ret;
1230         struct ldb_dn *new_dn;
1231         struct ldb_context *ldb = ldb_module_get_ctx(module);
1232         static const char *attrs[] = { "dSHeuristics", NULL };
1233         struct ldb_result *res;
1234
1235         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1236         if (!ldb_dn_add_child_fmt(new_dn,
1237                                    "CN=Directory Service,CN=Windows NT,CN=Services")) {
1238                 talloc_free(new_dn);
1239                 return NULL;
1240         }
1241         ret = dsdb_module_search_dn(module, mem_ctx, &res,
1242                                     new_dn,
1243                                     attrs,
1244                                     DSDB_FLAG_NEXT_MODULE,
1245                                     parent);
1246         if (ret == LDB_SUCCESS && res->count == 1) {
1247                 talloc_free(new_dn);
1248                 return ldb_msg_find_ldb_val(res->msgs[0],
1249                                             "dSHeuristics");
1250         }
1251         talloc_free(new_dn);
1252         return NULL;
1253 }
1254
1255 bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1256 {
1257         TALLOC_CTX *tmp_ctx = talloc_new(module);
1258         bool result;
1259         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1260                                                                      tmp_ctx, parent);
1261         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1262                 result = true;
1263         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1264                 result = false;
1265         } else {
1266                 result = true;
1267         }
1268
1269         talloc_free(tmp_ctx);
1270         return result;
1271 }
1272
1273 bool dsdb_user_password_support(struct ldb_module *module,
1274                                 TALLOC_CTX *mem_ctx,
1275                                 struct ldb_request *parent)
1276 {
1277         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1278         bool result;
1279         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1280                                                                      tmp_ctx,
1281                                                                      parent);
1282         if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1283                 result = false;
1284         } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1285                    (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1286                 result = false;
1287         } else {
1288                 result = true;
1289         }
1290
1291         talloc_free(tmp_ctx);
1292         return result;
1293 }
1294
1295 /*
1296   show the chain of requests, useful for debugging async requests
1297  */
1298 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1299 {
1300         char *s = ldb_module_call_chain(req, req);
1301         DEBUG(level, ("%s\n", s));
1302         talloc_free(s);
1303 }
1304
1305 /*
1306  * Gets back a single-valued attribute by the rules of the DSDB triggers when
1307  * performing a modify operation.
1308  *
1309  * In order that the constraint checking by the "objectclass_attrs" LDB module
1310  * does work properly, the change request should remain similar or only be
1311  * enhanced (no other modifications as deletions, variations).
1312  */
1313 struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1314                                                         const char *attr_name,
1315                                                         enum ldb_request_type operation)
1316 {
1317         struct ldb_message_element *el = NULL;
1318         unsigned int i;
1319
1320         /* We've to walk over all modification entries and consider the last
1321          * non-delete one which belongs to "attr_name".
1322          *
1323          * If "el" is NULL afterwards then that means there was no interesting
1324          * change entry. */
1325         for (i = 0; i < msg->num_elements; i++) {
1326                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1327                         if ((operation == LDB_MODIFY) &&
1328                             (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1329                                                 == LDB_FLAG_MOD_DELETE)) {
1330                                 continue;
1331                         }
1332                         el = &msg->elements[i];
1333                 }
1334         }
1335
1336         return el;
1337 }