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