b64b934aeb2b0d42ff40d5e7ad68c795588c8f0a
[nivanova/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
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_DELETED |
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_DELETED |
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 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
488 {
489         const struct dsdb_class *last_class = NULL;
490         unsigned int i;
491
492         for (i = 0; i < element->num_values; i++){
493                 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
494
495                 if(tmp_class == NULL) {
496                         continue;
497                 }
498
499                 if(tmp_class->objectClassCategory > 1) {
500                         continue;
501                 }
502
503                 if (!last_class) {
504                         last_class = tmp_class;
505                 } else {
506                         if (tmp_class->subClass_order > last_class->subClass_order)
507                                 last_class = tmp_class;
508                 }
509         }
510
511         return last_class;
512 }
513
514 /*
515   check if a single valued link has multiple non-deleted values
516
517   This is needed when we will be using the RELAX control to stop
518   ldb_tdb from checking single valued links
519  */
520 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
521                                   const struct ldb_message_element *el)
522 {
523         bool found_active = false;
524         unsigned int i;
525
526         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
527             el->num_values < 2) {
528                 return LDB_SUCCESS;
529         }
530
531         for (i=0; i<el->num_values; i++) {
532                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
533                         if (found_active) {
534                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
535                         }
536                         found_active = true;
537                 }
538         }
539
540         return LDB_SUCCESS;
541 }
542
543 int dsdb_check_optional_feature(struct ldb_module *module, struct ldb_dn *scope,
544                                         struct GUID op_feature_guid, bool *feature_enabled)
545 {
546         TALLOC_CTX *tmp_ctx;
547         struct ldb_context *ldb = ldb_module_get_ctx(module);
548         struct ldb_result *res;
549         struct ldb_dn *search_dn;
550         struct GUID search_guid;
551         const char *attrs[] = {"msDS-EnabledFeature", NULL};
552         int ret;
553         unsigned int i;
554         struct ldb_message_element *el;
555
556         *feature_enabled = false;
557
558         tmp_ctx = talloc_new(ldb);
559
560         ret = ldb_search(ldb, tmp_ctx, &res,
561                                         scope, LDB_SCOPE_BASE, attrs,
562                                         NULL);
563         if (ret != LDB_SUCCESS) {
564                 ldb_asprintf_errstring(ldb,
565                                 "Could no find the scope object - dn: %s\n",
566                                 ldb_dn_get_linearized(scope));
567                 talloc_free(tmp_ctx);
568                 return LDB_ERR_OPERATIONS_ERROR;
569         }
570         if (res->msgs[0]->num_elements > 0) {
571
572                 el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
573
574                 attrs[0] = "msDS-OptionalFeatureGUID";
575
576                 for (i=0; i<el->num_values; i++) {
577                         search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
578
579                         ret = ldb_search(ldb, tmp_ctx, &res,
580                                                         search_dn, LDB_SCOPE_BASE, attrs,
581                                                         NULL);
582                         if (ret != LDB_SUCCESS) {
583                                 ldb_asprintf_errstring(ldb,
584                                                 "Could no find object dn: %s\n",
585                                                 ldb_dn_get_linearized(search_dn));
586                                 talloc_free(tmp_ctx);
587                                 return LDB_ERR_OPERATIONS_ERROR;
588                         }
589
590                         search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
591
592                         if (GUID_compare(&search_guid, &op_feature_guid) == 0){
593                                 *feature_enabled = true;
594                                 break;
595                         }
596                 }
597         }
598         talloc_free(tmp_ctx);
599         return LDB_SUCCESS;
600 }
601
602 /*
603   find a 'reference' DN that points at another object
604   (eg. serverReference, rIDManagerReference etc)
605  */
606 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
607                              const char *attribute, struct ldb_dn **dn)
608 {
609         const char *attrs[2];
610         struct ldb_result *res;
611         int ret;
612
613         attrs[0] = attribute;
614         attrs[1] = NULL;
615
616         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
617                                     DSDB_FLAG_NEXT_MODULE);
618         if (ret != LDB_SUCCESS) {
619                 return ret;
620         }
621
622         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
623                                       mem_ctx, res->msgs[0], attribute);
624         if (!*dn) {
625                 ldb_reset_err_string(ldb_module_get_ctx(module));
626                 talloc_free(res);
627                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
628         }
629
630         talloc_free(res);
631         return LDB_SUCCESS;
632 }
633
634 /*
635   find the RID Manager$ DN via the rIDManagerReference attribute in the
636   base DN
637  */
638 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
639 {
640         return dsdb_module_reference_dn(module, mem_ctx,
641                                         ldb_get_default_basedn(ldb_module_get_ctx(module)),
642                                         "rIDManagerReference", dn);
643 }
644
645
646 /*
647   update an integer attribute safely via a constrained delete/add
648  */
649 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
650                                             const char *attr, uint64_t old_val, uint64_t new_val)
651 {
652         struct ldb_message *msg;
653         struct ldb_message_element *el;
654         struct ldb_val v1, v2;
655         int ret;
656         char *vstring;
657
658         msg = ldb_msg_new(module);
659         msg->dn = dn;
660
661         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
662         if (ret != LDB_SUCCESS) {
663                 talloc_free(msg);
664                 return ret;
665         }
666         el->num_values = 1;
667         el->values = &v1;
668         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
669         if (!vstring) {
670                 talloc_free(msg);
671                 return ldb_module_oom(module);
672         }
673         v1 = data_blob_string_const(vstring);
674
675         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
676         if (ret != LDB_SUCCESS) {
677                 talloc_free(msg);
678                 return ret;
679         }
680         el->num_values = 1;
681         el->values = &v2;
682         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
683         if (!vstring) {
684                 talloc_free(msg);
685                 return ldb_module_oom(module);
686         }
687         v2 = data_blob_string_const(vstring);
688
689         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
690         talloc_free(msg);
691         return ret;
692 }
693
694 /*
695   used to chain to the callers callback
696  */
697 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
698 {
699         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
700
701         talloc_steal(up_req, req);
702         return up_req->callback(up_req, ares);
703 }
704
705
706 /*
707   set an integer attribute
708  */
709 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
710                             const char *attr, uint64_t new_val)
711 {
712         struct ldb_message *msg;
713         int ret;
714
715         msg = ldb_msg_new(module);
716         msg->dn = dn;
717
718         ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
719         if (ret != LDB_SUCCESS) {
720                 talloc_free(msg);
721                 return ret;
722         }
723         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
724
725         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
726         talloc_free(msg);
727         return ret;
728 }
729
730 /*
731   load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
732   object for a partition
733  */
734 int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
735                                   uint64_t *uSN, uint64_t *urgent_uSN)
736 {
737         struct ldb_context *ldb = ldb_module_get_ctx(module);
738         struct ldb_request *req;
739         int ret;
740         TALLOC_CTX *tmp_ctx = talloc_new(module);
741         struct dsdb_control_current_partition *p_ctrl;
742         struct ldb_result *res;
743
744         res = talloc_zero(tmp_ctx, struct ldb_result);
745         if (!res) {
746                 talloc_free(tmp_ctx);
747                 return ldb_module_oom(module);
748         }
749
750         ret = ldb_build_search_req(&req, ldb, tmp_ctx,
751                                    ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
752                                    LDB_SCOPE_BASE,
753                                    NULL, NULL,
754                                    NULL,
755                                    res, ldb_search_default_callback,
756                                    NULL);
757         LDB_REQ_SET_LOCATION(req);
758         if (ret != LDB_SUCCESS) {
759                 talloc_free(tmp_ctx);
760                 return ret;
761         }
762
763         p_ctrl = talloc(req, struct dsdb_control_current_partition);
764         if (p_ctrl == NULL) {
765                 talloc_free(tmp_ctx);
766                 return ldb_module_oom(module);
767         }
768         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
769         p_ctrl->dn = dn;
770
771
772         ret = ldb_request_add_control(req,
773                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
774                                       false, p_ctrl);
775         if (ret != LDB_SUCCESS) {
776                 talloc_free(tmp_ctx);
777                 return ret;
778         }
779
780         /* Run the new request */
781         ret = ldb_next_request(module, req);
782
783         if (ret == LDB_SUCCESS) {
784                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
785         }
786
787         if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
788                 /* it hasn't been created yet, which means
789                    an implicit value of zero */
790                 *uSN = 0;
791                 talloc_free(tmp_ctx);
792                 return LDB_SUCCESS;
793         }
794
795         if (ret != LDB_SUCCESS) {
796                 talloc_free(tmp_ctx);
797                 return ret;
798         }
799
800         if (res->count != 1) {
801                 *uSN = 0;
802                 if (urgent_uSN) {
803                         *urgent_uSN = 0;
804                 }
805         } else {
806                 *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
807                 if (urgent_uSN) {
808                         *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
809                 }
810         }
811
812         talloc_free(tmp_ctx);
813
814         return LDB_SUCCESS;
815 }
816
817 /*
818   save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
819   partition
820  */
821 int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
822                                    uint64_t uSN, uint64_t urgent_uSN)
823 {
824         struct ldb_context *ldb = ldb_module_get_ctx(module);
825         struct ldb_request *req;
826         struct ldb_message *msg;
827         struct dsdb_control_current_partition *p_ctrl;
828         int ret;
829         struct ldb_result *res;
830
831         msg = ldb_msg_new(module);
832         if (msg == NULL) {
833                 return ldb_module_oom(module);
834         }
835
836         msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
837         if (msg->dn == NULL) {
838                 talloc_free(msg);
839                 return ldb_operr(ldb_module_get_ctx(module));
840         }
841
842         res = talloc_zero(msg, struct ldb_result);
843         if (!res) {
844                 talloc_free(msg);
845                 return ldb_module_oom(module);
846         }
847
848         ret = ldb_msg_add_fmt(msg, "uSNHighest", "%llu", (unsigned long long)uSN);
849         if (ret != LDB_SUCCESS) {
850                 talloc_free(msg);
851                 return ret;
852         }
853         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
854
855         /* urgent_uSN is optional so may not be stored */
856         if (urgent_uSN) {
857                 ret = ldb_msg_add_fmt(msg, "uSNUrgent", "%llu", (unsigned long long)urgent_uSN);
858                 if (ret != LDB_SUCCESS) {
859                         talloc_free(msg);
860                         return ret;
861                 }
862                 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
863         }
864
865
866         p_ctrl = talloc(msg, struct dsdb_control_current_partition);
867         if (p_ctrl == NULL) {
868                 talloc_free(msg);
869                 return ldb_oom(ldb);
870         }
871         p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
872         p_ctrl->dn = dn;
873         ret = ldb_build_mod_req(&req, ldb, msg,
874                                 msg,
875                                 NULL,
876                                 res,
877                                 ldb_modify_default_callback,
878                                 NULL);
879         LDB_REQ_SET_LOCATION(req);
880 again:
881         if (ret != LDB_SUCCESS) {
882                 talloc_free(msg);
883                 return ret;
884         }
885
886         ret = ldb_request_add_control(req,
887                                       DSDB_CONTROL_CURRENT_PARTITION_OID,
888                                       false, p_ctrl);
889         if (ret != LDB_SUCCESS) {
890                 talloc_free(msg);
891                 return ret;
892         }
893
894         /* Run the new request */
895         ret = ldb_next_request(module, req);
896
897         if (ret == LDB_SUCCESS) {
898                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
899         }
900         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
901                 ret = ldb_build_add_req(&req, ldb, msg,
902                                         msg,
903                                         NULL,
904                                         res,
905                                         ldb_modify_default_callback,
906                                         NULL);
907                 LDB_REQ_SET_LOCATION(req);
908                 goto again;
909         }
910
911         talloc_free(msg);
912
913         return ret;
914 }
915
916 bool dsdb_module_am_system(struct ldb_module *module)
917 {
918         struct ldb_context *ldb = ldb_module_get_ctx(module);
919         struct auth_session_info *session_info
920                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
921         return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
922 }
923
924 bool dsdb_module_am_administrator(struct ldb_module *module)
925 {
926         struct ldb_context *ldb = ldb_module_get_ctx(module);
927         struct auth_session_info *session_info
928                 = talloc_get_type(ldb_get_opaque(ldb, "sessionInfo"), struct auth_session_info);
929         return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
930 }
931
932 /*
933   check if the recyclebin is enabled
934  */
935 int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
936 {
937         struct ldb_context *ldb = ldb_module_get_ctx(module);
938         struct ldb_dn *partitions_dn;
939         struct GUID recyclebin_guid;
940         int ret;
941
942         partitions_dn = samdb_partitions_dn(ldb, module);
943
944         GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
945
946         ret = dsdb_check_optional_feature(module, partitions_dn, recyclebin_guid, enabled);
947         if (ret != LDB_SUCCESS) {
948                 ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
949                 talloc_free(partitions_dn);
950                 return LDB_ERR_UNWILLING_TO_PERFORM;
951         }
952
953         talloc_free(partitions_dn);
954         return LDB_SUCCESS;
955 }
956
957 bool is_attr_in_list(const char * const * attrs, const char *attr)
958 {
959         unsigned int i;
960
961         for (i = 0; attrs[i]; i++) {
962                 if (ldb_attr_cmp(attrs[i], attr) == 0)
963                         return true;
964         }
965
966         return false;
967 }
968
969 int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
970                                        struct ldb_message *msg,
971                                        const char *attr,
972                                        const int32_t *old_val,
973                                        const int32_t *new_val)
974 {
975         struct ldb_message_element *el;
976         int ret;
977         char *vstring;
978
979         if (old_val) {
980                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
981                 if (ret != LDB_SUCCESS) {
982                         return ret;
983                 }
984                 el->num_values = 1;
985                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
986                 if (!el->values) {
987                         return ldb_module_oom(module);
988                 }
989                 vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
990                 if (!vstring) {
991                         return ldb_module_oom(module);
992                 }
993                 *el->values = data_blob_string_const(vstring);
994         }
995
996         if (new_val) {
997                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
998                 if (ret != LDB_SUCCESS) {
999                         return ret;
1000                 }
1001                 el->num_values = 1;
1002                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1003                 if (!el->values) {
1004                         return ldb_module_oom(module);
1005                 }
1006                 vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1007                 if (!vstring) {
1008                         return ldb_module_oom(module);
1009                 }
1010                 *el->values = data_blob_string_const(vstring);
1011         }
1012
1013         return LDB_SUCCESS;
1014 }
1015
1016 int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1017                                         struct ldb_message *msg,
1018                                         const char *attr,
1019                                         const uint32_t *old_val,
1020                                         const uint32_t *new_val)
1021 {
1022         return dsdb_msg_constrainted_update_int32(module, msg, attr,
1023                                                   (const int32_t *)old_val,
1024                                                   (const int32_t *)new_val);
1025 }
1026
1027 int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1028                                        struct ldb_message *msg,
1029                                        const char *attr,
1030                                        const int64_t *old_val,
1031                                        const int64_t *new_val)
1032 {
1033         struct ldb_message_element *el;
1034         int ret;
1035         char *vstring;
1036
1037         if (old_val) {
1038                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1039                 if (ret != LDB_SUCCESS) {
1040                         return ret;
1041                 }
1042                 el->num_values = 1;
1043                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1044                 if (!el->values) {
1045                         return ldb_module_oom(module);
1046                 }
1047                 vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1048                 if (!vstring) {
1049                         return ldb_module_oom(module);
1050                 }
1051                 *el->values = data_blob_string_const(vstring);
1052         }
1053
1054         if (new_val) {
1055                 ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1056                 if (ret != LDB_SUCCESS) {
1057                         return ret;
1058                 }
1059                 el->num_values = 1;
1060                 el->values = talloc_array(msg, struct ldb_val, el->num_values);
1061                 if (!el->values) {
1062                         return ldb_module_oom(module);
1063                 }
1064                 vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1065                 if (!vstring) {
1066                         return ldb_module_oom(module);
1067                 }
1068                 *el->values = data_blob_string_const(vstring);
1069         }
1070
1071         return LDB_SUCCESS;
1072 }
1073
1074 int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1075                                         struct ldb_message *msg,
1076                                         const char *attr,
1077                                         const uint64_t *old_val,
1078                                         const uint64_t *new_val)
1079 {
1080         return dsdb_msg_constrainted_update_int64(module, msg, attr,
1081                                                   (const int64_t *)old_val,
1082                                                   (const int64_t *)new_val);
1083 }
1084
1085 /*
1086   update an int32 attribute safely via a constrained delete/add
1087  */
1088 int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1089                                           struct ldb_dn *dn,
1090                                           const char *attr,
1091                                           const int32_t *old_val,
1092                                           const int32_t *new_val)
1093 {
1094         struct ldb_message *msg;
1095         int ret;
1096
1097         msg = ldb_msg_new(module);
1098         msg->dn = dn;
1099
1100         ret = dsdb_msg_constrainted_update_int32(module,
1101                                                  msg, attr,
1102                                                  old_val,
1103                                                  new_val);
1104         if (ret != LDB_SUCCESS) {
1105                 talloc_free(msg);
1106                 return ret;
1107         }
1108
1109         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1110         talloc_free(msg);
1111         return ret;
1112 }
1113
1114 int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1115                                            struct ldb_dn *dn,
1116                                            const char *attr,
1117                                            const uint32_t *old_val,
1118                                            const uint32_t *new_val)
1119 {
1120         return dsdb_module_constrainted_update_int32(module, dn, attr,
1121                                                      (const int32_t *)old_val,
1122                                                      (const int32_t *)new_val);
1123 }
1124
1125 /*
1126   update an int64 attribute safely via a constrained delete/add
1127  */
1128 int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1129                                           struct ldb_dn *dn,
1130                                           const char *attr,
1131                                           const int64_t *old_val,
1132                                           const int64_t *new_val)
1133 {
1134         struct ldb_message *msg;
1135         int ret;
1136
1137         msg = ldb_msg_new(module);
1138         msg->dn = dn;
1139
1140         ret = dsdb_msg_constrainted_update_int64(module,
1141                                                  msg, attr,
1142                                                  old_val,
1143                                                  new_val);
1144         if (ret != LDB_SUCCESS) {
1145                 talloc_free(msg);
1146                 return ret;
1147         }
1148
1149         ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE);
1150         talloc_free(msg);
1151         return ret;
1152 }
1153
1154 int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1155                                            struct ldb_dn *dn,
1156                                            const char *attr,
1157                                            const uint64_t *old_val,
1158                                            const uint64_t *new_val)
1159 {
1160         return dsdb_module_constrainted_update_int64(module, dn, attr,
1161                                                      (const int64_t *)old_val,
1162                                                      (const int64_t *)new_val);
1163 }
1164
1165
1166 const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1167                                                     TALLOC_CTX *mem_ctx)
1168 {
1169         int ret;
1170         struct ldb_dn *new_dn;
1171         struct ldb_context *ldb = ldb_module_get_ctx(module);
1172         static const char *attrs[] = { "dsHeuristics", NULL };
1173         struct ldb_result *res;
1174
1175         new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1176         if (!ldb_dn_add_child_fmt(new_dn,
1177                                    "CN=Directory Service,CN=Windows NT,CN=Services")) {
1178                 talloc_free(new_dn);
1179                 return NULL;
1180         }
1181         ret = dsdb_module_search_dn(module, mem_ctx, &res,
1182                                     new_dn,
1183                                     attrs,
1184                                     DSDB_FLAG_NEXT_MODULE);
1185         if (ret == LDB_SUCCESS && res->count == 1) {
1186                 talloc_free(new_dn);
1187                 return ldb_msg_find_ldb_val(res->msgs[0],
1188                                             "dsHeuristics");
1189         }
1190         talloc_free(new_dn);
1191         return NULL;
1192 }
1193
1194 bool dsdb_block_anonymous_ops(struct ldb_module *module,
1195                               TALLOC_CTX *mem_ctx)
1196 {
1197         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1198         bool result;
1199         const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1200                                                                      tmp_ctx);
1201         if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1202                 result = true;
1203         } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1204                 result = false;
1205         } else {
1206                 result = true;
1207         }
1208
1209         talloc_free(tmp_ctx);
1210         return result;
1211 }
1212
1213 /*
1214   show the chain of requests, useful for debugging async requests
1215  */
1216 void dsdb_req_chain_debug(struct ldb_request *req, int level)
1217 {
1218         int i=0;
1219
1220         while (req && req->handle) {
1221                 DEBUG(level,("req[%u] %p  : %s\n", i++, req, ldb_req_location(req)));
1222                 req = req->handle->parent;
1223         }
1224 }