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