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