s4-dsdb: Move get_last_structural class from descriptor.c to util.c
[Samba/ekacnet.git] / source4 / dsdb / samdb / ldb_modules / util.c
blob8d9930a81ff13ca7c5dee0fe9a41932e81134553
1 /*
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/>.
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"
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)
36 int ret;
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,
49 true, options);
50 if (ret != LDB_SUCCESS) {
51 return ret;
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) {
58 return ret;
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) {
65 return ret;
69 if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
70 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
71 if (!extended_ctrl) {
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) {
79 return ret;
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) {
86 return ret;
90 return LDB_SUCCESS;
94 search for attrs on one DN, in the modules below
96 int dsdb_module_search_dn(struct ldb_module *module,
97 TALLOC_CTX *mem_ctx,
98 struct ldb_result **_res,
99 struct ldb_dn *basedn,
100 const char * const *attrs,
101 uint32_t dsdb_flags)
103 int ret;
104 struct ldb_request *req;
105 TALLOC_CTX *tmp_ctx;
106 struct ldb_result *res;
108 tmp_ctx = talloc_new(mem_ctx);
110 res = talloc_zero(tmp_ctx, struct ldb_result);
111 if (!res) {
112 return LDB_ERR_OPERATIONS_ERROR;
115 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
116 basedn,
117 LDB_SCOPE_BASE,
118 NULL,
119 attrs,
120 NULL,
121 res,
122 ldb_search_default_callback,
123 NULL);
124 if (ret != LDB_SUCCESS) {
125 talloc_free(tmp_ctx);
126 return ret;
129 ret = dsdb_request_add_controls(module, req, dsdb_flags);
130 if (ret != LDB_SUCCESS) {
131 talloc_free(tmp_ctx);
132 return ret;
135 ret = ldb_next_request(module, req);
136 if (ret == LDB_SUCCESS) {
137 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
140 if (ret != LDB_SUCCESS) {
141 talloc_free(tmp_ctx);
142 return ret;
145 if (res->count != 1) {
146 /* we may be reading a DB that does not have the 'check base on search' option... */
147 ret = LDB_ERR_NO_SUCH_OBJECT;
148 ldb_asprintf_errstring(ldb_module_get_ctx(module),
149 "dsdb_module_search_dn: did not find base dn %s (%d results)",
150 ldb_dn_get_linearized(basedn), res->count);
151 } else {
152 *_res = talloc_steal(mem_ctx, res);
154 talloc_free(tmp_ctx);
155 return ret;
159 search for attrs in the modules below
161 int dsdb_module_search(struct ldb_module *module,
162 TALLOC_CTX *mem_ctx,
163 struct ldb_result **_res,
164 struct ldb_dn *basedn, enum ldb_scope scope,
165 const char * const *attrs,
166 int dsdb_flags,
167 const char *expression)
169 int ret;
170 struct ldb_request *req;
171 TALLOC_CTX *tmp_ctx;
172 struct ldb_result *res;
174 tmp_ctx = talloc_new(mem_ctx);
176 res = talloc_zero(tmp_ctx, struct ldb_result);
177 if (!res) {
178 return LDB_ERR_OPERATIONS_ERROR;
181 ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
182 basedn,
183 scope,
184 expression,
185 attrs,
186 NULL,
187 res,
188 ldb_search_default_callback,
189 NULL);
190 if (ret != LDB_SUCCESS) {
191 talloc_free(tmp_ctx);
192 return ret;
195 ret = dsdb_request_add_controls(module, req, dsdb_flags);
196 if (ret != LDB_SUCCESS) {
197 talloc_free(tmp_ctx);
198 return ret;
201 ret = ldb_next_request(module, req);
202 if (ret == LDB_SUCCESS) {
203 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
206 talloc_free(req);
207 if (ret == LDB_SUCCESS) {
208 *_res = talloc_steal(mem_ctx, res);
210 talloc_free(tmp_ctx);
211 return ret;
215 find a DN given a GUID. This searches across all partitions
217 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
218 const struct GUID *guid, struct ldb_dn **dn)
220 struct ldb_result *res;
221 const char *attrs[] = { NULL };
222 char *expression;
223 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
224 int ret;
226 expression = talloc_asprintf(tmp_ctx, "objectGUID=%s", GUID_string(tmp_ctx, guid));
227 if (!expression) {
228 ldb_module_oom(module);
229 return LDB_ERR_OPERATIONS_ERROR;
232 ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
233 attrs,
234 DSDB_SEARCH_SHOW_DELETED |
235 DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
236 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
237 expression);
238 if (ret != LDB_SUCCESS) {
239 talloc_free(tmp_ctx);
240 return ret;
242 if (res->count == 0) {
243 talloc_free(tmp_ctx);
244 return LDB_ERR_NO_SUCH_OBJECT;
246 if (res->count != 1) {
247 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching %s\n",
248 expression);
249 talloc_free(tmp_ctx);
250 return LDB_ERR_OPERATIONS_ERROR;
253 *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
255 talloc_free(tmp_ctx);
256 return LDB_SUCCESS;
260 a ldb_modify request operating on modules below the
261 current module
263 int dsdb_module_modify(struct ldb_module *module,
264 const struct ldb_message *message,
265 uint32_t dsdb_flags)
267 struct ldb_request *mod_req;
268 int ret;
269 struct ldb_context *ldb = ldb_module_get_ctx(module);
270 TALLOC_CTX *tmp_ctx = talloc_new(module);
272 ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
273 message,
274 NULL,
275 NULL,
276 ldb_op_default_callback,
277 NULL);
278 if (ret != LDB_SUCCESS) {
279 talloc_free(tmp_ctx);
280 return ret;
283 ret = dsdb_request_add_controls(module, mod_req, dsdb_flags);
284 if (ret != LDB_SUCCESS) {
285 talloc_free(tmp_ctx);
286 return ret;
289 /* Run the new request */
290 ret = ldb_next_request(module, mod_req);
291 if (ret == LDB_SUCCESS) {
292 ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
295 talloc_free(tmp_ctx);
296 return ret;
302 a ldb_rename request operating on modules below the
303 current module
305 int dsdb_module_rename(struct ldb_module *module,
306 struct ldb_dn *olddn, struct ldb_dn *newdn,
307 uint32_t dsdb_flags)
309 struct ldb_request *req;
310 int ret;
311 struct ldb_context *ldb = ldb_module_get_ctx(module);
312 TALLOC_CTX *tmp_ctx = talloc_new(module);
314 ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
315 olddn,
316 newdn,
317 NULL,
318 NULL,
319 ldb_op_default_callback,
320 NULL);
321 if (ret != LDB_SUCCESS) {
322 talloc_free(tmp_ctx);
323 return ret;
326 ret = dsdb_request_add_controls(module, req, dsdb_flags);
327 if (ret != LDB_SUCCESS) {
328 talloc_free(tmp_ctx);
329 return ret;
332 /* Run the new request */
333 ret = ldb_next_request(module, req);
334 if (ret == LDB_SUCCESS) {
335 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
338 talloc_free(tmp_ctx);
339 return ret;
342 const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
344 const struct dsdb_class *last_class = NULL;
345 int i;
347 for (i = 0; i < element->num_values; i++){
348 const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]);
350 if(tmp_class == NULL) {
351 continue;
354 if(tmp_class->objectClassCategory == 3) {
355 continue;
358 if (!last_class) {
359 last_class = tmp_class;
360 } else {
361 if (tmp_class->subClass_order > last_class->subClass_order)
362 last_class = tmp_class;
366 return last_class;