2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 2009
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
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.
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.
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/>.
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"
31 add a set of controls to a ldb_request structure based on a set of
32 flags. See util.h for a list of available flags
34 int dsdb_request_add_controls(struct ldb_module *module, struct ldb_request *req, uint32_t dsdb_flags)
37 if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
38 struct ldb_search_options_control *options;
39 /* Using the phantom root control allows us to search all partitions */
40 options = talloc(req, struct ldb_search_options_control);
41 if (options == NULL) {
42 ldb_module_oom(module);
43 return LDB_ERR_OPERATIONS_ERROR;
45 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
47 ret = ldb_request_add_control(req,
48 LDB_CONTROL_SEARCH_OPTIONS_OID,
50 if (ret != LDB_SUCCESS) {
55 if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
56 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
57 if (ret != LDB_SUCCESS) {
62 if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
63 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
64 if (ret != LDB_SUCCESS) {
69 if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
70 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
72 ldb_module_oom(module);
73 return LDB_ERR_OPERATIONS_ERROR;
75 extended_ctrl->type = 1;
77 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
78 if (ret != LDB_SUCCESS) {
83 if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
84 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
85 if (ret != LDB_SUCCESS) {
90 if (dsdb_flags & DSDB_MODIFY_RELAX) {
91 ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
92 if (ret != LDB_SUCCESS) {
101 search for attrs on one DN, in the modules below
103 int dsdb_module_search_dn(struct ldb_module *module,
105 struct ldb_result **_res,
106 struct ldb_dn *basedn,
107 const char * const *attrs,
111 struct ldb_request *req;
113 struct ldb_result *res;
115 tmp_ctx = talloc_new(mem_ctx);
117 res = talloc_zero(tmp_ctx, struct ldb_result);
119 return LDB_ERR_OPERATIONS_ERROR;
122 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
129 ldb_search_default_callback,
131 if (ret != LDB_SUCCESS) {
132 talloc_free(tmp_ctx);
136 ret = dsdb_request_add_controls(module, req, dsdb_flags);
137 if (ret != LDB_SUCCESS) {
138 talloc_free(tmp_ctx);
142 ret = ldb_next_request(module, req);
143 if (ret == LDB_SUCCESS) {
144 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
147 if (ret != LDB_SUCCESS) {
148 talloc_free(tmp_ctx);
152 if (res->count != 1) {
153 /* we may be reading a DB that does not have the 'check base on search' option... */
154 ret = LDB_ERR_NO_SUCH_OBJECT;
155 ldb_asprintf_errstring(ldb_module_get_ctx(module),
156 "dsdb_module_search_dn: did not find base dn %s (%d results)",
157 ldb_dn_get_linearized(basedn), res->count);
159 *_res = talloc_steal(mem_ctx, res);
161 talloc_free(tmp_ctx);
166 search for attrs in the modules below
168 int dsdb_module_search(struct ldb_module *module,
170 struct ldb_result **_res,
171 struct ldb_dn *basedn, enum ldb_scope scope,
172 const char * const *attrs,
174 const char *format, ...) _PRINTF_ATTRIBUTE(8, 9)
177 struct ldb_request *req;
179 struct ldb_result *res;
183 tmp_ctx = talloc_new(mem_ctx);
185 va_start(ap, format);
186 expression = talloc_vasprintf(tmp_ctx, format, ap);
189 res = talloc_zero(tmp_ctx, struct ldb_result);
191 return LDB_ERR_OPERATIONS_ERROR;
194 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
201 ldb_search_default_callback,
203 if (ret != LDB_SUCCESS) {
204 talloc_free(tmp_ctx);
208 ret = dsdb_request_add_controls(module, req, dsdb_flags);
209 if (ret != LDB_SUCCESS) {
210 talloc_free(tmp_ctx);
214 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
215 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
216 ret = ops->search(module, req);
218 ret = ldb_next_request(module, req);
220 if (ret == LDB_SUCCESS) {
221 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
225 if (ret == LDB_SUCCESS) {
226 *_res = talloc_steal(mem_ctx, res);
228 talloc_free(tmp_ctx);
233 find a DN given a GUID. This searches across all partitions
235 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
236 const struct GUID *guid, struct ldb_dn **dn)
238 struct ldb_result *res;
239 const char *attrs[] = { NULL };
240 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
243 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
245 DSDB_SEARCH_SHOW_DELETED |
246 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
247 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
248 "objectGUID=%s", GUID_string(tmp_ctx, guid));
249 if (ret != LDB_SUCCESS) {
250 talloc_free(tmp_ctx);
253 if (res->count == 0) {
254 talloc_free(tmp_ctx);
255 return LDB_ERR_NO_SUCH_OBJECT;
257 if (res->count != 1) {
258 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
259 GUID_string(tmp_ctx, guid));
260 talloc_free(tmp_ctx);
261 return LDB_ERR_OPERATIONS_ERROR;
264 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
266 talloc_free(tmp_ctx);
271 find a GUID given a DN.
273 int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid)
275 const char *attrs[] = { NULL };
276 struct ldb_result *res;
277 TALLOC_CTX *tmp_ctx = talloc_new(module);
281 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
282 DSDB_SEARCH_SHOW_DELETED|
283 DSDB_SEARCH_SHOW_EXTENDED_DN);
284 if (ret != LDB_SUCCESS) {
285 ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
286 ldb_dn_get_linearized(dn));
287 talloc_free(tmp_ctx);
291 status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
292 if (!NT_STATUS_IS_OK(status)) {
293 talloc_free(tmp_ctx);
294 return LDB_ERR_OPERATIONS_ERROR;
297 talloc_free(tmp_ctx);
302 a ldb_modify request operating on modules below the
305 int dsdb_module_modify(struct ldb_module *module,
306 const struct ldb_message *message,
309 struct ldb_request *mod_req;
311 struct ldb_context *ldb = ldb_module_get_ctx(module);
312 TALLOC_CTX *tmp_ctx = talloc_new(module);
314 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
318 ldb_op_default_callback,
320 if (ret != LDB_SUCCESS) {
321 talloc_free(tmp_ctx);
325 ret = dsdb_request_add_controls(module, mod_req, dsdb_flags);
326 if (ret != LDB_SUCCESS) {
327 talloc_free(tmp_ctx);
331 /* Run the new request */
332 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
333 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
334 ret = ops->modify(module, mod_req);
336 ret = ldb_next_request(module, mod_req);
338 if (ret == LDB_SUCCESS) {
339 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
342 talloc_free(tmp_ctx);
349 a ldb_rename request operating on modules below the
352 int dsdb_module_rename(struct ldb_module *module,
353 struct ldb_dn *olddn, struct ldb_dn *newdn,
356 struct ldb_request *req;
358 struct ldb_context *ldb = ldb_module_get_ctx(module);
359 TALLOC_CTX *tmp_ctx = talloc_new(module);
361 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
366 ldb_op_default_callback,
368 if (ret != LDB_SUCCESS) {
369 talloc_free(tmp_ctx);
373 ret = dsdb_request_add_controls(module, req, dsdb_flags);
374 if (ret != LDB_SUCCESS) {
375 talloc_free(tmp_ctx);
379 /* Run the new request */
380 if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
381 const struct ldb_module_ops *ops = ldb_module_get_ops(module);
382 ret = ops->rename(module, req);
384 ret = ldb_next_request(module, req);
386 if (ret == LDB_SUCCESS) {
387 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
390 talloc_free(tmp_ctx);
394 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
396 const struct dsdb_class *last_class = NULL;
399 for (i = 0; i < element->num_values; i++){
400 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
402 if(tmp_class == NULL) {
406 if(tmp_class->objectClassCategory == 3) {
411 last_class = tmp_class;
413 if (tmp_class->subClass_order > last_class->subClass_order)
414 last_class = tmp_class;
422 check if a single valued link has multiple non-deleted values
424 This is needed when we will be using the RELAX control to stop
425 ldb_tdb from checking single valued links
427 int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
428 const struct ldb_message_element *el)
430 bool found_active = false;
433 if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
434 el->num_values < 2) {
438 for (i=0; i<el->num_values; i++) {
439 if (!dsdb_dn_is_deleted_val(&el->values[i])) {
441 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;