s4-dsdb Reset the error string after 'expected' errors.
[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 "lib/ldb/include/ldb_private.h"
31 #include "libcli/security/session.h"
32
33 /*
34   search for attrs on one DN, in the modules below
35  */
36 int dsdb_module_search_dn(struct ldb_module *module,
37                           TALLOC_CTX *mem_ctx,
38                           struct ldb_result **_res,
39                           struct ldb_dn *basedn,
40                           const char * const *attrs,
41                           uint32_t dsdb_flags)
42 {
43         int ret;
44         struct ldb_request *req;
45         TALLOC_CTX *tmp_ctx;
46         struct ldb_result *res;
47
48         tmp_ctx = talloc_new(mem_ctx);
49
50         res = talloc_zero(tmp_ctx, struct ldb_result);
51         if (!res) {
52                 talloc_free(tmp_ctx);
53                 return ldb_oom(ldb_module_get_ctx(module));
54         }
55
56         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
57                                    basedn,
58                                    LDB_SCOPE_BASE,
59                                    NULL,
60                                    attrs,
61                                    NULL,
62                                    res,
63                                    ldb_search_default_callback,
64                                    NULL);
65         LDB_REQ_SET_LOCATION(req);
66         if (ret != LDB_SUCCESS) {
67                 talloc_free(tmp_ctx);
68                 return ret;
69         }
70
71         ret = dsdb_request_add_controls(req, dsdb_flags);
72         if (ret != LDB_SUCCESS) {
73                 talloc_free(tmp_ctx);
74                 return ret;
75         }
76
77         /* Run the new request */
78         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
79                 ret = ldb_next_request(module, req);
80         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
81                 ret = ldb_request(ldb_module_get_ctx(module), req);
82         } else {
83                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
84                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
85                 ret = ops->search(module, req);
86         }
87         if (ret == LDB_SUCCESS) {
88                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
89         }
90
91         if (ret != LDB_SUCCESS) {
92                 talloc_free(tmp_ctx);
93                 return ret;
94         }
95
96         if (res->count != 1) {
97                 /* we may be reading a DB that does not have the 'check base on search' option... */
98                 ret = LDB_ERR_NO_SUCH_OBJECT;
99                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
100                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
101                                        ldb_dn_get_linearized(basedn), res->count);
102         } else {
103                 *_res = talloc_steal(mem_ctx, res);
104         }
105         talloc_free(tmp_ctx);
106         return ret;
107 }
108
109 /*
110   search for attrs in the modules below
111  */
112 int dsdb_module_search(struct ldb_module *module,
113                        TALLOC_CTX *mem_ctx,
114                        struct ldb_result **_res,
115                        struct ldb_dn *basedn, enum ldb_scope scope, 
116                        const char * const *attrs,
117                        int dsdb_flags, 
118                        const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
119 {
120         int ret;
121         struct ldb_request *req;
122         TALLOC_CTX *tmp_ctx;
123         struct ldb_result *res;
124         va_list ap;
125         char *expression;
126
127         tmp_ctx = talloc_new(mem_ctx);
128
129         if (format) {
130                 va_start(ap, format);
131                 expression = talloc_vasprintf(tmp_ctx, format, ap);
132                 va_end(ap);
133
134                 if (!expression) {
135                         talloc_free(tmp_ctx);
136                         return ldb_oom(ldb_module_get_ctx(module));
137                 }
138         } else {
139                 expression = NULL;
140         }
141
142         res = talloc_zero(tmp_ctx, struct ldb_result);
143         if (!res) {
144                 talloc_free(tmp_ctx);
145                 return ldb_oom(ldb_module_get_ctx(module));
146         }
147
148         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
149                                    basedn,
150                                    scope,
151                                    expression,
152                                    attrs,
153                                    NULL,
154                                    res,
155                                    ldb_search_default_callback,
156                                    NULL);
157         LDB_REQ_SET_LOCATION(req);
158         if (ret != LDB_SUCCESS) {
159                 talloc_free(tmp_ctx);
160                 return ret;
161         }
162
163         ret = dsdb_request_add_controls(req, dsdb_flags);
164         if (ret != LDB_SUCCESS) {
165                 talloc_free(tmp_ctx);
166                 return ret;
167         }
168
169         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
170                 ret = ldb_next_request(module, req);
171         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
172                 ret = ldb_request(ldb_module_get_ctx(module), req);
173         } else {
174                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
175                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
176                 ret = ops->search(module, req);
177         }
178         if (ret == LDB_SUCCESS) {
179                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
180         }
181
182         talloc_free(req);
183         if (ret == LDB_SUCCESS) {
184                 *_res = talloc_steal(mem_ctx, res);
185         }
186         talloc_free(tmp_ctx);
187         return ret;
188 }
189
190 /*
191   find a DN given a GUID. This searches across all partitions
192  */
193 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
194                            const struct GUID *guid, struct ldb_dn **dn)
195 {
196         struct ldb_result *res;
197         const char *attrs[] = { NULL };
198         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
199         int ret;
200
201         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
202                                  attrs,
203                                  DSDB_FLAG_NEXT_MODULE |
204                                  DSDB_SEARCH_SHOW_RECYCLED |
205                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
206                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
207                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
208         if (ret != LDB_SUCCESS) {
209                 talloc_free(tmp_ctx);
210                 return ret;
211         }
212         if (res->count == 0) {
213                 talloc_free(tmp_ctx);
214                 return LDB_ERR_NO_SUCH_OBJECT;
215         }
216         if (res->count != 1) {
217                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
218                                        GUID_string(tmp_ctx, guid));
219                 talloc_free(tmp_ctx);
220                 return LDB_ERR_OPERATIONS_ERROR;
221         }
222
223         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
224
225         talloc_free(tmp_ctx);
226         return LDB_SUCCESS;
227 }
228
229 /*
230   find a GUID given a DN.
231  */
232 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
233 {
234         const char *attrs[] = { NULL };
235         struct ldb_result *res;
236         TALLOC_CTX *tmp_ctx = talloc_new(module);
237         int ret;
238         NTSTATUS status;
239
240         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
241                                     DSDB_FLAG_NEXT_MODULE |
242                                     DSDB_SEARCH_SHOW_RECYCLED |
243                                     DSDB_SEARCH_SHOW_EXTENDED_DN);
244         if (ret != LDB_SUCCESS) {
245                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
246                                        ldb_dn_get_linearized(dn));
247                 talloc_free(tmp_ctx);
248                 return ret;
249         }
250
251         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
252         if (!NT_STATUS_IS_OK(status)) {
253                 talloc_free(tmp_ctx);
254                 return ldb_operr(ldb_module_get_ctx(module));
255         }
256
257         talloc_free(tmp_ctx);
258         return LDB_SUCCESS;
259 }
260
261 /*
262   a ldb_modify request operating on modules below the
263   current module
264  */
265 int dsdb_module_modify(struct ldb_module *module,
266                        const struct ldb_message *message,
267                        uint32_t dsdb_flags)
268 {
269         struct ldb_request *mod_req;
270         int ret;
271         struct ldb_context *ldb = ldb_module_get_ctx(module);
272         TALLOC_CTX *tmp_ctx = talloc_new(module);
273         struct ldb_result *res;
274
275         res = talloc_zero(tmp_ctx, struct ldb_result);
276         if (!res) {
277                 talloc_free(tmp_ctx);
278                 return ldb_oom(ldb_module_get_ctx(module));
279         }
280
281         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
282                                 message,
283                                 NULL,
284                                 res,
285                                 ldb_modify_default_callback,
286                                 NULL);
287         LDB_REQ_SET_LOCATION(mod_req);
288         if (ret != LDB_SUCCESS) {
289                 talloc_free(tmp_ctx);
290                 return ret;
291         }
292
293         ret = dsdb_request_add_controls(mod_req, dsdb_flags);
294         if (ret != LDB_SUCCESS) {
295                 talloc_free(tmp_ctx);
296                 return ret;
297         }
298
299         /* Run the new request */
300         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
301                 ret = ldb_next_request(module, mod_req);
302         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
303                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
304         } else {
305                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
306                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
307                 ret = ops->modify(module, mod_req);
308         }
309         if (ret == LDB_SUCCESS) {
310                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
311         }
312
313         talloc_free(tmp_ctx);
314         return ret;
315 }
316
317
318
319 /*
320   a ldb_rename request operating on modules below the
321   current module
322  */
323 int dsdb_module_rename(struct ldb_module *module,
324                       struct ldb_dn *olddn, struct ldb_dn *newdn,
325                       uint32_t dsdb_flags)
326 {
327         struct ldb_request *req;
328         int ret;
329         struct ldb_context *ldb = ldb_module_get_ctx(module);
330         TALLOC_CTX *tmp_ctx = talloc_new(module);
331         struct ldb_result *res;
332
333         res = talloc_zero(tmp_ctx, struct ldb_result);
334         if (!res) {
335                 talloc_free(tmp_ctx);
336                 return ldb_oom(ldb_module_get_ctx(module));
337         }
338
339         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
340                                    olddn,
341                                    newdn,
342                                    NULL,
343                                    res,
344                                    ldb_modify_default_callback,
345                                    NULL);
346         LDB_REQ_SET_LOCATION(req);
347         if (ret != LDB_SUCCESS) {
348                 talloc_free(tmp_ctx);
349                 return ret;
350         }
351
352         ret = dsdb_request_add_controls(req, dsdb_flags);
353         if (ret != LDB_SUCCESS) {
354                 talloc_free(tmp_ctx);
355                 return ret;
356         }
357
358         /* Run the new request */
359         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
360                 ret = ldb_next_request(module, req);
361         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
362                 ret = ldb_request(ldb_module_get_ctx(module), req);
363         } else {
364                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
365                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
366                 ret = ops->rename(module, req);
367         }
368         if (ret == LDB_SUCCESS) {
369                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
370         }
371
372         talloc_free(tmp_ctx);
373         return ret;
374 }
375
376 /*
377   a ldb_add request operating on modules below the
378   current module
379  */
380 int dsdb_module_add(struct ldb_module *module,
381                     const struct ldb_message *message,
382                     uint32_t dsdb_flags)
383 {
384         struct ldb_request *req;
385         int ret;
386         struct ldb_context *ldb = ldb_module_get_ctx(module);
387         TALLOC_CTX *tmp_ctx = talloc_new(module);
388         struct ldb_result *res;
389
390         res = talloc_zero(tmp_ctx, struct ldb_result);
391         if (!res) {
392                 talloc_free(tmp_ctx);
393                 return ldb_oom(ldb_module_get_ctx(module));
394         }
395
396         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
397                                 message,
398                                 NULL,
399                                 res,
400                                 ldb_modify_default_callback,
401                                 NULL);
402         LDB_REQ_SET_LOCATION(req);
403         if (ret != LDB_SUCCESS) {
404                 talloc_free(tmp_ctx);
405                 return ret;
406         }
407
408         ret = dsdb_request_add_controls(req, dsdb_flags);
409         if (ret != LDB_SUCCESS) {
410                 talloc_free(tmp_ctx);
411                 return ret;
412         }
413
414         /* Run the new request */
415         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
416                 ret = ldb_next_request(module, req);
417         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
418                 ret = ldb_request(ldb_module_get_ctx(module), req);
419         } else {
420                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
421                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
422                 ret = ops->add(module, req);
423         }
424         if (ret == LDB_SUCCESS) {
425                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
426         }
427
428         talloc_free(tmp_ctx);
429         return ret;
430 }
431
432 /*
433   a ldb_delete request operating on modules below the
434   current module
435  */
436 int dsdb_module_del(struct ldb_module *module,
437                     struct ldb_dn *dn,
438                     uint32_t dsdb_flags)
439 {
440         struct ldb_request *req;
441         int ret;
442         struct ldb_context *ldb = ldb_module_get_ctx(module);
443         TALLOC_CTX *tmp_ctx = talloc_new(module);
444         struct ldb_result *res;
445
446         res = talloc_zero(tmp_ctx, struct ldb_result);
447         if (!res) {
448                 talloc_free(tmp_ctx);
449                 return ldb_oom(ldb);
450         }
451
452         ret = ldb_build_del_req(&req, ldb, tmp_ctx,
453                                 dn,
454                                 NULL,
455                                 res,
456                                 ldb_modify_default_callback,
457                                 NULL);
458         LDB_REQ_SET_LOCATION(req);
459         if (ret != LDB_SUCCESS) {
460                 talloc_free(tmp_ctx);
461                 return ret;
462         }
463
464         ret = dsdb_request_add_controls(req, dsdb_flags);
465         if (ret != LDB_SUCCESS) {
466                 talloc_free(tmp_ctx);
467                 return ret;
468         }
469
470         /* Run the new request */
471         if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
472                 ret = ldb_next_request(module, req);
473         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
474                 ret = ldb_request(ldb_module_get_ctx(module), req);
475         } else {
476                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
477                 SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
478                 ret = ops->del(module, req);
479         }
480         if (ret == LDB_SUCCESS) {
481                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
482         }
483
484         talloc_free(tmp_ctx);
485         return ret;
486 }
487
488 /*
489   check if a single valued link has multiple non-deleted values
490
491   This is needed when we will be using the RELAX control to stop
492   ldb_tdb from checking single valued links
493  */
494 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
495                                   const struct ldb_message_element *el)
496 {
497         bool found_active = false;
498         unsigned int i;
499
500         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
501             el->num_values < 2) {
502                 return LDB_SUCCESS;
503         }
504
505         for (i=0; i<el->num_values; i++) {
506                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
507                         if (found_active) {
508                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
509                         }
510                         found_active = true;
511                 }
512         }
513
514         return LDB_SUCCESS;
515 }
516
517 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
518                                         struct GUID op_feature_guid, bool *feature_enabled)
519 {
520         TALLOC_CTX *tmp_ctx;
521         struct ldb_context *ldb = ldb_module_get_ctx(module);
522         struct ldb_result *res;
523         struct ldb_dn *search_dn;
524         struct GUID search_guid;
525         const char *attrs[] = {"msDS-EnabledFeature", NULL};
526         int ret;
527         unsigned int i;
528         struct ldb_message_element *el;
529
530         *feature_enabled = false;
531
532         tmp_ctx = talloc_new(ldb);
533
534         ret = ldb_search(ldb, tmp_ctx, &res,
535                                         scope, LDB_SCOPE_BASE, attrs,
536                                         NULL);
537         if (ret != LDB_SUCCESS) {
538                 ldb_asprintf_errstring(ldb,
539                                 "Could no find the scope object - dn: %s\n",
540                                 ldb_dn_get_linearized(scope));
541                 talloc_free(tmp_ctx);
542                 return LDB_ERR_OPERATIONS_ERROR;
543         }
544         if (res->msgs[0]->num_elements > 0) {
545
546                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
547
548                 attrs[0] = "msDS-OptionalFeatureGUID";
549
550                 for (i=0; i<el->num_values; i++) {
551                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
552
553                         ret = ldb_search(ldb, tmp_ctx, &res,
554                                                         search_dn, LDB_SCOPE_BASE, attrs,
555                                                         NULL);
556                         if (ret != LDB_SUCCESS) {
557                                 ldb_asprintf_errstring(ldb,
558                                                 "Could no find object dn: %s\n",
559                                                 ldb_dn_get_linearized(search_dn));
560                                 talloc_free(tmp_ctx);
561                                 return LDB_ERR_OPERATIONS_ERROR;
562                         }
563
564                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
565
566                         if (GUID_compare(&search_guid, &op_feature_guid) == 0){
567                                 *feature_enabled = true;
568                                 break;
569                         }
570                 }
571         }
572         talloc_free(tmp_ctx);
573         return LDB_SUCCESS;
574 }
575
576 /*
577   find a 'reference' DN that points at another object
578   (eg. serverReference, rIDManagerReference etc)
579  */
580 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
581                              const char *attribute, struct ldb_dn **dn)
582 {
583         const char *attrs[2];
584         struct ldb_result *res;
585         int ret;
586
587         attrs[0] = attribute;
588         attrs[1] = NULL;
589
590         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
591                                     DSDB_FLAG_NEXT_MODULE);
592         if (ret != LDB_SUCCESS) {
593                 return ret;
594         }
595
596         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
597                                       mem_ctx, res->msgs[0], attribute);
598         if (!*dn) {
599                 ldb_reset_err_string(ldb_module_get_ctx(module));
600                 talloc_free(res);
601                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
602         }
603
604         talloc_free(res);
605         return LDB_SUCCESS;
606 }
607
608 /*
609   find the RID Manager$ DN via the rIDManagerReference attribute in the
610   base DN
611  */
612 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
613 {
614         return dsdb_module_reference_dn(module, mem_ctx,
615                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
616                                         "rIDManagerReference", dn);
617 }
618
619 /*
620   used to chain to the callers callback
621  */
622 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
623 {
624         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
625
626         talloc_steal(up_req, req);
627         return up_req->callback(up_req, ares);
628 }
629
630 /*
631   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
632   object for a partition
633  */
634 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
635                                   uint64_t *uSN, uint64_t *urgent_uSN)
636 {
637         struct ldb_context *ldb = ldb_module_get_ctx(module);
638         struct ldb_request *req;
639         int ret;
640         TALLOC_CTX *tmp_ctx = talloc_new(module);
641         struct dsdb_control_current_partition *p_ctrl;
642         struct ldb_result *res;
643
644         res = talloc_zero(tmp_ctx, struct ldb_result);
645         if (!res) {
646                 talloc_free(tmp_ctx);
647                 return ldb_module_oom(module);
648         }
649
650         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
651                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
652                                    LDB_SCOPE_BASE,
653                                    NULL, NULL,
654                                    NULL,
655                                    res, ldb_search_default_callback,
656                                    NULL);
657         LDB_REQ_SET_LOCATION(req);
658         if (ret != LDB_SUCCESS) {
659                 talloc_free(tmp_ctx);
660                 return ret;
661         }
662
663         p_ctrl = talloc(req, struct dsdb_control_current_partition);
664         if (p_ctrl == NULL) {
665                 talloc_free(tmp_ctx);
666                 return ldb_module_oom(module);
667         }
668         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
669         p_ctrl->dn = dn;
670
671
672         ret = ldb_request_add_control(req,
673                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
674                                       false, p_ctrl);
675         if (ret != LDB_SUCCESS) {
676                 talloc_free(tmp_ctx);
677                 return ret;
678         }
679
680         /* Run the new request */
681         ret = ldb_next_request(module, req);
682
683         if (ret == LDB_SUCCESS) {
684                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
685         }
686
687         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
688                 /* it hasn't been created yet, which means
689                    an implicit value of zero */
690                 *uSN = 0;
691                 talloc_free(tmp_ctx);
692                 ldb_reset_err_string(ldb);
693                 return LDB_SUCCESS;
694         }
695
696         if (ret != LDB_SUCCESS) {
697                 talloc_free(tmp_ctx);
698                 return ret;
699         }
700
701         if (res->count != 1) {
702                 *uSN = 0;
703                 if (urgent_uSN) {
704                         *urgent_uSN = 0;
705                 }
706         } else {
707                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
708                 if (urgent_uSN) {
709                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
710                 }
711         }
712
713         talloc_free(tmp_ctx);
714
715         return LDB_SUCCESS;
716 }
717
718 /*
719   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
720   partition
721  */
722 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
723                                    uint64_t uSN, uint64_t urgent_uSN)
724 {
725         struct ldb_context *ldb = ldb_module_get_ctx(module);
726         struct ldb_request *req;
727         struct ldb_message *msg;
728         struct dsdb_control_current_partition *p_ctrl;
729         int ret;
730         struct ldb_result *res;
731
732         msg = ldb_msg_new(module);
733         if (msg == NULL) {
734                 return ldb_module_oom(module);
735         }
736
737         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
738         if (msg->dn == NULL) {
739                 talloc_free(msg);
740                 return ldb_operr(ldb_module_get_ctx(module));
741         }
742
743         res = talloc_zero(msg, struct ldb_result);
744         if (!res) {
745                 talloc_free(msg);
746                 return ldb_module_oom(module);
747         }
748
749         ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
750         if (ret != LDB_SUCCESS) {
751                 talloc_free(msg);
752                 return ret;
753         }
754         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
755
756         /* urgent_uSN is optional so may not be stored */
757         if (urgent_uSN) {
758                 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)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                               TALLOC_CTX *mem_ctx)
1085 {
1086         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1087         bool result;
1088         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1089                                                                      tmp_ctx);
1090         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1091                 result = true;
1092         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1093                 result = false;
1094         } else {
1095                 result = true;
1096         }
1097
1098         talloc_free(tmp_ctx);
1099         return result;
1100 }
1101
1102 /*
1103   show the chain of requests, useful for debugging async requests
1104  */
1105 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1106 {
1107         int i=0;
1108
1109         while (req && req->handle) {
1110                 DEBUG(level,("req[%u] %p  : %s\n", i++, req, ldb_req_location(req)));
1111                 req = req->handle->parent;
1112         }
1113 }