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 9987776 : int dsdb_module_search_dn(struct ldb_module *module,
38 : TALLOC_CTX *mem_ctx,
39 : struct ldb_result **_res,
40 : struct ldb_dn *basedn,
41 : const char * const *attrs,
42 : uint32_t dsdb_flags,
43 : struct ldb_request *parent)
44 : {
45 : int ret;
46 : struct ldb_request *req;
47 : TALLOC_CTX *tmp_ctx;
48 : struct ldb_result *res;
49 :
50 9987776 : tmp_ctx = talloc_new(mem_ctx);
51 :
52 9987776 : res = talloc_zero(tmp_ctx, struct ldb_result);
53 9987776 : if (!res) {
54 0 : talloc_free(tmp_ctx);
55 0 : return ldb_oom(ldb_module_get_ctx(module));
56 : }
57 :
58 9987776 : 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 9987776 : LDB_REQ_SET_LOCATION(req);
68 9987776 : if (ret != LDB_SUCCESS) {
69 0 : talloc_free(tmp_ctx);
70 0 : return ret;
71 : }
72 :
73 9987776 : ret = dsdb_request_add_controls(req, dsdb_flags);
74 9987776 : if (ret != LDB_SUCCESS) {
75 0 : talloc_free(tmp_ctx);
76 0 : return ret;
77 : }
78 :
79 9987776 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
80 0 : ldb_req_mark_trusted(req);
81 : }
82 :
83 : /* Run the new request */
84 9987776 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
85 9987502 : 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 9987776 : if (ret == LDB_SUCCESS) {
94 9987755 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
95 : }
96 :
97 9987776 : if (ret != LDB_SUCCESS) {
98 251243 : talloc_free(tmp_ctx);
99 251243 : return ret;
100 : }
101 :
102 9736533 : if (res->count != 1) {
103 : /* we may be reading a DB that does not have the 'check base on search' option... */
104 12098 : ret = LDB_ERR_NO_SUCH_OBJECT;
105 12098 : 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 9724435 : *_res = talloc_steal(mem_ctx, res);
110 : }
111 9736533 : talloc_free(tmp_ctx);
112 9736533 : return ret;
113 : }
114 :
115 9847957 : int dsdb_module_search_tree(struct ldb_module *module,
116 : TALLOC_CTX *mem_ctx,
117 : struct ldb_result **_res,
118 : struct ldb_dn *basedn,
119 : enum ldb_scope scope,
120 : struct ldb_parse_tree *tree,
121 : const char * const *attrs,
122 : int dsdb_flags,
123 : struct ldb_request *parent)
124 : {
125 : int ret;
126 : struct ldb_request *req;
127 : TALLOC_CTX *tmp_ctx;
128 : struct ldb_result *res;
129 :
130 9847957 : tmp_ctx = talloc_new(mem_ctx);
131 :
132 : /* cross-partitions searches with a basedn break multi-domain support */
133 9847957 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
134 :
135 9847957 : res = talloc_zero(tmp_ctx, struct ldb_result);
136 9847957 : if (!res) {
137 0 : talloc_free(tmp_ctx);
138 0 : return ldb_oom(ldb_module_get_ctx(module));
139 : }
140 :
141 9847957 : 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 9847957 : LDB_REQ_SET_LOCATION(req);
151 9847957 : if (ret != LDB_SUCCESS) {
152 0 : talloc_free(tmp_ctx);
153 0 : return ret;
154 : }
155 :
156 9847957 : ret = dsdb_request_add_controls(req, dsdb_flags);
157 9847957 : if (ret != LDB_SUCCESS) {
158 0 : talloc_free(tmp_ctx);
159 0 : return ret;
160 : }
161 :
162 9847957 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
163 0 : ldb_req_mark_trusted(req);
164 : }
165 :
166 9847957 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
167 9847954 : 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 9847957 : if (ret == LDB_SUCCESS) {
176 9847957 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
177 : }
178 :
179 9847957 : if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
180 7902826 : if (res->count == 0) {
181 6692 : talloc_free(tmp_ctx);
182 6692 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
183 : }
184 7896134 : 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 9841265 : talloc_free(req);
192 9841265 : if (ret == LDB_SUCCESS) {
193 9840298 : *_res = talloc_steal(mem_ctx, res);
194 : }
195 9841265 : talloc_free(tmp_ctx);
196 9841265 : return ret;
197 : }
198 :
199 : /*
200 : search for attrs in the modules below
201 : */
202 9846614 : int dsdb_module_search(struct ldb_module *module,
203 : TALLOC_CTX *mem_ctx,
204 : struct ldb_result **_res,
205 : struct ldb_dn *basedn, enum ldb_scope scope,
206 : const char * const *attrs,
207 : int dsdb_flags,
208 : struct ldb_request *parent,
209 : const char *format, ...) _PRINTF_ATTRIBUTE(9, 10)
210 : {
211 : int ret;
212 : TALLOC_CTX *tmp_ctx;
213 : va_list ap;
214 : char *expression;
215 : struct ldb_parse_tree *tree;
216 :
217 : /* cross-partitions searches with a basedn break multi-domain support */
218 9846614 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
219 :
220 9846614 : tmp_ctx = talloc_new(mem_ctx);
221 :
222 9846614 : if (format) {
223 9310076 : va_start(ap, format);
224 9310076 : expression = talloc_vasprintf(tmp_ctx, format, ap);
225 9310076 : va_end(ap);
226 :
227 9310076 : if (!expression) {
228 0 : talloc_free(tmp_ctx);
229 0 : return ldb_oom(ldb_module_get_ctx(module));
230 : }
231 : } else {
232 517398 : expression = NULL;
233 : }
234 :
235 9846614 : tree = ldb_parse_tree(tmp_ctx, expression);
236 9846614 : 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 9846614 : 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 9846614 : talloc_free(tmp_ctx);
254 9846614 : return ret;
255 : }
256 :
257 : /*
258 : find a DN given a GUID. This searches across all partitions
259 : */
260 35798 : int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
261 : const struct GUID *guid, struct ldb_dn **dn,
262 : struct ldb_request *parent)
263 : {
264 : struct ldb_result *res;
265 35798 : const char *attrs[] = { NULL };
266 35798 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
267 : int ret;
268 :
269 35798 : ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
270 : attrs,
271 : DSDB_FLAG_NEXT_MODULE |
272 : DSDB_SEARCH_SHOW_RECYCLED |
273 : DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
274 : DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
275 : parent,
276 : "objectGUID=%s", GUID_string(tmp_ctx, guid));
277 35798 : if (ret != LDB_SUCCESS) {
278 0 : talloc_free(tmp_ctx);
279 0 : return ret;
280 : }
281 35798 : if (res->count == 0) {
282 56 : talloc_free(tmp_ctx);
283 56 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
284 : }
285 35742 : if (res->count != 1) {
286 0 : ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching objectGUID %s\n",
287 : GUID_string(tmp_ctx, guid));
288 0 : talloc_free(tmp_ctx);
289 0 : return LDB_ERR_OPERATIONS_ERROR;
290 : }
291 :
292 35742 : *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
293 :
294 35742 : talloc_free(tmp_ctx);
295 35742 : return LDB_SUCCESS;
296 : }
297 :
298 : /*
299 : find a GUID given a DN.
300 : */
301 11123 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
302 : struct ldb_request *parent)
303 : {
304 11123 : const char *attrs[] = { NULL };
305 : struct ldb_result *res;
306 11123 : TALLOC_CTX *tmp_ctx = talloc_new(module);
307 : int ret;
308 : NTSTATUS status;
309 :
310 11123 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, dn, attrs,
311 : DSDB_FLAG_NEXT_MODULE |
312 : DSDB_SEARCH_SHOW_RECYCLED |
313 : DSDB_SEARCH_SHOW_EXTENDED_DN,
314 : parent);
315 11123 : if (ret != LDB_SUCCESS) {
316 3 : ldb_asprintf_errstring(ldb_module_get_ctx(module), "Failed to find GUID for %s",
317 : ldb_dn_get_linearized(dn));
318 3 : talloc_free(tmp_ctx);
319 3 : return ret;
320 : }
321 :
322 11120 : status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
323 11120 : if (!NT_STATUS_IS_OK(status)) {
324 0 : talloc_free(tmp_ctx);
325 0 : return ldb_operr(ldb_module_get_ctx(module));
326 : }
327 :
328 11120 : talloc_free(tmp_ctx);
329 11120 : return LDB_SUCCESS;
330 : }
331 :
332 :
333 : /*
334 : a ldb_extended request operating on modules below the
335 : current module
336 :
337 : Note that this does not automatically start a transaction. If you
338 : need a transaction the caller needs to start it as needed.
339 : */
340 14263475 : int dsdb_module_extended(struct ldb_module *module,
341 : TALLOC_CTX *mem_ctx,
342 : struct ldb_result **_res,
343 : const char* oid, void* data,
344 : uint32_t dsdb_flags,
345 : struct ldb_request *parent)
346 : {
347 : struct ldb_request *req;
348 : int ret;
349 14263475 : struct ldb_context *ldb = ldb_module_get_ctx(module);
350 14263475 : TALLOC_CTX *tmp_ctx = talloc_new(module);
351 : struct ldb_result *res;
352 :
353 14263475 : if (_res != NULL) {
354 13933044 : (*_res) = NULL;
355 : }
356 :
357 14263475 : res = talloc_zero(tmp_ctx, struct ldb_result);
358 14263475 : if (!res) {
359 0 : talloc_free(tmp_ctx);
360 0 : return ldb_oom(ldb_module_get_ctx(module));
361 : }
362 :
363 14263475 : ret = ldb_build_extended_req(&req, ldb,
364 : tmp_ctx,
365 : oid,
366 : data,
367 : NULL,
368 : res, ldb_extended_default_callback,
369 : parent);
370 :
371 14263475 : LDB_REQ_SET_LOCATION(req);
372 14263475 : if (ret != LDB_SUCCESS) {
373 0 : talloc_free(tmp_ctx);
374 0 : return ret;
375 : }
376 :
377 14263475 : ret = dsdb_request_add_controls(req, dsdb_flags);
378 14263475 : if (ret != LDB_SUCCESS) {
379 0 : talloc_free(tmp_ctx);
380 0 : return ret;
381 : }
382 :
383 14263475 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
384 330431 : ldb_req_mark_trusted(req);
385 : }
386 :
387 : /* Run the new request */
388 14263475 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
389 13933044 : ret = ldb_next_request(module, req);
390 330431 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
391 330431 : ret = ldb_request(ldb_module_get_ctx(module), req);
392 : } else {
393 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
394 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
395 0 : ret = ops->extended(module, req);
396 : }
397 14263475 : if (ret == LDB_SUCCESS) {
398 14263475 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
399 : }
400 :
401 14263475 : if (_res != NULL && ret == LDB_SUCCESS) {
402 13933044 : (*_res) = talloc_steal(mem_ctx, res);
403 : }
404 :
405 14263475 : talloc_free(tmp_ctx);
406 14263475 : return ret;
407 : }
408 :
409 :
410 : /*
411 : a ldb_modify request operating on modules below the
412 : current module
413 : */
414 275724 : int dsdb_module_modify(struct ldb_module *module,
415 : const struct ldb_message *message,
416 : uint32_t dsdb_flags,
417 : struct ldb_request *parent)
418 : {
419 : struct ldb_request *mod_req;
420 : int ret;
421 275724 : struct ldb_context *ldb = ldb_module_get_ctx(module);
422 275724 : TALLOC_CTX *tmp_ctx = talloc_new(module);
423 : struct ldb_result *res;
424 :
425 275724 : res = talloc_zero(tmp_ctx, struct ldb_result);
426 275724 : if (!res) {
427 0 : talloc_free(tmp_ctx);
428 0 : return ldb_oom(ldb_module_get_ctx(module));
429 : }
430 :
431 275724 : ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
432 : message,
433 : NULL,
434 : res,
435 : ldb_modify_default_callback,
436 : parent);
437 275724 : LDB_REQ_SET_LOCATION(mod_req);
438 275724 : if (ret != LDB_SUCCESS) {
439 0 : talloc_free(tmp_ctx);
440 0 : return ret;
441 : }
442 :
443 275724 : ret = dsdb_request_add_controls(mod_req, dsdb_flags);
444 275724 : if (ret != LDB_SUCCESS) {
445 0 : talloc_free(tmp_ctx);
446 0 : return ret;
447 : }
448 :
449 275724 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
450 0 : ldb_req_mark_trusted(mod_req);
451 : }
452 :
453 : /* Run the new request */
454 275724 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
455 100874 : ret = ldb_next_request(module, mod_req);
456 174850 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
457 2 : ret = ldb_request(ldb_module_get_ctx(module), mod_req);
458 : } else {
459 174848 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
460 174848 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
461 174848 : ret = ops->modify(module, mod_req);
462 : }
463 275724 : if (ret == LDB_SUCCESS) {
464 275724 : ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
465 : }
466 :
467 275724 : talloc_free(tmp_ctx);
468 275724 : return ret;
469 : }
470 :
471 :
472 :
473 : /*
474 : a ldb_rename request operating on modules below the
475 : current module
476 : */
477 121252 : int dsdb_module_rename(struct ldb_module *module,
478 : struct ldb_dn *olddn, struct ldb_dn *newdn,
479 : uint32_t dsdb_flags,
480 : struct ldb_request *parent)
481 : {
482 : struct ldb_request *req;
483 : int ret;
484 121252 : struct ldb_context *ldb = ldb_module_get_ctx(module);
485 121252 : TALLOC_CTX *tmp_ctx = talloc_new(module);
486 : struct ldb_result *res;
487 :
488 121252 : res = talloc_zero(tmp_ctx, struct ldb_result);
489 121252 : if (!res) {
490 0 : talloc_free(tmp_ctx);
491 0 : return ldb_oom(ldb_module_get_ctx(module));
492 : }
493 :
494 121252 : ret = ldb_build_rename_req(&req, ldb, tmp_ctx,
495 : olddn,
496 : newdn,
497 : NULL,
498 : res,
499 : ldb_modify_default_callback,
500 : parent);
501 121252 : LDB_REQ_SET_LOCATION(req);
502 121252 : if (ret != LDB_SUCCESS) {
503 0 : talloc_free(tmp_ctx);
504 0 : return ret;
505 : }
506 :
507 121252 : ret = dsdb_request_add_controls(req, dsdb_flags);
508 121252 : if (ret != LDB_SUCCESS) {
509 0 : talloc_free(tmp_ctx);
510 0 : return ret;
511 : }
512 :
513 121252 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
514 0 : ldb_req_mark_trusted(req);
515 : }
516 :
517 : /* Run the new request */
518 121252 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
519 120767 : ret = ldb_next_request(module, req);
520 485 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
521 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
522 : } else {
523 485 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
524 485 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
525 485 : ret = ops->rename(module, req);
526 : }
527 121252 : if (ret == LDB_SUCCESS) {
528 121250 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
529 : }
530 :
531 121252 : talloc_free(tmp_ctx);
532 121252 : return ret;
533 : }
534 :
535 : /*
536 : a ldb_add request operating on modules below the
537 : current module
538 : */
539 1296 : int dsdb_module_add(struct ldb_module *module,
540 : const struct ldb_message *message,
541 : uint32_t dsdb_flags,
542 : struct ldb_request *parent)
543 : {
544 : struct ldb_request *req;
545 : int ret;
546 1296 : struct ldb_context *ldb = ldb_module_get_ctx(module);
547 1296 : TALLOC_CTX *tmp_ctx = talloc_new(module);
548 : struct ldb_result *res;
549 :
550 1296 : res = talloc_zero(tmp_ctx, struct ldb_result);
551 1296 : if (!res) {
552 0 : talloc_free(tmp_ctx);
553 0 : return ldb_oom(ldb_module_get_ctx(module));
554 : }
555 :
556 1296 : ret = ldb_build_add_req(&req, ldb, tmp_ctx,
557 : message,
558 : NULL,
559 : res,
560 : ldb_modify_default_callback,
561 : parent);
562 1296 : LDB_REQ_SET_LOCATION(req);
563 1296 : if (ret != LDB_SUCCESS) {
564 0 : talloc_free(tmp_ctx);
565 0 : return ret;
566 : }
567 :
568 1296 : ret = dsdb_request_add_controls(req, dsdb_flags);
569 1296 : if (ret != LDB_SUCCESS) {
570 0 : talloc_free(tmp_ctx);
571 0 : return ret;
572 : }
573 :
574 1296 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
575 0 : ldb_req_mark_trusted(req);
576 : }
577 :
578 : /* Run the new request */
579 1296 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
580 1226 : ret = ldb_next_request(module, req);
581 70 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
582 70 : ret = ldb_request(ldb_module_get_ctx(module), req);
583 : } else {
584 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
585 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
586 0 : ret = ops->add(module, req);
587 : }
588 1296 : if (ret == LDB_SUCCESS) {
589 1296 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
590 : }
591 :
592 1296 : talloc_free(tmp_ctx);
593 1296 : return ret;
594 : }
595 :
596 : /*
597 : a ldb_delete request operating on modules below the
598 : current module
599 : */
600 25025 : int dsdb_module_del(struct ldb_module *module,
601 : struct ldb_dn *dn,
602 : uint32_t dsdb_flags,
603 : struct ldb_request *parent)
604 : {
605 : struct ldb_request *req;
606 : int ret;
607 25025 : struct ldb_context *ldb = ldb_module_get_ctx(module);
608 25025 : TALLOC_CTX *tmp_ctx = talloc_new(module);
609 : struct ldb_result *res;
610 :
611 25025 : res = talloc_zero(tmp_ctx, struct ldb_result);
612 25025 : if (!res) {
613 0 : talloc_free(tmp_ctx);
614 0 : return ldb_oom(ldb);
615 : }
616 :
617 25025 : ret = ldb_build_del_req(&req, ldb, tmp_ctx,
618 : dn,
619 : NULL,
620 : res,
621 : ldb_modify_default_callback,
622 : parent);
623 25025 : LDB_REQ_SET_LOCATION(req);
624 25025 : if (ret != LDB_SUCCESS) {
625 0 : talloc_free(tmp_ctx);
626 0 : return ret;
627 : }
628 :
629 25025 : ret = dsdb_request_add_controls(req, dsdb_flags);
630 25025 : if (ret != LDB_SUCCESS) {
631 0 : talloc_free(tmp_ctx);
632 0 : return ret;
633 : }
634 :
635 25025 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
636 25025 : ldb_req_mark_trusted(req);
637 : }
638 :
639 : /* Run the new request */
640 25025 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
641 0 : ret = ldb_next_request(module, req);
642 25025 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
643 25025 : ret = ldb_request(ldb_module_get_ctx(module), req);
644 : } else {
645 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
646 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
647 0 : ret = ops->del(module, req);
648 : }
649 25025 : if (ret == LDB_SUCCESS) {
650 25025 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
651 : }
652 :
653 25025 : talloc_free(tmp_ctx);
654 25025 : return ret;
655 : }
656 :
657 : /*
658 : check if a single valued link has multiple non-deleted values
659 :
660 : This is needed when we will be using the RELAX control to stop
661 : ldb_tdb from checking single valued links
662 : */
663 37896 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
664 : const struct ldb_message_element *el)
665 : {
666 37896 : bool found_active = false;
667 : unsigned int i;
668 :
669 44741 : if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
670 7079 : el->num_values < 2) {
671 37090 : return LDB_SUCCESS;
672 : }
673 :
674 387 : for (i=0; i<el->num_values; i++) {
675 260 : if (!dsdb_dn_is_deleted_val(&el->values[i])) {
676 123 : if (found_active) {
677 3 : return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
678 : }
679 120 : found_active = true;
680 : }
681 : }
682 :
683 127 : return LDB_SUCCESS;
684 : }
685 :
686 :
687 264906 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
688 : const char *feature,
689 : bool *found)
690 : {
691 264906 : struct ldb_context *ldb = ldb_module_get_ctx(module);
692 : struct ldb_result *res;
693 : static const char *samba_dsdb_attrs[] = {
694 : SAMBA_COMPATIBLE_FEATURES_ATTR,
695 : NULL
696 : };
697 : int ret;
698 264906 : struct ldb_dn *samba_dsdb_dn = NULL;
699 264906 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
700 264906 : if (tmp_ctx == NULL) {
701 0 : *found = false;
702 0 : return ldb_oom(ldb);
703 : }
704 264906 : *found = false;
705 :
706 264906 : samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
707 264906 : if (samba_dsdb_dn == NULL) {
708 0 : TALLOC_FREE(tmp_ctx);
709 0 : return ldb_oom(ldb);
710 : }
711 :
712 264906 : ret = dsdb_module_search_dn(module,
713 : tmp_ctx,
714 : &res,
715 : samba_dsdb_dn,
716 : samba_dsdb_attrs,
717 : DSDB_FLAG_NEXT_MODULE,
718 : NULL);
719 264906 : if (ret == LDB_SUCCESS) {
720 264906 : *found = ldb_msg_check_string_attribute(
721 264906 : res->msgs[0],
722 : SAMBA_COMPATIBLE_FEATURES_ATTR,
723 : feature);
724 0 : } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
725 : /* it is not an error not to find it */
726 0 : ret = LDB_SUCCESS;
727 : }
728 264906 : TALLOC_FREE(tmp_ctx);
729 264906 : return ret;
730 : }
731 :
732 :
733 : /*
734 : check if an optional feature is enabled on our own NTDS DN
735 :
736 : Note that features can be marked as enabled in more than one
737 : place. For example, the recyclebin feature is marked as enabled both
738 : on the CN=Partitions,CN=Configurration object and on the NTDS DN of
739 : each DC in the forest. It seems likely that it is the job of the KCC
740 : to propagate between the two
741 : */
742 83326 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
743 : {
744 : TALLOC_CTX *tmp_ctx;
745 83326 : struct ldb_context *ldb = ldb_module_get_ctx(module);
746 : struct ldb_result *res;
747 : struct ldb_dn *search_dn;
748 : struct GUID search_guid;
749 83326 : const char *attrs[] = {"msDS-EnabledFeature", NULL};
750 : int ret;
751 : unsigned int i;
752 : struct ldb_message_element *el;
753 : struct ldb_dn *feature_dn;
754 :
755 83326 : tmp_ctx = talloc_new(ldb);
756 :
757 83326 : feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
758 83326 : if (feature_dn == NULL) {
759 1 : talloc_free(tmp_ctx);
760 1 : return ldb_operr(ldb_module_get_ctx(module));
761 : }
762 :
763 83325 : *feature_enabled = false;
764 :
765 83325 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
766 83325 : if (ret != LDB_SUCCESS) {
767 1389 : ldb_asprintf_errstring(ldb,
768 : "Could not find the feature object - dn: %s\n",
769 : ldb_dn_get_linearized(feature_dn));
770 1389 : talloc_free(tmp_ctx);
771 1389 : return LDB_ERR_NO_SUCH_OBJECT;
772 : }
773 81936 : if (res->msgs[0]->num_elements > 0) {
774 0 : const char *attrs2[] = {"msDS-OptionalFeatureGUID", NULL};
775 :
776 0 : el = ldb_msg_find_element(res->msgs[0],"msDS-EnabledFeature");
777 :
778 0 : for (i=0; i<el->num_values; i++) {
779 0 : search_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &el->values[i]);
780 :
781 0 : ret = dsdb_module_search_dn(module, tmp_ctx, &res,
782 : search_dn, attrs2, DSDB_FLAG_NEXT_MODULE, NULL);
783 0 : if (ret != LDB_SUCCESS) {
784 0 : ldb_asprintf_errstring(ldb,
785 : "Could no find object dn: %s\n",
786 : ldb_dn_get_linearized(search_dn));
787 0 : talloc_free(tmp_ctx);
788 0 : return LDB_ERR_OPERATIONS_ERROR;
789 : }
790 :
791 0 : search_guid = samdb_result_guid(res->msgs[0], "msDS-OptionalFeatureGUID");
792 :
793 0 : if (GUID_equal(&search_guid, &op_feature_guid)) {
794 0 : *feature_enabled = true;
795 0 : break;
796 : }
797 : }
798 : }
799 81936 : talloc_free(tmp_ctx);
800 81936 : return LDB_SUCCESS;
801 : }
802 :
803 : /*
804 : find the NTDS GUID from a computers DN record
805 : */
806 397 : int dsdb_module_find_ntdsguid_for_computer(struct ldb_module *module,
807 : TALLOC_CTX *mem_ctx,
808 : struct ldb_dn *computer_dn,
809 : struct GUID *ntds_guid,
810 : struct ldb_request *parent)
811 : {
812 : int ret;
813 : struct ldb_dn *dn;
814 :
815 397 : *ntds_guid = GUID_zero();
816 :
817 397 : ret = dsdb_module_reference_dn(module, mem_ctx, computer_dn,
818 : "serverReferenceBL", &dn, parent);
819 397 : if (ret != LDB_SUCCESS) {
820 0 : return ret;
821 : }
822 :
823 397 : if (!ldb_dn_add_child_fmt(dn, "CN=NTDS Settings")) {
824 0 : talloc_free(dn);
825 0 : return LDB_ERR_OPERATIONS_ERROR;
826 : }
827 :
828 397 : ret = dsdb_module_guid_by_dn(module, dn, ntds_guid, parent);
829 397 : talloc_free(dn);
830 397 : return ret;
831 : }
832 :
833 : /*
834 : find a 'reference' DN that points at another object
835 : (eg. serverReference, rIDManagerReference etc)
836 : */
837 1405 : int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
838 : const char *attribute, struct ldb_dn **dn, struct ldb_request *parent)
839 : {
840 : const char *attrs[2];
841 : struct ldb_result *res;
842 : int ret;
843 :
844 1405 : attrs[0] = attribute;
845 1405 : attrs[1] = NULL;
846 :
847 1405 : ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
848 : DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
849 1405 : if (ret != LDB_SUCCESS) {
850 0 : return ret;
851 : }
852 :
853 1405 : *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
854 1405 : mem_ctx, res->msgs[0], attribute);
855 1405 : if (!*dn) {
856 30 : ldb_reset_err_string(ldb_module_get_ctx(module));
857 30 : talloc_free(res);
858 30 : return LDB_ERR_NO_SUCH_ATTRIBUTE;
859 : }
860 :
861 1375 : talloc_free(res);
862 1375 : return LDB_SUCCESS;
863 : }
864 :
865 : /*
866 : find the RID Manager$ DN via the rIDManagerReference attribute in the
867 : base DN
868 : */
869 446 : int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn,
870 : struct ldb_request *parent)
871 : {
872 446 : return dsdb_module_reference_dn(module, mem_ctx,
873 : ldb_get_default_basedn(ldb_module_get_ctx(module)),
874 : "rIDManagerReference", dn, parent);
875 : }
876 :
877 : /*
878 : used to chain to the callers callback
879 : */
880 107140610 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
881 : {
882 107140610 : struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
883 :
884 107140610 : if (!ares) {
885 0 : return ldb_module_done(up_req, NULL, NULL,
886 : LDB_ERR_OPERATIONS_ERROR);
887 : }
888 :
889 107140610 : if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
890 34646817 : return ldb_module_done(up_req, ares->controls,
891 : ares->response, ares->error);
892 : }
893 :
894 : /* Otherwise pass on the callback */
895 72493793 : switch (ares->type) {
896 70068171 : case LDB_REPLY_ENTRY:
897 70068171 : return ldb_module_send_entry(up_req, ares->message,
898 : ares->controls);
899 :
900 2425622 : case LDB_REPLY_REFERRAL:
901 2425622 : return ldb_module_send_referral(up_req,
902 : ares->referral);
903 0 : default:
904 : /* Can't happen */
905 0 : return LDB_ERR_OPERATIONS_ERROR;
906 : }
907 : }
908 :
909 : /*
910 : load the uSNHighest and the uSNUrgent attributes from the @REPLCHANGED
911 : object for a partition
912 : */
913 0 : int dsdb_module_load_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
914 : uint64_t *uSN, uint64_t *urgent_uSN, struct ldb_request *parent)
915 : {
916 0 : struct ldb_context *ldb = ldb_module_get_ctx(module);
917 : struct ldb_request *req;
918 : int ret;
919 0 : TALLOC_CTX *tmp_ctx = talloc_new(module);
920 : struct dsdb_control_current_partition *p_ctrl;
921 : struct ldb_result *res;
922 :
923 0 : res = talloc_zero(tmp_ctx, struct ldb_result);
924 0 : if (!res) {
925 0 : talloc_free(tmp_ctx);
926 0 : return ldb_module_oom(module);
927 : }
928 :
929 0 : ret = ldb_build_search_req(&req, ldb, tmp_ctx,
930 : ldb_dn_new(tmp_ctx, ldb, "@REPLCHANGED"),
931 : LDB_SCOPE_BASE,
932 : NULL, NULL,
933 : NULL,
934 : res, ldb_search_default_callback,
935 : parent);
936 0 : LDB_REQ_SET_LOCATION(req);
937 0 : if (ret != LDB_SUCCESS) {
938 0 : talloc_free(tmp_ctx);
939 0 : return ret;
940 : }
941 :
942 0 : p_ctrl = talloc(req, struct dsdb_control_current_partition);
943 0 : if (p_ctrl == NULL) {
944 0 : talloc_free(tmp_ctx);
945 0 : return ldb_module_oom(module);
946 : }
947 0 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
948 0 : p_ctrl->dn = dn;
949 :
950 :
951 0 : ret = ldb_request_add_control(req,
952 : DSDB_CONTROL_CURRENT_PARTITION_OID,
953 : false, p_ctrl);
954 0 : if (ret != LDB_SUCCESS) {
955 0 : talloc_free(tmp_ctx);
956 0 : return ret;
957 : }
958 :
959 : /* Run the new request */
960 0 : ret = ldb_next_request(module, req);
961 :
962 0 : if (ret == LDB_SUCCESS) {
963 0 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
964 : }
965 :
966 0 : if (ret == LDB_ERR_NO_SUCH_OBJECT || ret == LDB_ERR_INVALID_DN_SYNTAX) {
967 : /* it hasn't been created yet, which means
968 : an implicit value of zero */
969 0 : *uSN = 0;
970 0 : talloc_free(tmp_ctx);
971 0 : ldb_reset_err_string(ldb);
972 0 : return LDB_SUCCESS;
973 : }
974 :
975 0 : if (ret != LDB_SUCCESS) {
976 0 : talloc_free(tmp_ctx);
977 0 : return ret;
978 : }
979 :
980 0 : if (res->count != 1) {
981 0 : *uSN = 0;
982 0 : if (urgent_uSN) {
983 0 : *urgent_uSN = 0;
984 : }
985 : } else {
986 0 : *uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNHighest", 0);
987 0 : if (urgent_uSN) {
988 0 : *urgent_uSN = ldb_msg_find_attr_as_uint64(res->msgs[0], "uSNUrgent", 0);
989 : }
990 : }
991 :
992 0 : talloc_free(tmp_ctx);
993 :
994 0 : return LDB_SUCCESS;
995 : }
996 :
997 : /*
998 : save uSNHighest and uSNUrgent attributes in the @REPLCHANGED object for a
999 : partition
1000 : */
1001 159376 : int dsdb_module_save_partition_usn(struct ldb_module *module, struct ldb_dn *dn,
1002 : uint64_t uSN, uint64_t urgent_uSN,
1003 : struct ldb_request *parent)
1004 : {
1005 159376 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1006 : struct ldb_request *req;
1007 : struct ldb_message *msg;
1008 : struct dsdb_control_current_partition *p_ctrl;
1009 : int ret;
1010 : struct ldb_result *res;
1011 :
1012 159376 : msg = ldb_msg_new(module);
1013 159376 : if (msg == NULL) {
1014 0 : return ldb_module_oom(module);
1015 : }
1016 :
1017 159376 : msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1018 159376 : if (msg->dn == NULL) {
1019 0 : talloc_free(msg);
1020 0 : return ldb_operr(ldb_module_get_ctx(module));
1021 : }
1022 :
1023 159376 : res = talloc_zero(msg, struct ldb_result);
1024 159376 : if (!res) {
1025 0 : talloc_free(msg);
1026 0 : return ldb_module_oom(module);
1027 : }
1028 :
1029 159376 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1030 159376 : if (ret != LDB_SUCCESS) {
1031 0 : talloc_free(msg);
1032 0 : return ret;
1033 : }
1034 159376 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1035 :
1036 : /* urgent_uSN is optional so may not be stored */
1037 159376 : if (urgent_uSN) {
1038 23478 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1039 : urgent_uSN);
1040 23478 : if (ret != LDB_SUCCESS) {
1041 0 : talloc_free(msg);
1042 0 : return ret;
1043 : }
1044 23478 : msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1045 : }
1046 :
1047 :
1048 159376 : p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1049 159376 : if (p_ctrl == NULL) {
1050 0 : talloc_free(msg);
1051 0 : return ldb_oom(ldb);
1052 : }
1053 159376 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1054 159376 : p_ctrl->dn = dn;
1055 159376 : ret = ldb_build_mod_req(&req, ldb, msg,
1056 : msg,
1057 : NULL,
1058 : res,
1059 : ldb_modify_default_callback,
1060 : parent);
1061 159376 : LDB_REQ_SET_LOCATION(req);
1062 160295 : again:
1063 160295 : if (ret != LDB_SUCCESS) {
1064 0 : talloc_free(msg);
1065 0 : return ret;
1066 : }
1067 :
1068 160295 : ret = ldb_request_add_control(req,
1069 : DSDB_CONTROL_CURRENT_PARTITION_OID,
1070 : false, p_ctrl);
1071 160295 : if (ret != LDB_SUCCESS) {
1072 0 : talloc_free(msg);
1073 0 : return ret;
1074 : }
1075 :
1076 : /* Run the new request */
1077 160295 : ret = ldb_next_request(module, req);
1078 :
1079 160295 : if (ret == LDB_SUCCESS) {
1080 160295 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1081 : }
1082 160295 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1083 919 : ret = ldb_build_add_req(&req, ldb, msg,
1084 : msg,
1085 : NULL,
1086 : res,
1087 : ldb_modify_default_callback,
1088 : parent);
1089 919 : LDB_REQ_SET_LOCATION(req);
1090 919 : goto again;
1091 : }
1092 :
1093 159376 : talloc_free(msg);
1094 :
1095 159376 : return ret;
1096 : }
1097 :
1098 40005729 : bool dsdb_module_am_system(struct ldb_module *module)
1099 : {
1100 40005729 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1101 34013540 : struct auth_session_info *session_info
1102 40005729 : = talloc_get_type(
1103 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1104 : struct auth_session_info);
1105 40005729 : return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1106 : }
1107 :
1108 16628807 : bool dsdb_module_am_administrator(struct ldb_module *module)
1109 : {
1110 16628807 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1111 14250237 : struct auth_session_info *session_info
1112 16628807 : = talloc_get_type(
1113 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1114 : struct auth_session_info);
1115 16628807 : return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1116 : }
1117 :
1118 : /*
1119 : check if the recyclebin is enabled
1120 : */
1121 83326 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1122 : {
1123 83326 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1124 : struct GUID recyclebin_guid;
1125 : int ret;
1126 :
1127 83326 : GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1128 :
1129 83326 : ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1130 83326 : if (ret != LDB_SUCCESS) {
1131 1390 : ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1132 1390 : return ret;
1133 : }
1134 :
1135 80303 : return LDB_SUCCESS;
1136 : }
1137 :
1138 47681 : int dsdb_msg_constrainted_update_int32(struct ldb_module *module,
1139 : struct ldb_message *msg,
1140 : const char *attr,
1141 : const int32_t *old_val,
1142 : const int32_t *new_val)
1143 : {
1144 : struct ldb_message_element *el;
1145 : int ret;
1146 : char *vstring;
1147 :
1148 47681 : if (old_val) {
1149 23800 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1150 23800 : if (ret != LDB_SUCCESS) {
1151 0 : return ret;
1152 : }
1153 23800 : el->num_values = 1;
1154 23800 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1155 23800 : if (!el->values) {
1156 0 : return ldb_module_oom(module);
1157 : }
1158 23800 : vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1159 23800 : if (!vstring) {
1160 0 : return ldb_module_oom(module);
1161 : }
1162 23800 : *el->values = data_blob_string_const(vstring);
1163 : }
1164 :
1165 47681 : if (new_val) {
1166 23945 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1167 23945 : if (ret != LDB_SUCCESS) {
1168 0 : return ret;
1169 : }
1170 23945 : el->num_values = 1;
1171 23945 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1172 23945 : if (!el->values) {
1173 0 : return ldb_module_oom(module);
1174 : }
1175 23945 : vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1176 23945 : if (!vstring) {
1177 0 : return ldb_module_oom(module);
1178 : }
1179 23945 : *el->values = data_blob_string_const(vstring);
1180 : }
1181 :
1182 47340 : return LDB_SUCCESS;
1183 : }
1184 :
1185 47680 : int dsdb_msg_constrainted_update_uint32(struct ldb_module *module,
1186 : struct ldb_message *msg,
1187 : const char *attr,
1188 : const uint32_t *old_val,
1189 : const uint32_t *new_val)
1190 : {
1191 47680 : return dsdb_msg_constrainted_update_int32(module, msg, attr,
1192 : (const int32_t *)old_val,
1193 : (const int32_t *)new_val);
1194 : }
1195 :
1196 47799 : int dsdb_msg_constrainted_update_int64(struct ldb_module *module,
1197 : struct ldb_message *msg,
1198 : const char *attr,
1199 : const int64_t *old_val,
1200 : const int64_t *new_val)
1201 : {
1202 : struct ldb_message_element *el;
1203 : int ret;
1204 : char *vstring;
1205 :
1206 47799 : if (old_val) {
1207 209 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1208 209 : if (ret != LDB_SUCCESS) {
1209 0 : return ret;
1210 : }
1211 209 : el->num_values = 1;
1212 209 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1213 209 : if (!el->values) {
1214 0 : return ldb_module_oom(module);
1215 : }
1216 209 : vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1217 209 : if (!vstring) {
1218 0 : return ldb_module_oom(module);
1219 : }
1220 209 : *el->values = data_blob_string_const(vstring);
1221 : }
1222 :
1223 47799 : if (new_val) {
1224 353 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1225 353 : if (ret != LDB_SUCCESS) {
1226 0 : return ret;
1227 : }
1228 353 : el->num_values = 1;
1229 353 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1230 353 : if (!el->values) {
1231 0 : return ldb_module_oom(module);
1232 : }
1233 353 : vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1234 353 : if (!vstring) {
1235 0 : return ldb_module_oom(module);
1236 : }
1237 353 : *el->values = data_blob_string_const(vstring);
1238 : }
1239 :
1240 47459 : return LDB_SUCCESS;
1241 : }
1242 :
1243 47680 : int dsdb_msg_constrainted_update_uint64(struct ldb_module *module,
1244 : struct ldb_message *msg,
1245 : const char *attr,
1246 : const uint64_t *old_val,
1247 : const uint64_t *new_val)
1248 : {
1249 47680 : return dsdb_msg_constrainted_update_int64(module, msg, attr,
1250 : (const int64_t *)old_val,
1251 : (const int64_t *)new_val);
1252 : }
1253 :
1254 : /*
1255 : update an int32 attribute safely via a constrained delete/add
1256 : */
1257 1 : int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1258 : struct ldb_dn *dn,
1259 : const char *attr,
1260 : const int32_t *old_val,
1261 : const int32_t *new_val,
1262 : struct ldb_request *parent)
1263 : {
1264 : struct ldb_message *msg;
1265 : int ret;
1266 :
1267 1 : msg = ldb_msg_new(module);
1268 1 : if (msg == NULL) {
1269 0 : return ldb_module_oom(module);
1270 : }
1271 1 : msg->dn = dn;
1272 :
1273 1 : ret = dsdb_msg_constrainted_update_int32(module,
1274 : msg, attr,
1275 : old_val,
1276 : new_val);
1277 1 : if (ret != LDB_SUCCESS) {
1278 0 : talloc_free(msg);
1279 0 : return ret;
1280 : }
1281 :
1282 1 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1283 1 : talloc_free(msg);
1284 1 : return ret;
1285 : }
1286 :
1287 1 : int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1288 : struct ldb_dn *dn,
1289 : const char *attr,
1290 : const uint32_t *old_val,
1291 : const uint32_t *new_val,
1292 : struct ldb_request *parent)
1293 : {
1294 1 : return dsdb_module_constrainted_update_int32(module, dn, attr,
1295 : (const int32_t *)old_val,
1296 : (const int32_t *)new_val, parent);
1297 : }
1298 :
1299 : /*
1300 : update an int64 attribute safely via a constrained delete/add
1301 : */
1302 119 : int dsdb_module_constrainted_update_int64(struct ldb_module *module,
1303 : struct ldb_dn *dn,
1304 : const char *attr,
1305 : const int64_t *old_val,
1306 : const int64_t *new_val,
1307 : struct ldb_request *parent)
1308 : {
1309 : struct ldb_message *msg;
1310 : int ret;
1311 :
1312 119 : msg = ldb_msg_new(module);
1313 119 : if (msg == NULL) {
1314 0 : return ldb_module_oom(module);
1315 : }
1316 119 : msg->dn = dn;
1317 :
1318 119 : ret = dsdb_msg_constrainted_update_int64(module,
1319 : msg, attr,
1320 : old_val,
1321 : new_val);
1322 119 : if (ret != LDB_SUCCESS) {
1323 0 : talloc_free(msg);
1324 0 : return ret;
1325 : }
1326 :
1327 119 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1328 119 : talloc_free(msg);
1329 119 : return ret;
1330 : }
1331 :
1332 119 : int dsdb_module_constrainted_update_uint64(struct ldb_module *module,
1333 : struct ldb_dn *dn,
1334 : const char *attr,
1335 : const uint64_t *old_val,
1336 : const uint64_t *new_val,
1337 : struct ldb_request *parent)
1338 : {
1339 119 : return dsdb_module_constrainted_update_int64(module, dn, attr,
1340 : (const int64_t *)old_val,
1341 : (const int64_t *)new_val,
1342 : parent);
1343 : }
1344 :
1345 :
1346 1317249 : const struct ldb_val *dsdb_module_find_dsheuristics(struct ldb_module *module,
1347 : TALLOC_CTX *mem_ctx, struct ldb_request *parent)
1348 : {
1349 : int ret;
1350 : struct ldb_dn *new_dn;
1351 1317249 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1352 : static const char *attrs[] = { "dSHeuristics", NULL };
1353 : struct ldb_result *res;
1354 :
1355 1317249 : new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1356 1317249 : if (!ldb_dn_add_child_fmt(new_dn,
1357 : "CN=Directory Service,CN=Windows NT,CN=Services")) {
1358 0 : talloc_free(new_dn);
1359 0 : return NULL;
1360 : }
1361 1317249 : ret = dsdb_module_search_dn(module, mem_ctx, &res,
1362 : new_dn,
1363 : attrs,
1364 : DSDB_FLAG_NEXT_MODULE,
1365 : parent);
1366 1317249 : if (ret == LDB_SUCCESS && res->count == 1) {
1367 1067922 : talloc_free(new_dn);
1368 1067922 : return ldb_msg_find_ldb_val(res->msgs[0],
1369 : "dSHeuristics");
1370 : }
1371 249327 : talloc_free(new_dn);
1372 249327 : return NULL;
1373 : }
1374 :
1375 132901 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1376 : {
1377 132901 : TALLOC_CTX *tmp_ctx = talloc_new(module);
1378 : bool result;
1379 132901 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1380 : tmp_ctx, parent);
1381 132901 : if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1382 122093 : result = true;
1383 6035 : } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1384 18 : result = false;
1385 : } else {
1386 6017 : result = true;
1387 : }
1388 :
1389 132901 : talloc_free(tmp_ctx);
1390 132901 : return result;
1391 : }
1392 :
1393 1168040 : bool dsdb_user_password_support(struct ldb_module *module,
1394 : TALLOC_CTX *mem_ctx,
1395 : struct ldb_request *parent)
1396 : {
1397 1168040 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1398 : bool result;
1399 1168040 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1400 : tmp_ctx,
1401 : parent);
1402 1168040 : if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1403 1038461 : result = false;
1404 35696 : } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1405 20442 : (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1406 184 : result = false;
1407 : } else {
1408 20286 : result = true;
1409 : }
1410 :
1411 1168040 : talloc_free(tmp_ctx);
1412 1168040 : return result;
1413 : }
1414 :
1415 16308 : bool dsdb_do_list_object(struct ldb_module *module,
1416 : TALLOC_CTX *mem_ctx,
1417 : struct ldb_request *parent)
1418 : {
1419 16308 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1420 : bool result;
1421 16308 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1422 : tmp_ctx,
1423 : parent);
1424 16308 : if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1425 0 : result = false;
1426 16308 : } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1427 8064 : result = true;
1428 : } else {
1429 8244 : result = false;
1430 : }
1431 :
1432 16308 : talloc_free(tmp_ctx);
1433 16308 : return result;
1434 : }
1435 :
1436 : /*
1437 : show the chain of requests, useful for debugging async requests
1438 : */
1439 0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
1440 : {
1441 0 : char *s = ldb_module_call_chain(req, req);
1442 0 : DEBUG(level, ("%s\n", s));
1443 0 : talloc_free(s);
1444 0 : }
1445 :
1446 : /*
1447 : * Gets back a single-valued attribute by the rules of the DSDB triggers when
1448 : * performing a modify operation.
1449 : *
1450 : * In order that the constraint checking by the "objectclass_attrs" LDB module
1451 : * does work properly, the change request should remain similar or only be
1452 : * enhanced (no other modifications as deletions, variations).
1453 : */
1454 263958 : struct ldb_message_element *dsdb_get_single_valued_attr(const struct ldb_message *msg,
1455 : const char *attr_name,
1456 : enum ldb_request_type operation)
1457 : {
1458 263958 : struct ldb_message_element *el = NULL;
1459 : unsigned int i;
1460 :
1461 : /* We've to walk over all modification entries and consider the last
1462 : * non-delete one which belongs to "attr_name".
1463 : *
1464 : * If "el" is NULL afterwards then that means there was no interesting
1465 : * change entry. */
1466 4678668 : for (i = 0; i < msg->num_elements; i++) {
1467 4414710 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1468 306764 : if ((operation == LDB_MODIFY) &&
1469 44062 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1470 : == LDB_FLAG_MOD_DELETE)) {
1471 18714 : continue;
1472 : }
1473 222374 : el = &msg->elements[i];
1474 : }
1475 : }
1476 :
1477 263958 : return el;
1478 : }
1479 :
1480 : /*
1481 : * This function determines the (last) structural or 88 object class of a passed
1482 : * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1483 : * Without schema this does not work and hence NULL is returned.
1484 : */
1485 3705055 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1486 : const struct ldb_message_element *element)
1487 : {
1488 : const struct dsdb_class *last_class;
1489 :
1490 3705055 : if (schema == NULL) {
1491 0 : return NULL;
1492 : }
1493 :
1494 3705055 : if (element->num_values == 0) {
1495 0 : return NULL;
1496 : }
1497 :
1498 3705055 : last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1499 3705055 : &element->values[element->num_values-1]);
1500 3705055 : if (last_class == NULL) {
1501 0 : return NULL;
1502 : }
1503 3705055 : if (last_class->objectClassCategory > 1) {
1504 3 : return NULL;
1505 : }
1506 :
1507 3705052 : return last_class;
1508 : }
1509 :
1510 1947444 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1511 : const struct ldb_message *msg)
1512 : {
1513 : struct ldb_message_element *oc_el;
1514 :
1515 1947444 : oc_el = ldb_msg_find_element(msg, "objectClass");
1516 1947444 : if (!oc_el) {
1517 0 : return NULL;
1518 : }
1519 :
1520 1947444 : return dsdb_get_last_structural_class(schema, oc_el);
1521 : }
1522 :
1523 : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1524 : cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1525 : CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1526 : */
1527 0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1528 : {
1529 : int i, ret;
1530 : char *upper_rdn_attr;
1531 :
1532 0 : for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1533 : /* We need the attribute name in upper case */
1534 0 : upper_rdn_attr = strupper_talloc(dn,
1535 : ldb_dn_get_component_name(dn, i));
1536 0 : if (!upper_rdn_attr) {
1537 0 : return ldb_oom(ldb);
1538 : }
1539 0 : ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1540 0 : *ldb_dn_get_component_val(dn, i));
1541 0 : talloc_free(upper_rdn_attr);
1542 0 : if (ret != LDB_SUCCESS) {
1543 0 : return ret;
1544 : }
1545 : }
1546 0 : return LDB_SUCCESS;
1547 : }
1548 :
1549 : /**
1550 : * Make most specific objectCategory for the objectClass of passed object
1551 : * NOTE: In this implementation we count that it is called on already
1552 : * verified objectClass attribute value. See objectclass.c thorough
1553 : * implementation for all the magic that involves
1554 : *
1555 : * @param ldb ldb context
1556 : * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1557 : * Hence leave the responsibility to the caller.
1558 : * @param obj AD object to determint objectCategory for
1559 : * @param mem_ctx Memory context - usually it is obj actually
1560 : * @param pobjectcategory location to store found objectCategory
1561 : *
1562 : * @return LDB_SUCCESS or error including out of memory error
1563 : */
1564 274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1565 : const struct ldb_message *obj,
1566 : TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1567 : {
1568 : const struct dsdb_class *objectclass;
1569 : struct ldb_message_element *objectclass_element;
1570 : struct dsdb_extended_dn_store_format *dn_format;
1571 :
1572 274 : objectclass_element = ldb_msg_find_element(obj, "objectClass");
1573 274 : if (!objectclass_element) {
1574 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1575 0 : ldb_dn_get_linearized(obj->dn));
1576 0 : return LDB_ERR_OBJECT_CLASS_VIOLATION;
1577 : }
1578 274 : if (objectclass_element->num_values == 0) {
1579 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1580 0 : ldb_dn_get_linearized(obj->dn));
1581 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1582 : }
1583 :
1584 : /*
1585 : * Get the new top-most structural object class and check for
1586 : * unrelated structural classes
1587 : */
1588 274 : objectclass = dsdb_get_last_structural_class(schema,
1589 : objectclass_element);
1590 274 : if (objectclass == NULL) {
1591 0 : ldb_asprintf_errstring(ldb,
1592 : "Failed to find a structural class for %s",
1593 0 : ldb_dn_get_linearized(obj->dn));
1594 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
1595 : }
1596 :
1597 274 : dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1598 : struct dsdb_extended_dn_store_format);
1599 274 : if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1600 : /* Strip off extended components */
1601 0 : struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1602 0 : objectclass->defaultObjectCategory);
1603 0 : *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1604 0 : talloc_free(dn);
1605 : } else {
1606 274 : *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1607 : }
1608 :
1609 274 : if (*pobjectcategory == NULL) {
1610 0 : return ldb_oom(ldb);
1611 : }
1612 :
1613 274 : return LDB_SUCCESS;
1614 : }
|