s4-dsdb: added dsdb_module_am_system()
[ira/wip.git] / source4 / dsdb / samdb / ldb_modules / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 2009
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "ldb.h"
24 #include "ldb_module.h"
25 #include "librpc/ndr/libndr.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "util.h"
29 #include "libcli/security/security.h"
30
31 /*
32   add a set of controls to a ldb_request structure based on a set of
33   flags. See util.h for a list of available flags
34  */
35 int dsdb_request_add_controls(struct ldb_module *module, struct ldb_request *req, uint32_t dsdb_flags)
36 {
37         int ret;
38         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
39                 struct ldb_search_options_control *options;
40                 /* Using the phantom root control allows us to search all partitions */
41                 options = talloc(req, struct ldb_search_options_control);
42                 if (options == NULL) {
43                         ldb_module_oom(module);
44                         return LDB_ERR_OPERATIONS_ERROR;
45                 }
46                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
47                 
48                 ret = ldb_request_add_control(req,
49                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
50                                               true, options);
51                 if (ret != LDB_SUCCESS) {
52                         return ret;
53                 }
54         }
55
56         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
57                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
58                 if (ret != LDB_SUCCESS) {
59                         return ret;
60                 }
61         }
62
63         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
64                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
65                 if (ret != LDB_SUCCESS) {
66                         return ret;
67                 }
68         }
69
70         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
71                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
72                 if (!extended_ctrl) {
73                         ldb_module_oom(module);
74                         return LDB_ERR_OPERATIONS_ERROR;
75                 }
76                 extended_ctrl->type = 1;
77                 
78                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
79                 if (ret != LDB_SUCCESS) {
80                         return ret;
81                 }
82         }
83
84         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
85                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
86                 if (ret != LDB_SUCCESS) {
87                         return ret;
88                 }
89         }
90
91         if (dsdb_flags & DSDB_MODIFY_RELAX) {
92                 ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
93                 if (ret != LDB_SUCCESS) {
94                         return ret;
95                 }
96         }
97
98         return LDB_SUCCESS;
99 }
100
101 /*
102   search for attrs on one DN, in the modules below
103  */
104 int dsdb_module_search_dn(struct ldb_module *module,
105                           TALLOC_CTX *mem_ctx,
106                           struct ldb_result **_res,
107                           struct ldb_dn *basedn,
108                           const char * const *attrs,
109                           uint32_t dsdb_flags)
110 {
111         int ret;
112         struct ldb_request *req;
113         TALLOC_CTX *tmp_ctx;
114         struct ldb_result *res;
115
116         tmp_ctx = talloc_new(mem_ctx);
117
118         res = talloc_zero(tmp_ctx, struct ldb_result);
119         if (!res) {
120                 return LDB_ERR_OPERATIONS_ERROR;
121         }
122
123         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
124                                    basedn,
125                                    LDB_SCOPE_BASE,
126                                    NULL,
127                                    attrs,
128                                    NULL,
129                                    res,
130                                    ldb_search_default_callback,
131                                    NULL);
132         if (ret != LDB_SUCCESS) {
133                 talloc_free(tmp_ctx);
134                 return ret;
135         }
136
137         ret = dsdb_request_add_controls(module, req, dsdb_flags);
138         if (ret != LDB_SUCCESS) {
139                 talloc_free(tmp_ctx);
140                 return ret;
141         }
142
143         ret = ldb_next_request(module, req);
144         if (ret == LDB_SUCCESS) {
145                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
146         }
147
148         if (ret != LDB_SUCCESS) {
149                 talloc_free(tmp_ctx);
150                 return ret;
151         }
152
153         if (res->count != 1) {
154                 /* we may be reading a DB that does not have the 'check base on search' option... */
155                 ret = LDB_ERR_NO_SUCH_OBJECT;
156                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
157                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
158                                        ldb_dn_get_linearized(basedn), res->count);
159         } else {
160                 *_res = talloc_steal(mem_ctx, res);
161         }
162         talloc_free(tmp_ctx);
163         return ret;
164 }
165
166 /*
167   search for attrs in the modules below
168  */
169 int dsdb_module_search(struct ldb_module *module,
170                        TALLOC_CTX *mem_ctx,
171                        struct ldb_result **_res,
172                        struct ldb_dn *basedn, enum ldb_scope scope, 
173                        const char * const *attrs,
174                        int dsdb_flags, 
175                        const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
176 {
177         int ret;
178         struct ldb_request *req;
179         TALLOC_CTX *tmp_ctx;
180         struct ldb_result *res;
181         va_list ap;
182         char *expression;
183
184         tmp_ctx = talloc_new(mem_ctx);
185
186         va_start(ap, format);
187         expression = talloc_vasprintf(tmp_ctx, format, ap);
188         va_end(ap);
189
190         res = talloc_zero(tmp_ctx, struct ldb_result);
191         if (!res) {
192                 return LDB_ERR_OPERATIONS_ERROR;
193         }
194
195         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
196                                    basedn,
197                                    scope,
198                                    expression,
199                                    attrs,
200                                    NULL,
201                                    res,
202                                    ldb_search_default_callback,
203                                    NULL);
204         if (ret != LDB_SUCCESS) {
205                 talloc_free(tmp_ctx);
206                 return ret;
207         }
208
209         ret = dsdb_request_add_controls(module, req, dsdb_flags);
210         if (ret != LDB_SUCCESS) {
211                 talloc_free(tmp_ctx);
212                 return ret;
213         }
214
215         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
216                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
217                 ret = ops->search(module, req);
218         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
219                 ret = ldb_request(ldb_module_get_ctx(module), req);
220         } else {
221                 ret = ldb_next_request(module, req);
222         }
223         if (ret == LDB_SUCCESS) {
224                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
225         }
226
227         talloc_free(req);
228         if (ret == LDB_SUCCESS) {
229                 *_res = talloc_steal(mem_ctx, res);
230         }
231         talloc_free(tmp_ctx);
232         return ret;
233 }
234
235 /*
236   find a DN given a GUID. This searches across all partitions
237  */
238 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
239                            const struct GUID *guid, struct ldb_dn **dn)
240 {
241         struct ldb_result *res;
242         const char *attrs[] = { NULL };
243         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
244         int ret;
245
246         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
247                                  attrs,
248                                  DSDB_SEARCH_SHOW_DELETED |
249                                  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
250                                  DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
251                                  "objectGUID=%s", GUID_string(tmp_ctx, guid));
252         if (ret != LDB_SUCCESS) {
253                 talloc_free(tmp_ctx);
254                 return ret;
255         }
256         if (res->count == 0) {
257                 talloc_free(tmp_ctx);
258                 return LDB_ERR_NO_SUCH_OBJECT;
259         }
260         if (res->count != 1) {
261                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
262                                        GUID_string(tmp_ctx, guid));
263                 talloc_free(tmp_ctx);
264                 return LDB_ERR_OPERATIONS_ERROR;
265         }
266
267         *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
268
269         talloc_free(tmp_ctx);
270         return LDB_SUCCESS;
271 }
272
273 /*
274   find a GUID given a DN.
275  */
276 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
277 {
278         const char *attrs[] = { NULL };
279         struct ldb_result *res;
280         TALLOC_CTX *tmp_ctx = talloc_new(module);
281         int ret;
282         NTSTATUS status;
283
284         ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
285                                     DSDB_SEARCH_SHOW_DELETED|
286                                     DSDB_SEARCH_SHOW_EXTENDED_DN);
287         if (ret != LDB_SUCCESS) {
288                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
289                                        ldb_dn_get_linearized(dn));
290                 talloc_free(tmp_ctx);
291                 return ret;
292         }
293
294         status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
295         if (!NT_STATUS_IS_OK(status)) {
296                 talloc_free(tmp_ctx);
297                 return LDB_ERR_OPERATIONS_ERROR;
298         }
299
300         talloc_free(tmp_ctx);
301         return LDB_SUCCESS;
302 }
303
304 /*
305   a ldb_modify request operating on modules below the
306   current module
307  */
308 int dsdb_module_modify(struct ldb_module *module,
309                        const struct ldb_message *message,
310                        uint32_t dsdb_flags)
311 {
312         struct ldb_request *mod_req;
313         int ret;
314         struct ldb_context *ldb = ldb_module_get_ctx(module);
315         TALLOC_CTX *tmp_ctx = talloc_new(module);
316
317         ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
318                                 message,
319                                 NULL,
320                                 NULL,
321                                 ldb_op_default_callback,
322                                 NULL);
323         if (ret != LDB_SUCCESS) {
324                 talloc_free(tmp_ctx);
325                 return ret;
326         }
327
328         ret = dsdb_request_add_controls(module, mod_req, dsdb_flags);
329         if (ret != LDB_SUCCESS) {
330                 talloc_free(tmp_ctx);
331                 return ret;
332         }
333
334         /* Run the new request */
335         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
336                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
337                 ret = ops->modify(module, mod_req);
338         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
339                 ret = ldb_request(ldb_module_get_ctx(module), mod_req);
340         } else {
341                 ret = ldb_next_request(module, mod_req);
342         }
343         if (ret == LDB_SUCCESS) {
344                 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
345         }
346
347         talloc_free(tmp_ctx);
348         return ret;
349 }
350
351
352
353 /*
354   a ldb_rename request operating on modules below the
355   current module
356  */
357 int dsdb_module_rename(struct ldb_module *module,
358                       struct ldb_dn *olddn, struct ldb_dn *newdn,
359                       uint32_t dsdb_flags)
360 {
361         struct ldb_request *req;
362         int ret;
363         struct ldb_context *ldb = ldb_module_get_ctx(module);
364         TALLOC_CTX *tmp_ctx = talloc_new(module);
365
366         ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
367                                    olddn,
368                                    newdn,
369                                    NULL,
370                                    NULL,
371                                    ldb_op_default_callback,
372                                    NULL);
373         if (ret != LDB_SUCCESS) {
374                 talloc_free(tmp_ctx);
375                 return ret;
376         }
377
378         ret = dsdb_request_add_controls(module, req, dsdb_flags);
379         if (ret != LDB_SUCCESS) {
380                 talloc_free(tmp_ctx);
381                 return ret;
382         }
383
384         /* Run the new request */
385         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
386                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
387                 ret = ops->rename(module, req);
388         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
389                 ret = ldb_request(ldb_module_get_ctx(module), req);
390         } else {
391                 ret = ldb_next_request(module, req);
392         }
393         if (ret == LDB_SUCCESS) {
394                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
395         }
396
397         talloc_free(tmp_ctx);
398         return ret;
399 }
400
401 /*
402   a ldb_add request operating on modules below the
403   current module
404  */
405 int dsdb_module_add(struct ldb_module *module,
406                     const struct ldb_message *message,
407                     uint32_t dsdb_flags)
408 {
409         struct ldb_request *req;
410         int ret;
411         struct ldb_context *ldb = ldb_module_get_ctx(module);
412         TALLOC_CTX *tmp_ctx = talloc_new(module);
413
414         ret = ldb_build_add_req(&req, ldb, tmp_ctx,
415                                 message,
416                                 NULL,
417                                 NULL,
418                                 ldb_op_default_callback,
419                                 NULL);
420         if (ret != LDB_SUCCESS) {
421                 talloc_free(tmp_ctx);
422                 return ret;
423         }
424
425         ret = dsdb_request_add_controls(module, req, dsdb_flags);
426         if (ret != LDB_SUCCESS) {
427                 talloc_free(tmp_ctx);
428                 return ret;
429         }
430
431         /* Run the new request */
432         if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
433                 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
434                 ret = ops->add(module, req);
435         } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
436                 ret = ldb_request(ldb_module_get_ctx(module), req);
437         } else {
438                 ret = ldb_next_request(module, req);
439         }
440         if (ret == LDB_SUCCESS) {
441                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
442         }
443
444         talloc_free(tmp_ctx);
445         return ret;
446 }
447
448
449 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
450 {
451         const struct dsdb_class *last_class = NULL;
452         int i;
453
454         for (i = 0; i < element->num_values; i++){
455                 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
456
457                 if(tmp_class == NULL) {
458                         continue;
459                 }
460
461                 if(tmp_class->objectClassCategory == 3) {
462                         continue;
463                 }
464
465                 if (!last_class) {
466                         last_class = tmp_class;
467                 } else {
468                         if (tmp_class->subClass_order > last_class->subClass_order)
469                                 last_class = tmp_class;
470                 }
471         }
472
473         return last_class;
474 }
475
476 /*
477   check if a single valued link has multiple non-deleted values
478
479   This is needed when we will be using the RELAX control to stop
480   ldb_tdb from checking single valued links
481  */
482 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
483                                   const struct ldb_message_element *el)
484 {
485         bool found_active = false;
486         int i;
487
488         if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
489             el->num_values < 2) {
490                 return LDB_SUCCESS;
491         }
492
493         for (i=0; i<el->num_values; i++) {
494                 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
495                         if (found_active) {
496                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
497                         }
498                         found_active = true;
499                 }
500         }
501
502         return LDB_SUCCESS;
503 }
504
505
506 /*
507   find a 'reference' DN that points at another object
508   (eg. serverReference, rIDManagerReference etc)
509  */
510 int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
511                              const char *attribute, struct ldb_dn **dn)
512 {
513         const char *attrs[2];
514         struct ldb_result *res;
515         int ret;
516
517         attrs[0] = attribute;
518         attrs[1] = NULL;
519
520         ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 0);
521         if (ret != LDB_SUCCESS) {
522                 return ret;
523         }
524
525         *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
526                                       mem_ctx, res->msgs[0], attribute);
527         if (!*dn) {
528                 talloc_free(res);
529                 return LDB_ERR_NO_SUCH_ATTRIBUTE;
530         }
531
532         talloc_free(res);
533         return LDB_SUCCESS;
534 }
535
536 /*
537   find the RID Manager$ DN via the rIDManagerReference attribute in the
538   base DN
539  */
540 int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
541 {
542         return dsdb_module_reference_dn(module, mem_ctx,
543                                         samdb_base_dn(ldb_module_get_ctx(module)),
544                                         "rIDManagerReference", dn);
545 }
546
547
548 /*
549   update an integer attribute safely via a constrained delete/add
550  */
551 int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
552                                             const char *attr, uint64_t old_val, uint64_t new_val)
553 {
554         struct ldb_message *msg;
555         struct ldb_message_element *el;
556         struct ldb_val v1, v2;
557         int ret;
558         char *vstring;
559
560         msg = ldb_msg_new(module);
561         msg->dn = dn;
562
563         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
564         if (ret != LDB_SUCCESS) {
565                 talloc_free(msg);
566                 return ret;
567         }
568         el->num_values = 1;
569         el->values = &v1;
570         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
571         if (!vstring) {
572                 ldb_module_oom(module);
573                 talloc_free(msg);
574                 return LDB_ERR_OPERATIONS_ERROR;
575         }
576         v1 = data_blob_string_const(vstring);
577
578         ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
579         if (ret != LDB_SUCCESS) {
580                 talloc_free(msg);
581                 return ret;
582         }
583         el->num_values = 1;
584         el->values = &v2;
585         vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
586         if (!vstring) {
587                 ldb_module_oom(module);
588                 talloc_free(msg);
589                 return LDB_ERR_OPERATIONS_ERROR;
590         }
591         v2 = data_blob_string_const(vstring);
592
593         ret = dsdb_module_modify(module, msg, 0);
594         talloc_free(msg);
595         return ret;
596 }
597
598 /*
599   used to chain to the callers callback
600  */
601 int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
602 {
603         struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
604
605         talloc_steal(up_req, req);
606         return up_req->callback(up_req, ares);
607 }
608
609
610 /*
611   set an integer attribute
612  */
613 int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
614                             const char *attr, uint64_t new_val)
615 {
616         struct ldb_message *msg;
617         int ret;
618
619         msg = ldb_msg_new(module);
620         msg->dn = dn;
621
622         ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
623         if (ret != LDB_SUCCESS) {
624                 talloc_free(msg);
625                 return ret;
626         }
627         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
628
629         ret = dsdb_module_modify(module, msg, 0);
630         talloc_free(msg);
631         return ret;
632 }
633
634 bool dsdb_module_am_system(struct ldb_module *module)
635 {
636         struct ldb_context *ldb = ldb_module_get_ctx(module);
637         struct auth_session_info *session_info
638                 = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
639         return security_session_user_level(session_info) == SECURITY_SYSTEM;
640 }