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 13477687 : 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 596487 : int ret;
46 596487 : struct ldb_request *req;
47 596487 : TALLOC_CTX *tmp_ctx;
48 596487 : struct ldb_result *res;
49 :
50 13477687 : tmp_ctx = talloc_new(mem_ctx);
51 13477687 : if (tmp_ctx == NULL) {
52 0 : return ldb_oom(ldb_module_get_ctx(module));
53 : }
54 :
55 13477687 : res = talloc_zero(tmp_ctx, struct ldb_result);
56 13477687 : if (!res) {
57 0 : talloc_free(tmp_ctx);
58 0 : return ldb_oom(ldb_module_get_ctx(module));
59 : }
60 :
61 13477687 : 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 13477687 : LDB_REQ_SET_LOCATION(req);
71 13477687 : if (ret != LDB_SUCCESS) {
72 0 : talloc_free(tmp_ctx);
73 0 : return ret;
74 : }
75 :
76 13477687 : ret = dsdb_request_add_controls(req, dsdb_flags);
77 13477687 : if (ret != LDB_SUCCESS) {
78 0 : talloc_free(tmp_ctx);
79 0 : return ret;
80 : }
81 :
82 13477687 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
83 0 : ldb_req_mark_trusted(req);
84 : }
85 :
86 : /* Run the new request */
87 13477687 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
88 13477413 : 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 13477687 : if (ret == LDB_SUCCESS) {
97 13477666 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
98 : }
99 :
100 13477687 : if (ret != LDB_SUCCESS) {
101 494830 : talloc_free(tmp_ctx);
102 494830 : return ret;
103 : }
104 :
105 12982857 : if (res->count != 1) {
106 : /* we may be reading a DB that does not have the 'check base on search' option... */
107 21016 : ret = LDB_ERR_NO_SUCH_OBJECT;
108 21016 : 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 12961841 : *_res = talloc_steal(mem_ctx, res);
113 : }
114 12982857 : talloc_free(tmp_ctx);
115 12982857 : return ret;
116 : }
117 :
118 13191941 : 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 165535 : int ret;
129 165535 : struct ldb_request *req;
130 165535 : TALLOC_CTX *tmp_ctx;
131 165535 : struct ldb_result *res;
132 :
133 13191941 : tmp_ctx = talloc_new(mem_ctx);
134 13191941 : 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 13191941 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
140 :
141 13191941 : res = talloc_zero(tmp_ctx, struct ldb_result);
142 13191941 : if (!res) {
143 0 : talloc_free(tmp_ctx);
144 0 : return ldb_oom(ldb_module_get_ctx(module));
145 : }
146 :
147 13191941 : 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 13191941 : LDB_REQ_SET_LOCATION(req);
157 13191941 : if (ret != LDB_SUCCESS) {
158 0 : talloc_free(tmp_ctx);
159 0 : return ret;
160 : }
161 :
162 13191941 : ret = dsdb_request_add_controls(req, dsdb_flags);
163 13191941 : if (ret != LDB_SUCCESS) {
164 0 : talloc_free(tmp_ctx);
165 0 : return ret;
166 : }
167 :
168 13191941 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
169 0 : ldb_req_mark_trusted(req);
170 : }
171 :
172 13191941 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
173 13191938 : 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 13191941 : if (ret == LDB_SUCCESS) {
182 13191941 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
183 : }
184 :
185 13191941 : if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
186 10633392 : if (res->count == 0) {
187 7174 : talloc_free(tmp_ctx);
188 7174 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
189 : }
190 10626218 : 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 13184767 : talloc_free(req);
198 13184767 : if (ret == LDB_SUCCESS) {
199 13183713 : *_res = talloc_steal(mem_ctx, res);
200 : }
201 13184767 : talloc_free(tmp_ctx);
202 13184767 : return ret;
203 : }
204 :
205 : /*
206 : search for attrs in the modules below
207 : */
208 13190389 : 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 165535 : int ret;
218 165535 : TALLOC_CTX *tmp_ctx;
219 165535 : va_list ap;
220 165535 : char *expression;
221 165535 : struct ldb_parse_tree *tree;
222 :
223 : /* cross-partitions searches with a basedn break multi-domain support */
224 13190389 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
225 :
226 13190389 : tmp_ctx = talloc_new(mem_ctx);
227 13190389 : if (tmp_ctx == NULL) {
228 0 : return ldb_oom(ldb_module_get_ctx(module));
229 : }
230 :
231 13190389 : if (format) {
232 12452327 : va_start(ap, format);
233 12452327 : expression = talloc_vasprintf(tmp_ctx, format, ap);
234 12452327 : va_end(ap);
235 :
236 12452327 : if (!expression) {
237 0 : talloc_free(tmp_ctx);
238 0 : return ldb_oom(ldb_module_get_ctx(module));
239 : }
240 : } else {
241 713822 : expression = NULL;
242 : }
243 :
244 13190389 : tree = ldb_parse_tree(tmp_ctx, expression);
245 13190389 : 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 13190389 : 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 13190389 : talloc_free(tmp_ctx);
263 13190389 : return ret;
264 : }
265 :
266 : /*
267 : find an object given a GUID. This searches across all partitions
268 : */
269 79042 : 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 79042 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
278 1602 : int ret;
279 :
280 79042 : 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 79042 : if (ret != LDB_SUCCESS) {
289 0 : talloc_free(tmp_ctx);
290 0 : return ret;
291 : }
292 79042 : if (res->count == 0) {
293 41 : talloc_free(tmp_ctx);
294 41 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
295 : }
296 79001 : 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 79001 : *_msg = talloc_steal(mem_ctx, res->msgs[0]);
304 :
305 79001 : talloc_free(tmp_ctx);
306 79001 : 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 27254 : 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 27254 : TALLOC_CTX *tmp_ctx = talloc_new(module);
347 46 : int ret;
348 46 : NTSTATUS status;
349 :
350 27254 : 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 27254 : 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 27251 : status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
363 27251 : 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 27251 : talloc_free(tmp_ctx);
369 27251 : 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 19748826 : 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 1124188 : struct ldb_request *req;
388 1124188 : int ret;
389 19748826 : struct ldb_context *ldb = ldb_module_get_ctx(module);
390 19748826 : TALLOC_CTX *tmp_ctx = talloc_new(module);
391 1124188 : struct ldb_result *res;
392 :
393 19748826 : if (_res != NULL) {
394 19381262 : (*_res) = NULL;
395 : }
396 :
397 19748826 : res = talloc_zero(tmp_ctx, struct ldb_result);
398 19748826 : if (!res) {
399 0 : talloc_free(tmp_ctx);
400 0 : return ldb_oom(ldb_module_get_ctx(module));
401 : }
402 :
403 19748826 : 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 19748826 : LDB_REQ_SET_LOCATION(req);
412 19748826 : if (ret != LDB_SUCCESS) {
413 0 : talloc_free(tmp_ctx);
414 0 : return ret;
415 : }
416 :
417 19748826 : ret = dsdb_request_add_controls(req, dsdb_flags);
418 19748826 : if (ret != LDB_SUCCESS) {
419 0 : talloc_free(tmp_ctx);
420 0 : return ret;
421 : }
422 :
423 19748826 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
424 367564 : ldb_req_mark_trusted(req);
425 : }
426 :
427 : /* Run the new request */
428 19748826 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
429 19381262 : ret = ldb_next_request(module, req);
430 367564 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
431 367564 : 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 19748826 : if (ret == LDB_SUCCESS) {
438 19748826 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
439 : }
440 :
441 19748826 : if (_res != NULL && ret == LDB_SUCCESS) {
442 19381262 : (*_res) = talloc_steal(mem_ctx, res);
443 : }
444 :
445 19748826 : talloc_free(tmp_ctx);
446 19748826 : return ret;
447 : }
448 :
449 :
450 : /*
451 : a ldb_modify request operating on modules below the
452 : current module
453 : */
454 403968 : 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 403968 : struct ldb_context *ldb = ldb_module_get_ctx(module);
462 403968 : TALLOC_CTX *tmp_ctx = talloc_new(module);
463 8038 : struct ldb_result *res;
464 :
465 403968 : res = talloc_zero(tmp_ctx, struct ldb_result);
466 403968 : if (!res) {
467 0 : talloc_free(tmp_ctx);
468 0 : return ldb_oom(ldb_module_get_ctx(module));
469 : }
470 :
471 403968 : ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
472 : message,
473 : NULL,
474 : res,
475 : ldb_modify_default_callback,
476 : parent);
477 403968 : LDB_REQ_SET_LOCATION(mod_req);
478 403968 : if (ret != LDB_SUCCESS) {
479 0 : talloc_free(tmp_ctx);
480 0 : return ret;
481 : }
482 :
483 403968 : ret = dsdb_request_add_controls(mod_req, dsdb_flags);
484 403968 : if (ret != LDB_SUCCESS) {
485 0 : talloc_free(tmp_ctx);
486 0 : return ret;
487 : }
488 :
489 403968 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
490 0 : ldb_req_mark_trusted(mod_req);
491 : }
492 :
493 : /* Run the new request */
494 403968 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
495 160559 : ret = ldb_next_request(module, mod_req);
496 243409 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
497 2 : ret = ldb_request(ldb_module_get_ctx(module), mod_req);
498 : } else {
499 243407 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
500 243407 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
501 243407 : ret = ops->modify(module, mod_req);
502 : }
503 403968 : if (ret == LDB_SUCCESS) {
504 403968 : ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
505 : }
506 :
507 403968 : talloc_free(tmp_ctx);
508 403968 : return ret;
509 : }
510 :
511 :
512 :
513 : /*
514 : a ldb_rename request operating on modules below the
515 : current module
516 : */
517 160118 : 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 160118 : struct ldb_context *ldb = ldb_module_get_ctx(module);
525 160118 : TALLOC_CTX *tmp_ctx = talloc_new(module);
526 297 : struct ldb_result *res;
527 :
528 160118 : res = talloc_zero(tmp_ctx, struct ldb_result);
529 160118 : if (!res) {
530 0 : talloc_free(tmp_ctx);
531 0 : return ldb_oom(ldb_module_get_ctx(module));
532 : }
533 :
534 160118 : 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 160118 : LDB_REQ_SET_LOCATION(req);
542 160118 : if (ret != LDB_SUCCESS) {
543 0 : talloc_free(tmp_ctx);
544 0 : return ret;
545 : }
546 :
547 160118 : ret = dsdb_request_add_controls(req, dsdb_flags);
548 160118 : if (ret != LDB_SUCCESS) {
549 0 : talloc_free(tmp_ctx);
550 0 : return ret;
551 : }
552 :
553 160118 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
554 0 : ldb_req_mark_trusted(req);
555 : }
556 :
557 : /* Run the new request */
558 160118 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
559 159544 : ret = ldb_next_request(module, req);
560 574 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
561 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
562 : } else {
563 574 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
564 574 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
565 574 : ret = ops->rename(module, req);
566 : }
567 160118 : if (ret == LDB_SUCCESS) {
568 160116 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
569 : }
570 :
571 160118 : talloc_free(tmp_ctx);
572 160118 : 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 82219 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
704 : const struct ldb_message_element *el)
705 : {
706 82219 : bool found_active = false;
707 1095 : unsigned int i;
708 :
709 82219 : if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
710 12221 : el->num_values < 2) {
711 81007 : return LDB_SUCCESS;
712 : }
713 :
714 349 : for (i=0; i<el->num_values; i++) {
715 235 : if (!dsdb_dn_is_deleted_val(&el->values[i])) {
716 110 : if (found_active) {
717 3 : return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
718 : }
719 107 : found_active = true;
720 : }
721 : }
722 :
723 114 : return LDB_SUCCESS;
724 : }
725 :
726 :
727 364008 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
728 : const char *feature,
729 : bool *found)
730 : {
731 364008 : struct ldb_context *ldb = ldb_module_get_ctx(module);
732 12032 : struct ldb_result *res;
733 12032 : static const char * const samba_dsdb_attrs[] = {
734 : SAMBA_COMPATIBLE_FEATURES_ATTR,
735 : NULL
736 : };
737 12032 : int ret;
738 364008 : struct ldb_dn *samba_dsdb_dn = NULL;
739 364008 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
740 364008 : if (tmp_ctx == NULL) {
741 0 : *found = false;
742 0 : return ldb_oom(ldb);
743 : }
744 364008 : *found = false;
745 :
746 364008 : samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
747 364008 : if (samba_dsdb_dn == NULL) {
748 0 : TALLOC_FREE(tmp_ctx);
749 0 : return ldb_oom(ldb);
750 : }
751 :
752 364008 : 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 364008 : if (ret == LDB_SUCCESS) {
760 364008 : *found = ldb_msg_check_string_attribute(
761 364008 : 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 364008 : TALLOC_FREE(tmp_ctx);
769 364008 : 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 119618 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
783 : {
784 2212 : TALLOC_CTX *tmp_ctx;
785 119618 : struct ldb_context *ldb = ldb_module_get_ctx(module);
786 2212 : struct ldb_result *res;
787 2212 : struct ldb_dn *search_dn;
788 2212 : struct GUID search_guid;
789 2212 : static const char * const attrs[] = {"msDS-EnabledFeature", NULL};
790 2212 : int ret;
791 2212 : unsigned int i;
792 2212 : struct ldb_message_element *el;
793 2212 : struct ldb_dn *feature_dn;
794 :
795 119618 : tmp_ctx = talloc_new(ldb);
796 :
797 119618 : feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
798 119618 : if (feature_dn == NULL) {
799 0 : talloc_free(tmp_ctx);
800 0 : return ldb_operr(ldb_module_get_ctx(module));
801 : }
802 :
803 119618 : *feature_enabled = false;
804 :
805 119618 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
806 119618 : if (ret != LDB_SUCCESS) {
807 1813 : ldb_asprintf_errstring(ldb,
808 : "Could not find the feature object - dn: %s\n",
809 : ldb_dn_get_linearized(feature_dn));
810 1813 : talloc_free(tmp_ctx);
811 1813 : return LDB_ERR_NO_SUCH_OBJECT;
812 : }
813 117805 : 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 117805 : talloc_free(tmp_ctx);
840 117805 : 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 159180841 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
921 : {
922 159180841 : struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
923 :
924 159180841 : if (!ares) {
925 0 : return ldb_module_done(up_req, NULL, NULL,
926 : LDB_ERR_OPERATIONS_ERROR);
927 : }
928 :
929 159180841 : if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
930 55705706 : return ldb_module_done(up_req, ares->controls,
931 : ares->response, ares->error);
932 : }
933 :
934 : /* Otherwise pass on the callback */
935 103475135 : switch (ares->type) {
936 99282376 : case LDB_REPLY_ENTRY:
937 99282376 : return ldb_module_send_entry(up_req, ares->message,
938 : ares->controls);
939 :
940 4192759 : case LDB_REPLY_REFERRAL:
941 4192759 : 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 227117 : 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 227117 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1046 1106 : struct ldb_request *req;
1047 1106 : struct ldb_message *msg;
1048 1106 : struct dsdb_control_current_partition *p_ctrl;
1049 1106 : int ret;
1050 1106 : struct ldb_result *res;
1051 :
1052 227117 : msg = ldb_msg_new(module);
1053 227117 : if (msg == NULL) {
1054 0 : return ldb_module_oom(module);
1055 : }
1056 :
1057 227117 : msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1058 227117 : if (msg->dn == NULL) {
1059 0 : talloc_free(msg);
1060 0 : return ldb_operr(ldb_module_get_ctx(module));
1061 : }
1062 :
1063 227117 : res = talloc_zero(msg, struct ldb_result);
1064 227117 : if (!res) {
1065 0 : talloc_free(msg);
1066 0 : return ldb_module_oom(module);
1067 : }
1068 :
1069 227117 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1070 227117 : if (ret != LDB_SUCCESS) {
1071 0 : talloc_free(msg);
1072 0 : return ret;
1073 : }
1074 227117 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1075 :
1076 : /* urgent_uSN is optional so may not be stored */
1077 227117 : if (urgent_uSN) {
1078 33704 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1079 : urgent_uSN);
1080 33704 : if (ret != LDB_SUCCESS) {
1081 0 : talloc_free(msg);
1082 0 : return ret;
1083 : }
1084 33704 : msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1085 : }
1086 :
1087 :
1088 227117 : p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1089 227117 : if (p_ctrl == NULL) {
1090 0 : talloc_free(msg);
1091 0 : return ldb_oom(ldb);
1092 : }
1093 227117 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1094 227117 : p_ctrl->dn = dn;
1095 227117 : ret = ldb_build_mod_req(&req, ldb, msg,
1096 : msg,
1097 : NULL,
1098 : res,
1099 : ldb_modify_default_callback,
1100 : parent);
1101 227117 : LDB_REQ_SET_LOCATION(req);
1102 228096 : again:
1103 228096 : if (ret != LDB_SUCCESS) {
1104 0 : talloc_free(msg);
1105 0 : return ret;
1106 : }
1107 :
1108 228096 : ret = ldb_request_add_control(req,
1109 : DSDB_CONTROL_CURRENT_PARTITION_OID,
1110 : false, p_ctrl);
1111 228096 : if (ret != LDB_SUCCESS) {
1112 0 : talloc_free(msg);
1113 0 : return ret;
1114 : }
1115 :
1116 : /* Run the new request */
1117 228096 : ret = ldb_next_request(module, req);
1118 :
1119 228096 : if (ret == LDB_SUCCESS) {
1120 228096 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1121 : }
1122 228096 : 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 227117 : talloc_free(msg);
1134 :
1135 227117 : return ret;
1136 : }
1137 :
1138 52472039 : bool dsdb_module_am_system(struct ldb_module *module)
1139 : {
1140 52472039 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1141 3066619 : struct auth_session_info *session_info
1142 52472039 : = talloc_get_type(
1143 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1144 : struct auth_session_info);
1145 52472039 : return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1146 : }
1147 :
1148 32673733 : bool dsdb_module_am_administrator(struct ldb_module *module)
1149 : {
1150 32673733 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1151 1752323 : struct auth_session_info *session_info
1152 32673733 : = talloc_get_type(
1153 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1154 : struct auth_session_info);
1155 32673733 : 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 35671301 : 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 35671301 : struct ldb_control *as_system = NULL;
1168 :
1169 35671301 : as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
1170 35671301 : if (as_system != NULL) {
1171 16214742 : switch (strip_critical) {
1172 15086540 : case SYSTEM_CONTROL_KEEP_CRITICAL:
1173 15086540 : break;
1174 284771 : case SYSTEM_CONTROL_STRIP_CRITICAL:
1175 284771 : as_system->critical = 0;
1176 284771 : break;
1177 : }
1178 :
1179 16214742 : return true;
1180 : }
1181 :
1182 19456559 : return dsdb_module_am_system(module);
1183 : }
1184 :
1185 : /*
1186 : check if the recyclebin is enabled
1187 : */
1188 119618 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1189 : {
1190 119618 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1191 2212 : struct GUID recyclebin_guid;
1192 2212 : int ret;
1193 :
1194 119618 : GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1195 :
1196 119618 : ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1197 119618 : if (ret != LDB_SUCCESS) {
1198 1813 : ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1199 1813 : return ret;
1200 : }
1201 :
1202 115615 : return LDB_SUCCESS;
1203 : }
1204 :
1205 69759 : 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 69759 : if (old_val) {
1216 34857 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1217 34857 : if (ret != LDB_SUCCESS) {
1218 0 : return ret;
1219 : }
1220 34857 : el->num_values = 1;
1221 34857 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1222 34857 : if (!el->values) {
1223 0 : return ldb_module_oom(module);
1224 : }
1225 34857 : vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1226 34857 : if (!vstring) {
1227 0 : return ldb_module_oom(module);
1228 : }
1229 34857 : *el->values = data_blob_string_const(vstring);
1230 : }
1231 :
1232 69759 : if (new_val) {
1233 35011 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1234 35011 : if (ret != LDB_SUCCESS) {
1235 0 : return ret;
1236 : }
1237 35011 : el->num_values = 1;
1238 35011 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1239 35011 : if (!el->values) {
1240 0 : return ldb_module_oom(module);
1241 : }
1242 35011 : vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1243 35011 : if (!vstring) {
1244 0 : return ldb_module_oom(module);
1245 : }
1246 35011 : *el->values = data_blob_string_const(vstring);
1247 : }
1248 :
1249 69414 : return LDB_SUCCESS;
1250 : }
1251 :
1252 69758 : 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 69758 : return dsdb_msg_constrainted_update_int32(module, msg, attr,
1259 : (const int32_t *)old_val,
1260 : (const int32_t *)new_val);
1261 : }
1262 :
1263 69903 : 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 69903 : if (old_val) {
1274 279 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1275 279 : if (ret != LDB_SUCCESS) {
1276 0 : return ret;
1277 : }
1278 279 : el->num_values = 1;
1279 279 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1280 279 : if (!el->values) {
1281 0 : return ldb_module_oom(module);
1282 : }
1283 279 : vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1284 279 : if (!vstring) {
1285 0 : return ldb_module_oom(module);
1286 : }
1287 279 : *el->values = data_blob_string_const(vstring);
1288 : }
1289 :
1290 69903 : if (new_val) {
1291 432 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1292 432 : if (ret != LDB_SUCCESS) {
1293 0 : return ret;
1294 : }
1295 432 : el->num_values = 1;
1296 432 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1297 432 : if (!el->values) {
1298 0 : return ldb_module_oom(module);
1299 : }
1300 432 : vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1301 432 : if (!vstring) {
1302 0 : return ldb_module_oom(module);
1303 : }
1304 432 : *el->values = data_blob_string_const(vstring);
1305 : }
1306 :
1307 69559 : return LDB_SUCCESS;
1308 : }
1309 :
1310 69758 : 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 69758 : 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 145 : 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 145 : msg = ldb_msg_new(module);
1380 145 : if (msg == NULL) {
1381 0 : return ldb_module_oom(module);
1382 : }
1383 145 : msg->dn = dn;
1384 :
1385 145 : ret = dsdb_msg_constrainted_update_int64(module,
1386 : msg, attr,
1387 : old_val,
1388 : new_val);
1389 145 : if (ret != LDB_SUCCESS) {
1390 0 : talloc_free(msg);
1391 0 : return ret;
1392 : }
1393 :
1394 145 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1395 145 : talloc_free(msg);
1396 145 : return ret;
1397 : }
1398 :
1399 145 : 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 145 : 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 2226849 : const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1414 : TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1415 : {
1416 210119 : int ret;
1417 210119 : struct ldb_dn *new_dn;
1418 2226849 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1419 210119 : static const char * const attrs[] = { "dSHeuristics", NULL };
1420 210119 : struct ldb_result *res;
1421 :
1422 2226849 : new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1423 2226849 : 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 2226849 : ret = dsdb_module_search_dn(module, mem_ctx, &res,
1429 : new_dn,
1430 : attrs,
1431 : DSDB_FLAG_NEXT_MODULE,
1432 : parent);
1433 2226849 : if (ret == LDB_SUCCESS && res->count == 1) {
1434 1734198 : talloc_free(new_dn);
1435 1734198 : 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 182651 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1443 : {
1444 182651 : TALLOC_CTX *tmp_ctx = talloc_new(module);
1445 6048 : bool result;
1446 182651 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1447 : tmp_ctx, parent);
1448 182651 : if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1449 143347 : result = true;
1450 33256 : } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1451 17 : result = false;
1452 : } else {
1453 33239 : result = true;
1454 : }
1455 :
1456 182651 : talloc_free(tmp_ctx);
1457 182651 : return result;
1458 : }
1459 :
1460 1488988 : bool dsdb_user_password_support(struct ldb_module *module,
1461 : TALLOC_CTX *mem_ctx,
1462 : struct ldb_request *parent)
1463 : {
1464 1488988 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1465 120525 : bool result;
1466 1488988 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1467 : tmp_ctx,
1468 : parent);
1469 1488988 : if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1470 1233611 : result = false;
1471 134852 : } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1472 134816 : (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1473 108139 : result = false;
1474 : } else {
1475 26713 : result = true;
1476 : }
1477 :
1478 1488988 : talloc_free(tmp_ctx);
1479 1488988 : 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 538624 : bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1504 : TALLOC_CTX *mem_ctx,
1505 : struct ldb_request *parent)
1506 : {
1507 538624 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1508 538624 : bool result = false;
1509 538624 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1510 : tmp_ctx,
1511 : parent);
1512 538624 : 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 538624 : talloc_free(tmp_ctx);
1520 538624 : 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 403882 : 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 403882 : unsigned int el_count = 0;
1579 403882 : unsigned int val_count = 0;
1580 403882 : struct ldb_val *v = NULL;
1581 403882 : struct ldb_message_element *_el = NULL;
1582 403882 : *el = NULL;
1583 :
1584 403882 : 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 7311046 : for (i = 0; i < msg->num_elements; i++) {
1591 6907164 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1592 42608 : unsigned int tmp;
1593 387699 : if ((operation == LDB_MODIFY) &&
1594 37427 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1595 : == LDB_FLAG_MOD_DELETE)) {
1596 14394 : continue;
1597 : }
1598 373305 : el_count++;
1599 373305 : tmp = val_count + msg->elements[i].num_values;
1600 373305 : 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 330733 : val_count = tmp;
1605 : }
1606 : }
1607 403882 : if (el_count == 0) {
1608 : /* nothing to see here */
1609 29441 : return LDB_SUCCESS;
1610 : }
1611 :
1612 373296 : 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 2416153 : for (i = 0; i < msg->num_elements; i++) {
1619 2416153 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1620 387657 : if ((operation == LDB_MODIFY) &&
1621 37385 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1622 : == LDB_FLAG_MOD_DELETE)) {
1623 14370 : continue;
1624 : }
1625 373287 : *el = &msg->elements[i];
1626 373287 : 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 6658332 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1791 : const struct ldb_message_element *element)
1792 : {
1793 297938 : const struct dsdb_class *last_class;
1794 :
1795 6658332 : if (schema == NULL) {
1796 0 : return NULL;
1797 : }
1798 :
1799 6658332 : if (element->num_values == 0) {
1800 0 : return NULL;
1801 : }
1802 :
1803 6956270 : last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1804 6658332 : &element->values[element->num_values-1]);
1805 6658332 : if (last_class == NULL) {
1806 0 : return NULL;
1807 : }
1808 6658332 : if (last_class->objectClassCategory > 1) {
1809 3 : return NULL;
1810 : }
1811 :
1812 6360391 : return last_class;
1813 : }
1814 :
1815 3941375 : 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 3941375 : oc_el = ldb_msg_find_element(msg, "objectClass");
1821 3941375 : if (!oc_el) {
1822 0 : return NULL;
1823 : }
1824 :
1825 3941375 : 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 : }
1958 :
1959 : /*
1960 : * Remove all password related attributes.
1961 : */
1962 48962 : void dsdb_remove_password_related_attrs(struct ldb_message *msg,
1963 : bool userPassword)
1964 : {
1965 48962 : if (userPassword) {
1966 3945 : ldb_msg_remove_attr(msg, "userPassword");
1967 : }
1968 48962 : ldb_msg_remove_attr(msg, "clearTextPassword");
1969 48962 : ldb_msg_remove_attr(msg, "unicodePwd");
1970 48962 : ldb_msg_remove_attr(msg, "ntPwdHistory");
1971 48962 : ldb_msg_remove_attr(msg, "dBCSPwd");
1972 48962 : ldb_msg_remove_attr(msg, "lmPwdHistory");
1973 48962 : ldb_msg_remove_attr(msg, "supplementalCredentials");
1974 48962 : ldb_msg_remove_attr(msg, "pwdLastSet");
1975 48962 : }
|