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