Line data Source code
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 : Copyright (C) Matthieu Patou <mat@matws.net> 2011
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "ldb.h"
25 : #include "ldb_module.h"
26 : #include "librpc/ndr/libndr.h"
27 : #include "dsdb/samdb/ldb_modules/util.h"
28 : #include "dsdb/samdb/samdb.h"
29 : #include "dsdb/common/util.h"
30 : #include "libcli/security/security.h"
31 :
32 : #undef strcasecmp
33 :
34 : /*
35 : search for attrs on one DN, in the modules below
36 : */
37 9042372 : int dsdb_module_search_dn(struct ldb_module *module,
38 : TALLOC_CTX *mem_ctx,
39 : struct ldb_result **_res,
40 : struct ldb_dn *basedn,
41 : const char * const *attrs,
42 : uint32_t dsdb_flags,
43 : struct ldb_request *parent)
44 : {
45 : int ret;
46 : struct ldb_request *req;
47 : TALLOC_CTX *tmp_ctx;
48 : struct ldb_result *res;
49 :
50 9042372 : tmp_ctx = talloc_new(mem_ctx);
51 :
52 9042372 : res = talloc_zero(tmp_ctx, struct ldb_result);
53 9042372 : if (!res) {
54 0 : talloc_free(tmp_ctx);
55 0 : return ldb_oom(ldb_module_get_ctx(module));
56 : }
57 :
58 9042372 : ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
59 : basedn,
60 : LDB_SCOPE_BASE,
61 : NULL,
62 : attrs,
63 : NULL,
64 : res,
65 : ldb_search_default_callback,
66 : parent);
67 9042372 : LDB_REQ_SET_LOCATION(req);
68 9042372 : if (ret != LDB_SUCCESS) {
69 0 : talloc_free(tmp_ctx);
70 0 : return ret;
71 : }
72 :
73 9042372 : ret = dsdb_request_add_controls(req, dsdb_flags);
74 9042372 : if (ret != LDB_SUCCESS) {
75 0 : talloc_free(tmp_ctx);
76 0 : return ret;
77 : }
78 :
79 9042372 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
80 0 : ldb_req_mark_trusted(req);
81 : }
82 :
83 : /* Run the new request */
84 9042372 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
85 9042098 : ret = ldb_next_request(module, req);
86 274 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
87 274 : ret = ldb_request(ldb_module_get_ctx(module), req);
88 : } else {
89 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
90 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
91 0 : ret = ops->search(module, req);
92 : }
93 9042372 : if (ret == LDB_SUCCESS) {
94 9042370 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
95 : }
96 :
97 9042372 : if (ret != LDB_SUCCESS) {
98 290037 : talloc_free(tmp_ctx);
99 290037 : return ret;
100 : }
101 :
102 8752335 : if (res->count != 1) {
103 : /* we may be reading a DB that does not have the 'check base on search' option... */
104 12892 : ret = LDB_ERR_NO_SUCH_OBJECT;
105 12892 : ldb_asprintf_errstring(ldb_module_get_ctx(module),
106 : "dsdb_module_search_dn: did not find base dn %s (%d results)",
107 : ldb_dn_get_linearized(basedn), res->count);
108 : } else {
109 8739443 : *_res = talloc_steal(mem_ctx, res);
110 : }
111 8752335 : talloc_free(tmp_ctx);
112 8752335 : return ret;
113 : }
114 :
115 9895228 : int dsdb_module_search_tree(struct ldb_module *module,
116 : TALLOC_CTX *mem_ctx,
117 : struct ldb_result **_res,
118 : struct ldb_dn *basedn,
119 : enum ldb_scope scope,
120 : struct ldb_parse_tree *tree,
121 : const char * const *attrs,
122 : int dsdb_flags,
123 : struct ldb_request *parent)
124 : {
125 : int ret;
126 : struct ldb_request *req;
127 : TALLOC_CTX *tmp_ctx;
128 : struct ldb_result *res;
129 :
130 9895228 : tmp_ctx = talloc_new(mem_ctx);
131 :
132 : /* cross-partitions searches with a basedn break multi-domain support */
133 9895228 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
134 :
135 9895228 : res = talloc_zero(tmp_ctx, struct ldb_result);
136 9895228 : if (!res) {
137 0 : talloc_free(tmp_ctx);
138 0 : return ldb_oom(ldb_module_get_ctx(module));
139 : }
140 :
141 9895228 : ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
142 : basedn,
143 : scope,
144 : tree,
145 : attrs,
146 : NULL,
147 : res,
148 : ldb_search_default_callback,
149 : parent);
150 9895228 : LDB_REQ_SET_LOCATION(req);
151 9895228 : if (ret != LDB_SUCCESS) {
152 0 : talloc_free(tmp_ctx);
153 0 : return ret;
154 : }
155 :
156 9895228 : ret = dsdb_request_add_controls(req, dsdb_flags);
157 9895228 : if (ret != LDB_SUCCESS) {
158 0 : talloc_free(tmp_ctx);
159 0 : return ret;
160 : }
161 :
162 9895228 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
163 0 : ldb_req_mark_trusted(req);
164 : }
165 :
166 9895228 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
167 9895228 : ret = ldb_next_request(module, req);
168 0 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
169 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
170 : } else {
171 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
172 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
173 0 : ret = ops->search(module, req);
174 : }
175 9895228 : if (ret == LDB_SUCCESS) {
176 9895228 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
177 : }
178 :
179 9895228 : if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
180 8026292 : if (res->count == 0) {
181 6123 : talloc_free(tmp_ctx);
182 6123 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
183 : }
184 8020169 : if (res->count != 1) {
185 0 : talloc_free(tmp_ctx);
186 0 : ldb_reset_err_string(ldb_module_get_ctx(module));
187 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
188 : }
189 : }
190 :
191 9889105 : talloc_free(req);
192 9889105 : if (ret == LDB_SUCCESS) {
193 9888341 : *_res = talloc_steal(mem_ctx, res);
194 : }
195 9889105 : talloc_free(tmp_ctx);
196 9889105 : return ret;
197 : }
198 :
199 : /*
200 : search for attrs in the modules below
201 : */
202 9893988 : int dsdb_module_search(struct ldb_module *module,
203 : TALLOC_CTX *mem_ctx,
204 : struct ldb_result **_res,
205 : struct ldb_dn *basedn, enum ldb_scope scope,
206 : const char * const *attrs,
207 : int dsdb_flags,
208 : struct ldb_request *parent,
209 : const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
210 : {
211 : int ret;
212 : TALLOC_CTX *tmp_ctx;
213 : va_list ap;
214 : char *expression;
215 : struct ldb_parse_tree *tree;
216 :
217 : /* cross-partitions searches with a basedn break multi-domain support */
218 9893988 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
219 :
220 9893988 : tmp_ctx = talloc_new(mem_ctx);
221 :
222 9893988 : if (format) {
223 9416045 : va_start(ap, format);
224 9416045 : expression = talloc_vasprintf(tmp_ctx, format, ap);
225 9416045 : va_end(ap);
226 :
227 9416045 : if (!expression) {
228 0 : talloc_free(tmp_ctx);
229 0 : return ldb_oom(ldb_module_get_ctx(module));
230 : }
231 : } else {
232 477943 : expression = NULL;
233 : }
234 :
235 9893988 : tree = ldb_parse_tree(tmp_ctx, expression);
236 9893988 : if (tree == NULL) {
237 0 : talloc_free(tmp_ctx);
238 0 : ldb_set_errstring(ldb_module_get_ctx(module),
239 : "Unable to parse search expression");
240 0 : return LDB_ERR_OPERATIONS_ERROR;
241 : }
242 :
243 9893988 : ret = dsdb_module_search_tree(module,
244 : mem_ctx,
245 : _res,
246 : basedn,
247 : scope,
248 : tree,
249 : attrs,
250 : dsdb_flags,
251 : parent);
252 :
253 9893988 : talloc_free(tmp_ctx);
254 9893988 : return ret;
255 : }
256 :
257 : /*
258 : find a DN given a GUID. This searches across all partitions
259 : */
260 39666 : int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
261 : const struct GUID *guid, struct ldb_dn **dn,
262 : struct ldb_request *parent)
263 : {
264 : struct ldb_result *res;
265 39666 : const char *attrs[] = { NULL };
266 39666 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
267 : int ret;
268 :
269 39666 : ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
270 : attrs,
271 : DSDB_FLAG_NEXT_MODULE |
272 : DSDB_SEARCH_SHOW_RECYCLED |
273 : DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
274 : DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
275 : parent,
276 : "objectGUID=%s", GUID_string(tmp_ctx, guid));
277 39666 : if (ret != LDB_SUCCESS) {
278 0 : talloc_free(tmp_ctx);
279 0 : return ret;
280 : }
281 39666 : if (res->count == 0) {
282 61 : talloc_free(tmp_ctx);
283 61 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
284 : }
285 39605 : if (res->count != 1) {
286 0 : ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
287 : GUID_string(tmp_ctx, guid));
288 0 : talloc_free(tmp_ctx);
289 0 : return LDB_ERR_OPERATIONS_ERROR;
290 : }
291 :
292 39605 : *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
293 :
294 39605 : talloc_free(tmp_ctx);
295 39605 : return LDB_SUCCESS;
296 : }
297 :
298 : /*
299 : find a GUID given a DN.
300 : */
301 13142 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
302 : struct ldb_request *parent)
303 : {
304 13142 : const char *attrs[] = { NULL };
305 : struct ldb_result *res;
306 13142 : TALLOC_CTX *tmp_ctx = talloc_new(module);
307 : int ret;
308 : NTSTATUS status;
309 :
310 13142 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
311 : DSDB_FLAG_NEXT_MODULE |
312 : DSDB_SEARCH_SHOW_RECYCLED |
313 : DSDB_SEARCH_SHOW_EXTENDED_DN,
314 : parent);
315 13142 : if (ret != LDB_SUCCESS) {
316 3 : ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
317 : ldb_dn_get_linearized(dn));
318 3 : talloc_free(tmp_ctx);
319 3 : return ret;
320 : }
321 :
322 13139 : status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
323 13139 : if (!NT_STATUS_IS_OK(status)) {
324 0 : talloc_free(tmp_ctx);
325 0 : return ldb_operr(ldb_module_get_ctx(module));
326 : }
327 :
328 13139 : talloc_free(tmp_ctx);
329 13139 : return LDB_SUCCESS;
330 : }
331 :
332 :
333 : /*
334 : a ldb_extended request operating on modules below the
335 : current module
336 :
337 : Note that this does not automatically start a transaction. If you
338 : need a transaction the caller needs to start it as needed.
339 : */
340 12409827 : int dsdb_module_extended(struct ldb_module *module,
341 : TALLOC_CTX *mem_ctx,
342 : struct ldb_result **_res,
343 : const char* oid, void* data,
344 : uint32_t dsdb_flags,
345 : struct ldb_request *parent)
346 : {
347 : struct ldb_request *req;
348 : int ret;
349 12409827 : struct ldb_context *ldb = ldb_module_get_ctx(module);
350 12409827 : TALLOC_CTX *tmp_ctx = talloc_new(module);
351 : struct ldb_result *res;
352 :
353 12409827 : if (_res != NULL) {
354 12069737 : (*_res) = NULL;
355 : }
356 :
357 12409827 : res = talloc_zero(tmp_ctx, struct ldb_result);
358 12409827 : if (!res) {
359 0 : talloc_free(tmp_ctx);
360 0 : return ldb_oom(ldb_module_get_ctx(module));
361 : }
362 :
363 12409827 : ret = ldb_build_extended_req(&req, ldb,
364 : tmp_ctx,
365 : oid,
366 : data,
367 : NULL,
368 : res, ldb_extended_default_callback,
369 : parent);
370 :
371 12409827 : LDB_REQ_SET_LOCATION(req);
372 12409827 : if (ret != LDB_SUCCESS) {
373 0 : talloc_free(tmp_ctx);
374 0 : return ret;
375 : }
376 :
377 12409827 : ret = dsdb_request_add_controls(req, dsdb_flags);
378 12409827 : if (ret != LDB_SUCCESS) {
379 0 : talloc_free(tmp_ctx);
380 0 : return ret;
381 : }
382 :
383 12409827 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
384 340090 : ldb_req_mark_trusted(req);
385 : }
386 :
387 : /* Run the new request */
388 12409827 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
389 12069737 : ret = ldb_next_request(module, req);
390 340090 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
391 340090 : ret = ldb_request(ldb_module_get_ctx(module), req);
392 : } else {
393 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
394 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
395 0 : ret = ops->extended(module, req);
396 : }
397 12409827 : if (ret == LDB_SUCCESS) {
398 12409827 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
399 : }
400 :
401 12409827 : if (_res != NULL && ret == LDB_SUCCESS) {
402 12069737 : (*_res) = talloc_steal(mem_ctx, res);
403 : }
404 :
405 12409827 : talloc_free(tmp_ctx);
406 12409827 : return ret;
407 : }
408 :
409 :
410 : /*
411 : a ldb_modify request operating on modules below the
412 : current module
413 : */
414 249948 : int dsdb_module_modify(struct ldb_module *module,
415 : const struct ldb_message *message,
416 : uint32_t dsdb_flags,
417 : struct ldb_request *parent)
418 : {
419 : struct ldb_request *mod_req;
420 : int ret;
421 249948 : struct ldb_context *ldb = ldb_module_get_ctx(module);
422 249948 : TALLOC_CTX *tmp_ctx = talloc_new(module);
423 : struct ldb_result *res;
424 :
425 249948 : res = talloc_zero(tmp_ctx, struct ldb_result);
426 249948 : if (!res) {
427 0 : talloc_free(tmp_ctx);
428 0 : return ldb_oom(ldb_module_get_ctx(module));
429 : }
430 :
431 249948 : ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
432 : message,
433 : NULL,
434 : res,
435 : ldb_modify_default_callback,
436 : parent);
437 249948 : LDB_REQ_SET_LOCATION(mod_req);
438 249948 : if (ret != LDB_SUCCESS) {
439 0 : talloc_free(tmp_ctx);
440 0 : return ret;
441 : }
442 :
443 249948 : ret = dsdb_request_add_controls(mod_req, dsdb_flags);
444 249948 : if (ret != LDB_SUCCESS) {
445 0 : talloc_free(tmp_ctx);
446 0 : return ret;
447 : }
448 :
449 249948 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
450 0 : ldb_req_mark_trusted(mod_req);
451 : }
452 :
453 : /* Run the new request */
454 249948 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
455 95602 : ret = ldb_next_request(module, mod_req);
456 154346 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
457 0 : ret = ldb_request(ldb_module_get_ctx(module), mod_req);
458 : } else {
459 154346 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
460 154346 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
461 154346 : ret = ops->modify(module, mod_req);
462 : }
463 249948 : if (ret == LDB_SUCCESS) {
464 249948 : ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
465 : }
466 :
467 249948 : talloc_free(tmp_ctx);
468 249948 : return ret;
469 : }
470 :
471 :
472 :
473 : /*
474 : a ldb_rename request operating on modules below the
475 : current module
476 : */
477 116310 : int dsdb_module_rename(struct ldb_module *module,
478 : struct ldb_dn *olddn, struct ldb_dn *newdn,
479 : uint32_t dsdb_flags,
480 : struct ldb_request *parent)
481 : {
482 : struct ldb_request *req;
483 : int ret;
484 116310 : struct ldb_context *ldb = ldb_module_get_ctx(module);
485 116310 : TALLOC_CTX *tmp_ctx = talloc_new(module);
486 : struct ldb_result *res;
487 :
488 116310 : res = talloc_zero(tmp_ctx, struct ldb_result);
489 116310 : if (!res) {
490 0 : talloc_free(tmp_ctx);
491 0 : return ldb_oom(ldb_module_get_ctx(module));
492 : }
493 :
494 116310 : ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
495 : olddn,
496 : newdn,
497 : NULL,
498 : res,
499 : ldb_modify_default_callback,
500 : parent);
501 116310 : LDB_REQ_SET_LOCATION(req);
502 116310 : if (ret != LDB_SUCCESS) {
503 0 : talloc_free(tmp_ctx);
504 0 : return ret;
505 : }
506 :
507 116310 : ret = dsdb_request_add_controls(req, dsdb_flags);
508 116310 : if (ret != LDB_SUCCESS) {
509 0 : talloc_free(tmp_ctx);
510 0 : return ret;
511 : }
512 :
513 116310 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
514 0 : ldb_req_mark_trusted(req);
515 : }
516 :
517 : /* Run the new request */
518 116310 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
519 115781 : ret = ldb_next_request(module, req);
520 529 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
521 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
522 : } else {
523 529 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
524 529 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
525 529 : ret = ops->rename(module, req);
526 : }
527 116310 : if (ret == LDB_SUCCESS) {
528 116308 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
529 : }
530 :
531 116310 : talloc_free(tmp_ctx);
532 116310 : return ret;
533 : }
534 :
535 : /*
536 : a ldb_add request operating on modules below the
537 : current module
538 : */
539 1129 : int dsdb_module_add(struct ldb_module *module,
540 : const struct ldb_message *message,
541 : uint32_t dsdb_flags,
542 : struct ldb_request *parent)
543 : {
544 : struct ldb_request *req;
545 : int ret;
546 1129 : struct ldb_context *ldb = ldb_module_get_ctx(module);
547 1129 : TALLOC_CTX *tmp_ctx = talloc_new(module);
548 : struct ldb_result *res;
549 :
550 1129 : res = talloc_zero(tmp_ctx, struct ldb_result);
551 1129 : if (!res) {
552 0 : talloc_free(tmp_ctx);
553 0 : return ldb_oom(ldb_module_get_ctx(module));
554 : }
555 :
556 1129 : ret = ldb_build_add_req(&req, ldb, tmp_ctx,
557 : message,
558 : NULL,
559 : res,
560 : ldb_modify_default_callback,
561 : parent);
562 1129 : LDB_REQ_SET_LOCATION(req);
563 1129 : if (ret != LDB_SUCCESS) {
564 0 : talloc_free(tmp_ctx);
565 0 : return ret;
566 : }
567 :
568 1129 : ret = dsdb_request_add_controls(req, dsdb_flags);
569 1129 : if (ret != LDB_SUCCESS) {
570 0 : talloc_free(tmp_ctx);
571 0 : return ret;
572 : }
573 :
574 1129 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
575 0 : ldb_req_mark_trusted(req);
576 : }
577 :
578 : /* Run the new request */
579 1129 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
580 1067 : ret = ldb_next_request(module, req);
581 62 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
582 62 : ret = ldb_request(ldb_module_get_ctx(module), req);
583 : } else {
584 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
585 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
586 0 : ret = ops->add(module, req);
587 : }
588 1129 : if (ret == LDB_SUCCESS) {
589 1129 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
590 : }
591 :
592 1129 : talloc_free(tmp_ctx);
593 1129 : return ret;
594 : }
595 :
596 : /*
597 : a ldb_delete request operating on modules below the
598 : current module
599 : */
600 18377 : int dsdb_module_del(struct ldb_module *module,
601 : struct ldb_dn *dn,
602 : uint32_t dsdb_flags,
603 : struct ldb_request *parent)
604 : {
605 : struct ldb_request *req;
606 : int ret;
607 18377 : struct ldb_context *ldb = ldb_module_get_ctx(module);
608 18377 : TALLOC_CTX *tmp_ctx = talloc_new(module);
609 : struct ldb_result *res;
610 :
611 18377 : res = talloc_zero(tmp_ctx, struct ldb_result);
612 18377 : if (!res) {
613 0 : talloc_free(tmp_ctx);
614 0 : return ldb_oom(ldb);
615 : }
616 :
617 18377 : ret = ldb_build_del_req(&req, ldb, tmp_ctx,
618 : dn,
619 : NULL,
620 : res,
621 : ldb_modify_default_callback,
622 : parent);
623 18377 : LDB_REQ_SET_LOCATION(req);
624 18377 : if (ret != LDB_SUCCESS) {
625 0 : talloc_free(tmp_ctx);
626 0 : return ret;
627 : }
628 :
629 18377 : ret = dsdb_request_add_controls(req, dsdb_flags);
630 18377 : if (ret != LDB_SUCCESS) {
631 0 : talloc_free(tmp_ctx);
632 0 : return ret;
633 : }
634 :
635 18377 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
636 18377 : ldb_req_mark_trusted(req);
637 : }
638 :
639 : /* Run the new request */
640 18377 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
641 0 : ret = ldb_next_request(module, req);
642 18377 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
643 18377 : ret = ldb_request(ldb_module_get_ctx(module), req);
644 : } else {
645 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
646 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
647 0 : ret = ops->del(module, req);
648 : }
649 18377 : if (ret == LDB_SUCCESS) {
650 18377 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
651 : }
652 :
653 18377 : talloc_free(tmp_ctx);
654 18377 : return ret;
655 : }
656 :
657 : /*
658 : check if a single valued link has multiple non-deleted values
659 :
660 : This is needed when we will be using the RELAX control to stop
661 : ldb_tdb from checking single valued links
662 : */
663 42331 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
664 : const struct ldb_message_element *el)
665 : {
666 42331 : bool found_active = false;
667 : unsigned int i;
668 :
669 42331 : if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
670 6688 : el->num_values < 2) {
671 42212 : return LDB_SUCCESS;
672 : }
673 :
674 355 : for (i=0; i<el->num_values; i++) {
675 239 : if (!dsdb_dn_is_deleted_val(&el->values[i])) {
676 112 : if (found_active) {
677 3 : return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
678 : }
679 109 : found_active = true;
680 : }
681 : }
682 :
683 116 : return LDB_SUCCESS;
684 : }
685 :
686 :
687 234910 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
688 : const char *feature,
689 : bool *found)
690 : {
691 234910 : struct ldb_context *ldb = ldb_module_get_ctx(module);
692 : struct ldb_result *res;
693 : static const char *samba_dsdb_attrs[] = {
694 : SAMBA_COMPATIBLE_FEATURES_ATTR,
695 : NULL
696 : };
697 : int ret;
698 234910 : struct ldb_dn *samba_dsdb_dn = NULL;
699 234910 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
700 234910 : if (tmp_ctx == NULL) {
701 0 : *found = false;
702 0 : return ldb_oom(ldb);
703 : }
704 234910 : *found = false;
705 :
706 234910 : samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
707 234910 : if (samba_dsdb_dn == NULL) {
708 0 : TALLOC_FREE(tmp_ctx);
709 0 : return ldb_oom(ldb);
710 : }
711 :
712 234910 : ret = dsdb_module_search_dn(module,
713 : tmp_ctx,
714 : &res,
715 : samba_dsdb_dn,
716 : samba_dsdb_attrs,
717 : DSDB_FLAG_NEXT_MODULE,
718 : NULL);
719 234910 : if (ret == LDB_SUCCESS) {
720 234910 : *found = ldb_msg_check_string_attribute(
721 234910 : res->msgs[0],
722 : SAMBA_COMPATIBLE_FEATURES_ATTR,
723 : feature);
724 0 : } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
725 : /* it is not an error not to find it */
726 0 : ret = LDB_SUCCESS;
727 : }
728 234910 : TALLOC_FREE(tmp_ctx);
729 234910 : return ret;
730 : }
731 :
732 :
733 : /*
734 : check if an optional feature is enabled on our own NTDS DN
735 :
736 : Note that features can be marked as enabled in more than one
737 : place. For example, the recyclebin feature is marked as enabled both
738 : on the CN=Partitions,CN=Configurration object and on the NTDS DN of
739 : each DC in the forest. It seems likely that it is the job of the KCC
740 : to propagate between the two
741 : */
742 89810 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
743 : {
744 : TALLOC_CTX *tmp_ctx;
745 89810 : struct ldb_context *ldb = ldb_module_get_ctx(module);
746 : struct ldb_result *res;
747 : struct ldb_dn *search_dn;
748 : struct GUID search_guid;
749 89810 : const char *attrs[] = {"msDS-EnabledFeature", NULL};
750 : int ret;
751 : unsigned int i;
752 : struct ldb_message_element *el;
753 : struct ldb_dn *feature_dn;
754 :
755 89810 : tmp_ctx = talloc_new(ldb);
756 :
757 89810 : feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
758 89810 : if (feature_dn == NULL) {
759 0 : talloc_free(tmp_ctx);
760 0 : return ldb_operr(ldb_module_get_ctx(module));
761 : }
762 :
763 89810 : *feature_enabled = false;
764 :
765 89810 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
766 89810 : if (ret != LDB_SUCCESS) {
767 1314 : ldb_asprintf_errstring(ldb,
768 : "Could not find the feature object - dn: %s\n",
769 : ldb_dn_get_linearized(feature_dn));
770 1314 : talloc_free(tmp_ctx);
771 1314 : return LDB_ERR_NO_SUCH_OBJECT;
772 : }
773 88496 : if (res->msgs[0]->num_elements > 0) {
774 0 : const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
775 :
776 0 : el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
777 :
778 0 : for (i=0; i<el->num_values; i++) {
779 0 : search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
780 :
781 0 : ret = dsdb_module_search_dn(module, tmp_ctx, &res,
782 : search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
783 0 : if (ret != LDB_SUCCESS) {
784 0 : ldb_asprintf_errstring(ldb,
785 : "Could no find object dn: %s\n",
786 : ldb_dn_get_linearized(search_dn));
787 0 : talloc_free(tmp_ctx);
788 0 : return LDB_ERR_OPERATIONS_ERROR;
789 : }
790 :
791 0 : search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
792 :
793 0 : if (GUID_equal(&search_guid, &op_feature_guid)) {
794 0 : *feature_enabled = true;
795 0 : break;
796 : }
797 : }
798 : }
799 88496 : talloc_free(tmp_ctx);
800 88496 : return LDB_SUCCESS;
801 : }
802 :
803 : /*
804 : find the NTDS GUID from a computers DN record
805 : */
806 397 : int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
807 : TALLOC_CTX *mem_ctx,
808 : struct ldb_dn *computer_dn,
809 : struct GUID *ntds_guid,
810 : struct ldb_request *parent)
811 : {
812 : int ret;
813 : struct ldb_dn *dn;
814 :
815 397 : *ntds_guid = GUID_zero();
816 :
817 397 : ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
818 : "serverReferenceBL", &dn, parent);
819 397 : if (ret != LDB_SUCCESS) {
820 0 : return ret;
821 : }
822 :
823 397 : if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
824 0 : talloc_free(dn);
825 0 : return LDB_ERR_OPERATIONS_ERROR;
826 : }
827 :
828 397 : ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
829 397 : talloc_free(dn);
830 397 : return ret;
831 : }
832 :
833 : /*
834 : find a 'reference' DN that points at another object
835 : (eg. serverReference, rIDManagerReference etc)
836 : */
837 1224 : int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
838 : const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
839 : {
840 : const char *attrs[2];
841 : struct ldb_result *res;
842 : int ret;
843 :
844 1224 : attrs[0] = attribute;
845 1224 : attrs[1] = NULL;
846 :
847 1224 : ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
848 : DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
849 1224 : if (ret != LDB_SUCCESS) {
850 0 : return ret;
851 : }
852 :
853 1224 : *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
854 1224 : mem_ctx, res->msgs[0], attribute);
855 1224 : if (!*dn) {
856 30 : ldb_reset_err_string(ldb_module_get_ctx(module));
857 30 : talloc_free(res);
858 30 : return LDB_ERR_NO_SUCH_ATTRIBUTE;
859 : }
860 :
861 1194 : talloc_free(res);
862 1194 : return LDB_SUCCESS;
863 : }
864 :
865 : /*
866 : find the RID Manager$ DN via the rIDManagerReference attribute in the
867 : base DN
868 : */
869 360 : int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
870 : struct ldb_request *parent)
871 : {
872 360 : return dsdb_module_reference_dn(module, mem_ctx,
873 : ldb_get_default_basedn(ldb_module_get_ctx(module)),
874 : "rIDManagerReference", dn, parent);
875 : }
876 :
877 : /*
878 : used to chain to the callers callback
879 : */
880 110027320 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
881 : {
882 110027320 : struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
883 :
884 110027320 : if (!ares) {
885 0 : return ldb_module_done(up_req, NULL, NULL,
886 : LDB_ERR_OPERATIONS_ERROR);
887 : }
888 :
889 110027320 : if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
890 36749200 : return ldb_module_done(up_req, ares->controls,
891 : ares->response, ares->error);
892 : }
893 :
894 : /* Otherwise pass on the callback */
895 73278120 : switch (ares->type) {
896 70520183 : case LDB_REPLY_ENTRY:
897 70520183 : return ldb_module_send_entry(up_req, ares->message,
898 : ares->controls);
899 :
900 2757937 : case LDB_REPLY_REFERRAL:
901 2757937 : return ldb_module_send_referral(up_req,
902 : ares->referral);
903 0 : default:
904 : /* Can't happen */
905 0 : return LDB_ERR_OPERATIONS_ERROR;
906 : }
907 : }
908 :
909 : /*
910 : load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
911 : object for a partition
912 : */
913 0 : int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
914 : uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
915 : {
916 0 : struct ldb_context *ldb = ldb_module_get_ctx(module);
917 : struct ldb_request *req;
918 : int ret;
919 0 : TALLOC_CTX *tmp_ctx = talloc_new(module);
920 : struct dsdb_control_current_partition *p_ctrl;
921 : struct ldb_result *res;
922 :
923 0 : res = talloc_zero(tmp_ctx, struct ldb_result);
924 0 : if (!res) {
925 0 : talloc_free(tmp_ctx);
926 0 : return ldb_module_oom(module);
927 : }
928 :
929 0 : ret = ldb_build_search_req(&req, ldb, tmp_ctx,
930 : ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
931 : LDB_SCOPE_BASE,
932 : NULL, NULL,
933 : NULL,
934 : res, ldb_search_default_callback,
935 : parent);
936 0 : LDB_REQ_SET_LOCATION(req);
937 0 : if (ret != LDB_SUCCESS) {
938 0 : talloc_free(tmp_ctx);
939 0 : return ret;
940 : }
941 :
942 0 : p_ctrl = talloc(req, struct dsdb_control_current_partition);
943 0 : if (p_ctrl == NULL) {
944 0 : talloc_free(tmp_ctx);
945 0 : return ldb_module_oom(module);
946 : }
947 0 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
948 0 : p_ctrl->dn = dn;
949 :
950 :
951 0 : ret = ldb_request_add_control(req,
952 : DSDB_CONTROL_CURRENT_PARTITION_OID,
953 : false, p_ctrl);
954 0 : if (ret != LDB_SUCCESS) {
955 0 : talloc_free(tmp_ctx);
956 0 : return ret;
957 : }
958 :
959 : /* Run the new request */
960 0 : ret = ldb_next_request(module, req);
961 :
962 0 : if (ret == LDB_SUCCESS) {
963 0 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
964 : }
965 :
966 0 : if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
967 : /* it hasn't been created yet, which means
968 : an implicit value of zero */
969 0 : *uSN = 0;
970 0 : talloc_free(tmp_ctx);
971 0 : ldb_reset_err_string(ldb);
972 0 : return LDB_SUCCESS;
973 : }
974 :
975 0 : if (ret != LDB_SUCCESS) {
976 0 : talloc_free(tmp_ctx);
977 0 : return ret;
978 : }
979 :
980 0 : if (res->count != 1) {
981 0 : *uSN = 0;
982 0 : if (urgent_uSN) {
983 0 : *urgent_uSN = 0;
984 : }
985 : } else {
986 0 : *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
987 0 : if (urgent_uSN) {
988 0 : *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
989 : }
990 : }
991 :
992 0 : talloc_free(tmp_ctx);
993 :
994 0 : return LDB_SUCCESS;
995 : }
996 :
997 : /*
998 : save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
999 : partition
1000 : */
1001 176479 : int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
1002 : uint64_t uSN, uint64_t urgent_uSN,
1003 : struct ldb_request *parent)
1004 : {
1005 176479 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1006 : struct ldb_request *req;
1007 : struct ldb_message *msg;
1008 : struct dsdb_control_current_partition *p_ctrl;
1009 : int ret;
1010 : struct ldb_result *res;
1011 :
1012 176479 : msg = ldb_msg_new(module);
1013 176479 : if (msg == NULL) {
1014 0 : return ldb_module_oom(module);
1015 : }
1016 :
1017 176479 : msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1018 176479 : if (msg->dn == NULL) {
1019 0 : talloc_free(msg);
1020 0 : return ldb_operr(ldb_module_get_ctx(module));
1021 : }
1022 :
1023 176479 : res = talloc_zero(msg, struct ldb_result);
1024 176479 : if (!res) {
1025 0 : talloc_free(msg);
1026 0 : return ldb_module_oom(module);
1027 : }
1028 :
1029 176479 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1030 176479 : if (ret != LDB_SUCCESS) {
1031 0 : talloc_free(msg);
1032 0 : return ret;
1033 : }
1034 176479 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1035 :
1036 : /* urgent_uSN is optional so may not be stored */
1037 176479 : if (urgent_uSN) {
1038 29185 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1039 : urgent_uSN);
1040 29185 : if (ret != LDB_SUCCESS) {
1041 0 : talloc_free(msg);
1042 0 : return ret;
1043 : }
1044 29185 : msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1045 : }
1046 :
1047 :
1048 176479 : p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1049 176479 : if (p_ctrl == NULL) {
1050 0 : talloc_free(msg);
1051 0 : return ldb_oom(ldb);
1052 : }
1053 176479 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1054 176479 : p_ctrl->dn = dn;
1055 176479 : ret = ldb_build_mod_req(&req, ldb, msg,
1056 : msg,
1057 : NULL,
1058 : res,
1059 : ldb_modify_default_callback,
1060 : parent);
1061 176479 : LDB_REQ_SET_LOCATION(req);
1062 177185 : again:
1063 177185 : if (ret != LDB_SUCCESS) {
1064 0 : talloc_free(msg);
1065 0 : return ret;
1066 : }
1067 :
1068 177185 : ret = ldb_request_add_control(req,
1069 : DSDB_CONTROL_CURRENT_PARTITION_OID,
1070 : false, p_ctrl);
1071 177185 : if (ret != LDB_SUCCESS) {
1072 0 : talloc_free(msg);
1073 0 : return ret;
1074 : }
1075 :
1076 : /* Run the new request */
1077 177185 : ret = ldb_next_request(module, req);
1078 :
1079 177185 : if (ret == LDB_SUCCESS) {
1080 177185 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1081 : }
1082 177185 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1083 706 : ret = ldb_build_add_req(&req, ldb, msg,
1084 : msg,
1085 : NULL,
1086 : res,
1087 : ldb_modify_default_callback,
1088 : parent);
1089 706 : LDB_REQ_SET_LOCATION(req);
1090 706 : goto again;
1091 : }
1092 :
1093 176479 : talloc_free(msg);
1094 :
1095 176479 : return ret;
1096 : }
1097 :
1098 32207439 : bool dsdb_module_am_system(struct ldb_module *module)
1099 : {
1100 32207439 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1101 : struct auth_session_info *session_info
1102 32207439 : = talloc_get_type(
1103 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1104 : struct auth_session_info);
1105 32207439 : return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1106 : }
1107 :
1108 20120589 : bool dsdb_module_am_administrator(struct ldb_module *module)
1109 : {
1110 20120589 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1111 : struct auth_session_info *session_info
1112 20120589 : = talloc_get_type(
1113 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1114 : struct auth_session_info);
1115 20120589 : return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1116 : }
1117 :
1118 : /*
1119 : check if the recyclebin is enabled
1120 : */
1121 89810 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1122 : {
1123 89810 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1124 : struct GUID recyclebin_guid;
1125 : int ret;
1126 :
1127 89810 : GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1128 :
1129 89810 : ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1130 89810 : if (ret != LDB_SUCCESS) {
1131 1314 : ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1132 1314 : return ret;
1133 : }
1134 :
1135 88496 : return LDB_SUCCESS;
1136 : }
1137 :
1138 52052 : int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1139 : struct ldb_message *msg,
1140 : const char *attr,
1141 : const int32_t *old_val,
1142 : const int32_t *new_val)
1143 : {
1144 : struct ldb_message_element *el;
1145 : int ret;
1146 : char *vstring;
1147 :
1148 52052 : if (old_val) {
1149 26000 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1150 26000 : if (ret != LDB_SUCCESS) {
1151 0 : return ret;
1152 : }
1153 26000 : el->num_values = 1;
1154 26000 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1155 26000 : if (!el->values) {
1156 0 : return ldb_module_oom(module);
1157 : }
1158 26000 : vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1159 26000 : if (!vstring) {
1160 0 : return ldb_module_oom(module);
1161 : }
1162 26000 : *el->values = data_blob_string_const(vstring);
1163 : }
1164 :
1165 52052 : if (new_val) {
1166 26130 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1167 26130 : if (ret != LDB_SUCCESS) {
1168 0 : return ret;
1169 : }
1170 26130 : el->num_values = 1;
1171 26130 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1172 26130 : if (!el->values) {
1173 0 : return ldb_module_oom(module);
1174 : }
1175 26130 : vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1176 26130 : if (!vstring) {
1177 0 : return ldb_module_oom(module);
1178 : }
1179 26130 : *el->values = data_blob_string_const(vstring);
1180 : }
1181 :
1182 52052 : return LDB_SUCCESS;
1183 : }
1184 :
1185 52052 : int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1186 : struct ldb_message *msg,
1187 : const char *attr,
1188 : const uint32_t *old_val,
1189 : const uint32_t *new_val)
1190 : {
1191 52052 : return dsdb_msg_constrainted_update_int32(module, msg, attr,
1192 : (const int32_t *)old_val,
1193 : (const int32_t *)new_val);
1194 : }
1195 :
1196 52166 : int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1197 : struct ldb_message *msg,
1198 : const char *attr,
1199 : const int64_t *old_val,
1200 : const int64_t *new_val)
1201 : {
1202 : struct ldb_message_element *el;
1203 : int ret;
1204 : char *vstring;
1205 :
1206 52166 : if (old_val) {
1207 214 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1208 214 : if (ret != LDB_SUCCESS) {
1209 0 : return ret;
1210 : }
1211 214 : el->num_values = 1;
1212 214 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1213 214 : if (!el->values) {
1214 0 : return ldb_module_oom(module);
1215 : }
1216 214 : vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1217 214 : if (!vstring) {
1218 0 : return ldb_module_oom(module);
1219 : }
1220 214 : *el->values = data_blob_string_const(vstring);
1221 : }
1222 :
1223 52166 : if (new_val) {
1224 343 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1225 343 : if (ret != LDB_SUCCESS) {
1226 0 : return ret;
1227 : }
1228 343 : el->num_values = 1;
1229 343 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1230 343 : if (!el->values) {
1231 0 : return ldb_module_oom(module);
1232 : }
1233 343 : vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1234 343 : if (!vstring) {
1235 0 : return ldb_module_oom(module);
1236 : }
1237 343 : *el->values = data_blob_string_const(vstring);
1238 : }
1239 :
1240 52166 : return LDB_SUCCESS;
1241 : }
1242 :
1243 52052 : int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1244 : struct ldb_message *msg,
1245 : const char *attr,
1246 : const uint64_t *old_val,
1247 : const uint64_t *new_val)
1248 : {
1249 52052 : return dsdb_msg_constrainted_update_int64(module, msg, attr,
1250 : (const int64_t *)old_val,
1251 : (const int64_t *)new_val);
1252 : }
1253 :
1254 : /*
1255 : update an int32 attribute safely via a constrained delete/add
1256 : */
1257 0 : int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1258 : struct ldb_dn *dn,
1259 : const char *attr,
1260 : const int32_t *old_val,
1261 : const int32_t *new_val,
1262 : struct ldb_request *parent)
1263 : {
1264 : struct ldb_message *msg;
1265 : int ret;
1266 :
1267 0 : msg = ldb_msg_new(module);
1268 0 : if (msg == NULL) {
1269 0 : return ldb_module_oom(module);
1270 : }
1271 0 : msg->dn = dn;
1272 :
1273 0 : ret = dsdb_msg_constrainted_update_int32(module,
1274 : msg, attr,
1275 : old_val,
1276 : new_val);
1277 0 : if (ret != LDB_SUCCESS) {
1278 0 : talloc_free(msg);
1279 0 : return ret;
1280 : }
1281 :
1282 0 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1283 0 : talloc_free(msg);
1284 0 : return ret;
1285 : }
1286 :
1287 0 : int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1288 : struct ldb_dn *dn,
1289 : const char *attr,
1290 : const uint32_t *old_val,
1291 : const uint32_t *new_val,
1292 : struct ldb_request *parent)
1293 : {
1294 0 : return dsdb_module_constrainted_update_int32(module, dn, attr,
1295 : (const int32_t *)old_val,
1296 : (const int32_t *)new_val, parent);
1297 : }
1298 :
1299 : /*
1300 : update an int64 attribute safely via a constrained delete/add
1301 : */
1302 114 : int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1303 : struct ldb_dn *dn,
1304 : const char *attr,
1305 : const int64_t *old_val,
1306 : const int64_t *new_val,
1307 : struct ldb_request *parent)
1308 : {
1309 : struct ldb_message *msg;
1310 : int ret;
1311 :
1312 114 : msg = ldb_msg_new(module);
1313 114 : if (msg == NULL) {
1314 0 : return ldb_module_oom(module);
1315 : }
1316 114 : msg->dn = dn;
1317 :
1318 114 : ret = dsdb_msg_constrainted_update_int64(module,
1319 : msg, attr,
1320 : old_val,
1321 : new_val);
1322 114 : if (ret != LDB_SUCCESS) {
1323 0 : talloc_free(msg);
1324 0 : return ret;
1325 : }
1326 :
1327 114 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1328 114 : talloc_free(msg);
1329 114 : return ret;
1330 : }
1331 :
1332 114 : int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1333 : struct ldb_dn *dn,
1334 : const char *attr,
1335 : const uint64_t *old_val,
1336 : const uint64_t *new_val,
1337 : struct ldb_request *parent)
1338 : {
1339 114 : return dsdb_module_constrainted_update_int64(module, dn, attr,
1340 : (const int64_t *)old_val,
1341 : (const int64_t *)new_val,
1342 : parent);
1343 : }
1344 :
1345 :
1346 1324812 : const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1347 : TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1348 : {
1349 : int ret;
1350 : struct ldb_dn *new_dn;
1351 1324812 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1352 : static const char *attrs[] = { "dSHeuristics", NULL };
1353 : struct ldb_result *res;
1354 :
1355 1324812 : new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1356 1324812 : if (!ldb_dn_add_child_fmt(new_dn,
1357 : "CN=Directory Service,CN=Windows NT,CN=Services")) {
1358 0 : talloc_free(new_dn);
1359 0 : return NULL;
1360 : }
1361 1324812 : ret = dsdb_module_search_dn(module, mem_ctx, &res,
1362 : new_dn,
1363 : attrs,
1364 : DSDB_FLAG_NEXT_MODULE,
1365 : parent);
1366 1324812 : if (ret == LDB_SUCCESS && res->count == 1) {
1367 1036243 : talloc_free(new_dn);
1368 1036243 : return ldb_msg_find_ldb_val(res->msgs[0],
1369 : "dSHeuristics");
1370 : }
1371 288569 : talloc_free(new_dn);
1372 288569 : return NULL;
1373 : }
1374 :
1375 118070 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1376 : {
1377 118070 : TALLOC_CTX *tmp_ctx = talloc_new(module);
1378 : bool result;
1379 118070 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1380 : tmp_ctx, parent);
1381 118070 : if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1382 85948 : result = true;
1383 32122 : } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1384 17 : result = false;
1385 : } else {
1386 32105 : result = true;
1387 : }
1388 :
1389 118070 : talloc_free(tmp_ctx);
1390 118070 : return result;
1391 : }
1392 :
1393 870715 : bool dsdb_user_password_support(struct ldb_module *module,
1394 : TALLOC_CTX *mem_ctx,
1395 : struct ldb_request *parent)
1396 : {
1397 870715 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1398 : bool result;
1399 870715 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1400 : tmp_ctx,
1401 : parent);
1402 870715 : if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1403 739007 : result = false;
1404 131708 : } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1405 131680 : (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1406 108918 : result = false;
1407 : } else {
1408 22790 : result = true;
1409 : }
1410 :
1411 870715 : talloc_free(tmp_ctx);
1412 870715 : return result;
1413 : }
1414 :
1415 16280 : bool dsdb_do_list_object(struct ldb_module *module,
1416 : TALLOC_CTX *mem_ctx,
1417 : struct ldb_request *parent)
1418 : {
1419 16280 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1420 : bool result;
1421 16280 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1422 : tmp_ctx,
1423 : parent);
1424 16280 : if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1425 26 : result = false;
1426 16254 : } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1427 8064 : result = true;
1428 : } else {
1429 8190 : result = false;
1430 : }
1431 :
1432 16280 : talloc_free(tmp_ctx);
1433 16280 : return result;
1434 : }
1435 :
1436 319441 : bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1437 : TALLOC_CTX *mem_ctx,
1438 : struct ldb_request *parent)
1439 : {
1440 319441 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1441 319441 : bool result = false;
1442 319441 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1443 : tmp_ctx,
1444 : parent);
1445 319441 : if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
1446 15858 : uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
1447 15858 : if (val != '0' && val != '2') {
1448 15840 : result = true;
1449 : }
1450 : }
1451 :
1452 319441 : talloc_free(tmp_ctx);
1453 319441 : return result;
1454 : }
1455 :
1456 306 : bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
1457 : TALLOC_CTX *mem_ctx,
1458 : struct ldb_request *parent)
1459 : {
1460 306 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1461 306 : bool result = false;
1462 306 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1463 : tmp_ctx,
1464 : parent);
1465 306 : if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
1466 306 : uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
1467 306 : if (val != '0' && val != '2') {
1468 270 : result = true;
1469 : }
1470 : }
1471 :
1472 306 : talloc_free(tmp_ctx);
1473 306 : return result;
1474 : }
1475 :
1476 : /*
1477 : show the chain of requests, useful for debugging async requests
1478 : */
1479 0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
1480 : {
1481 0 : char *s = ldb_module_call_chain(req, req);
1482 0 : DEBUG(level, ("%s\n", s));
1483 0 : talloc_free(s);
1484 0 : }
1485 :
1486 : /*
1487 : * Get all the values that *might* be added by an ldb message, as a composite
1488 : * ldb element.
1489 : *
1490 : * This is useful when we need to check all the possible values against some
1491 : * criteria.
1492 : *
1493 : * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
1494 : * the returned element might contain more values than would actually end up
1495 : * in the database if the message was run to its conclusion.
1496 : *
1497 : * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
1498 : * returned.
1499 : *
1500 : * The returned element might not be new, and should not be modified or freed
1501 : * before the message is finished.
1502 : */
1503 :
1504 265087 : int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
1505 : const struct ldb_message *msg,
1506 : const char *attr_name,
1507 : struct ldb_message_element **el,
1508 : enum ldb_request_type operation)
1509 : {
1510 : unsigned int i;
1511 265087 : unsigned int el_count = 0;
1512 265087 : unsigned int val_count = 0;
1513 265087 : struct ldb_val *v = NULL;
1514 265087 : struct ldb_message_element *_el = NULL;
1515 265087 : *el = NULL;
1516 :
1517 265087 : if (operation != LDB_ADD && operation != LDB_MODIFY) {
1518 0 : DBG_ERR("inapplicable operation type: %d\n", operation);
1519 0 : return LDB_ERR_OPERATIONS_ERROR;
1520 : }
1521 :
1522 : /* count the adding or replacing elements */
1523 4702414 : for (i = 0; i < msg->num_elements; i++) {
1524 4437327 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1525 : unsigned int tmp;
1526 257774 : if ((operation == LDB_MODIFY) &&
1527 32129 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1528 : == LDB_FLAG_MOD_DELETE)) {
1529 12832 : continue;
1530 : }
1531 244942 : el_count++;
1532 244942 : tmp = val_count + msg->elements[i].num_values;
1533 244942 : if (unlikely(tmp < val_count)) {
1534 0 : DBG_ERR("too many values for one element!");
1535 0 : return LDB_ERR_OPERATIONS_ERROR;
1536 : }
1537 244942 : val_count = tmp;
1538 : }
1539 : }
1540 265087 : if (el_count == 0) {
1541 : /* nothing to see here */
1542 20154 : return LDB_SUCCESS;
1543 : }
1544 :
1545 244933 : if (el_count == 1 || val_count == 0) {
1546 : /*
1547 : * There is one effective element, which we can return as-is,
1548 : * OR there are only elements with zero values -- any of which
1549 : * will do.
1550 : */
1551 1551573 : for (i = 0; i < msg->num_elements; i++) {
1552 1551573 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1553 257732 : if ((operation == LDB_MODIFY) &&
1554 32087 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1555 : == LDB_FLAG_MOD_DELETE)) {
1556 12808 : continue;
1557 : }
1558 244924 : *el = &msg->elements[i];
1559 244924 : return LDB_SUCCESS;
1560 : }
1561 : }
1562 : }
1563 :
1564 9 : _el = talloc_zero(mem_ctx, struct ldb_message_element);
1565 9 : if (_el == NULL) {
1566 0 : return LDB_ERR_OPERATIONS_ERROR;
1567 : }
1568 9 : _el->name = attr_name;
1569 :
1570 9 : if (val_count == 0) {
1571 : /*
1572 : * Seems unlikely, but sometimes we might be adding zero
1573 : * values in multiple separate elements. The talloc zero has
1574 : * already set the expected values = NULL, num_values = 0.
1575 : */
1576 0 : *el = _el;
1577 0 : return LDB_SUCCESS;
1578 : }
1579 :
1580 9 : _el->values = talloc_array(_el, struct ldb_val, val_count);
1581 9 : if (_el->values == NULL) {
1582 0 : talloc_free(_el);
1583 0 : return LDB_ERR_OPERATIONS_ERROR;
1584 : }
1585 9 : _el->num_values = val_count;
1586 :
1587 9 : v = _el->values;
1588 :
1589 36 : for (i = 0; i < msg->num_elements; i++) {
1590 27 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1591 18 : const struct ldb_message_element *tmp_el = &msg->elements[i];
1592 18 : if ((operation == LDB_MODIFY) &&
1593 18 : (LDB_FLAG_MOD_TYPE(tmp_el->flags)
1594 : == LDB_FLAG_MOD_DELETE)) {
1595 0 : continue;
1596 : }
1597 18 : if (tmp_el->values == NULL || tmp_el->num_values == 0) {
1598 0 : continue;
1599 : }
1600 18 : memcpy(v,
1601 18 : tmp_el->values,
1602 18 : tmp_el->num_values * sizeof(*v));
1603 18 : v += tmp_el->num_values;
1604 : }
1605 : }
1606 :
1607 9 : *el = _el;
1608 9 : return LDB_SUCCESS;
1609 : }
1610 :
1611 :
1612 : /*
1613 : * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
1614 : * long as 'msg' and 'original_val' do, and must not be freed.
1615 : */
1616 36 : int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
1617 : const char *attr_name,
1618 : const struct ldb_val **val)
1619 : {
1620 36 : const struct ldb_message_element *el = NULL;
1621 :
1622 : /*
1623 : * The ldb_msg_normalize() call in ldb_request() ensures that
1624 : * there is at most one message element for each
1625 : * attribute. Thus, we don't need a loop to deal with an
1626 : * LDB_ADD.
1627 : */
1628 36 : el = ldb_msg_find_element(msg, attr_name);
1629 36 : if (el == NULL) {
1630 18 : *val = NULL;
1631 18 : return LDB_SUCCESS;
1632 : }
1633 18 : if (el->num_values != 1) {
1634 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1635 : }
1636 :
1637 18 : *val = &el->values[0];
1638 18 : return LDB_SUCCESS;
1639 : }
1640 :
1641 : /*
1642 : * Get the value of a single-valued attribute after processing a
1643 : * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
1644 : * long as 'msg' and 'original_val' do, and must not be freed.
1645 : */
1646 1283 : int dsdb_msg_get_single_value(const struct ldb_message *msg,
1647 : const char *attr_name,
1648 : const struct ldb_val *original_val,
1649 : const struct ldb_val **val,
1650 : enum ldb_request_type operation)
1651 : {
1652 : unsigned idx;
1653 :
1654 1283 : *val = NULL;
1655 :
1656 1283 : if (operation == LDB_ADD) {
1657 36 : if (original_val != NULL) {
1658 : /* This is an error on the caller's part. */
1659 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1660 : }
1661 36 : return dsdb_msg_add_get_single_value(msg, attr_name, val);
1662 : }
1663 :
1664 1247 : SMB_ASSERT(operation == LDB_MODIFY);
1665 :
1666 1247 : *val = original_val;
1667 :
1668 2821 : for (idx = 0; idx < msg->num_elements; ++idx) {
1669 1574 : const struct ldb_message_element *el = &msg->elements[idx];
1670 :
1671 1574 : if (ldb_attr_cmp(el->name, attr_name) != 0) {
1672 1496 : continue;
1673 : }
1674 :
1675 78 : switch (el->flags & LDB_FLAG_MOD_MASK) {
1676 0 : case LDB_FLAG_MOD_ADD:
1677 0 : if (el->num_values != 1) {
1678 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1679 : }
1680 0 : if (*val != NULL) {
1681 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1682 : }
1683 :
1684 0 : *val = &el->values[0];
1685 :
1686 0 : break;
1687 :
1688 78 : case LDB_FLAG_MOD_REPLACE:
1689 78 : if (el->num_values > 1) {
1690 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1691 : }
1692 :
1693 78 : *val = el->num_values ? &el->values[0] : NULL;
1694 :
1695 78 : break;
1696 :
1697 0 : case LDB_FLAG_MOD_DELETE:
1698 0 : if (el->num_values > 1) {
1699 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1700 : }
1701 :
1702 : /*
1703 : * If a value was specified for the delete, we don't
1704 : * bother checking it matches the value we currently
1705 : * have. Any mismatch will be caught later (e.g. in
1706 : * ldb_kv_modify_internal).
1707 : */
1708 :
1709 0 : *val = NULL;
1710 :
1711 0 : break;
1712 : }
1713 : }
1714 :
1715 1247 : return LDB_SUCCESS;
1716 : }
1717 :
1718 : /*
1719 : * This function determines the (last) structural or 88 object class of a passed
1720 : * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1721 : * Without schema this does not work and hence NULL is returned.
1722 : */
1723 5129608 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1724 : const struct ldb_message_element *element)
1725 : {
1726 : const struct dsdb_class *last_class;
1727 :
1728 5129608 : if (schema == NULL) {
1729 0 : return NULL;
1730 : }
1731 :
1732 5129608 : if (element->num_values == 0) {
1733 0 : return NULL;
1734 : }
1735 :
1736 5129608 : last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1737 5129608 : &element->values[element->num_values-1]);
1738 5129608 : if (last_class == NULL) {
1739 0 : return NULL;
1740 : }
1741 5129608 : if (last_class->objectClassCategory > 1) {
1742 3 : return NULL;
1743 : }
1744 :
1745 5129605 : return last_class;
1746 : }
1747 :
1748 3655749 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1749 : const struct ldb_message *msg)
1750 : {
1751 : struct ldb_message_element *oc_el;
1752 :
1753 3655749 : oc_el = ldb_msg_find_element(msg, "objectClass");
1754 3655749 : if (!oc_el) {
1755 0 : return NULL;
1756 : }
1757 :
1758 3655749 : return dsdb_get_last_structural_class(schema, oc_el);
1759 : }
1760 :
1761 : /*
1762 : Get the parent class of an objectclass, or NULL if none exists.
1763 : */
1764 42399 : const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
1765 : const struct dsdb_class *objectclass)
1766 : {
1767 42399 : if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
1768 15030 : return NULL;
1769 : }
1770 :
1771 27369 : if (objectclass->subClassOf == NULL) {
1772 0 : return NULL;
1773 : }
1774 :
1775 27369 : return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
1776 : }
1777 :
1778 : /*
1779 : Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
1780 : two objectclasses must originate from the same schema, to allow for
1781 : pointer-based identity comparison.
1782 : */
1783 15993 : bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
1784 : const struct dsdb_class *struct_objectclass,
1785 : const struct dsdb_class *other_objectclass)
1786 : {
1787 58392 : while (struct_objectclass != NULL) {
1788 : /* Pointer comparison can be used due to the same schema str. */
1789 43362 : if (struct_objectclass == other_objectclass) {
1790 963 : return true;
1791 : }
1792 :
1793 42399 : struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
1794 : }
1795 :
1796 15030 : return false;
1797 : }
1798 :
1799 : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1800 : cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1801 : CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1802 : */
1803 0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1804 : {
1805 : int i, ret;
1806 : char *upper_rdn_attr;
1807 :
1808 0 : for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1809 : /* We need the attribute name in upper case */
1810 0 : upper_rdn_attr = strupper_talloc(dn,
1811 : ldb_dn_get_component_name(dn, i));
1812 0 : if (!upper_rdn_attr) {
1813 0 : return ldb_oom(ldb);
1814 : }
1815 0 : ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1816 0 : *ldb_dn_get_component_val(dn, i));
1817 0 : talloc_free(upper_rdn_attr);
1818 0 : if (ret != LDB_SUCCESS) {
1819 0 : return ret;
1820 : }
1821 : }
1822 0 : return LDB_SUCCESS;
1823 : }
1824 :
1825 : /**
1826 : * Make most specific objectCategory for the objectClass of passed object
1827 : * NOTE: In this implementation we count that it is called on already
1828 : * verified objectClass attribute value. See objectclass.c thorough
1829 : * implementation for all the magic that involves
1830 : *
1831 : * @param ldb ldb context
1832 : * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1833 : * Hence leave the responsibility to the caller.
1834 : * @param obj AD object to determint objectCategory for
1835 : * @param mem_ctx Memory context - usually it is obj actually
1836 : * @param pobjectcategory location to store found objectCategory
1837 : *
1838 : * @return LDB_SUCCESS or error including out of memory error
1839 : */
1840 274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1841 : const struct ldb_message *obj,
1842 : TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1843 : {
1844 : const struct dsdb_class *objectclass;
1845 : struct ldb_message_element *objectclass_element;
1846 : struct dsdb_extended_dn_store_format *dn_format;
1847 :
1848 274 : objectclass_element = ldb_msg_find_element(obj, "objectClass");
1849 274 : if (!objectclass_element) {
1850 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1851 0 : ldb_dn_get_linearized(obj->dn));
1852 0 : return LDB_ERR_OBJECT_CLASS_VIOLATION;
1853 : }
1854 274 : if (objectclass_element->num_values == 0) {
1855 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1856 0 : ldb_dn_get_linearized(obj->dn));
1857 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1858 : }
1859 :
1860 : /*
1861 : * Get the new top-most structural object class and check for
1862 : * unrelated structural classes
1863 : */
1864 274 : objectclass = dsdb_get_last_structural_class(schema,
1865 : objectclass_element);
1866 274 : if (objectclass == NULL) {
1867 0 : ldb_asprintf_errstring(ldb,
1868 : "Failed to find a structural class for %s",
1869 0 : ldb_dn_get_linearized(obj->dn));
1870 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
1871 : }
1872 :
1873 274 : dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1874 : struct dsdb_extended_dn_store_format);
1875 274 : if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1876 : /* Strip off extended components */
1877 0 : struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1878 0 : objectclass->defaultObjectCategory);
1879 0 : *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1880 0 : talloc_free(dn);
1881 : } else {
1882 274 : *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1883 : }
1884 :
1885 274 : if (*pobjectcategory == NULL) {
1886 0 : return ldb_oom(ldb);
1887 : }
1888 :
1889 274 : return LDB_SUCCESS;
1890 : }
|