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 8654217 : 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 8654217 : tmp_ctx = talloc_new(mem_ctx);
51 :
52 8654217 : res = talloc_zero(tmp_ctx, struct ldb_result);
53 8654217 : if (!res) {
54 0 : talloc_free(tmp_ctx);
55 0 : return ldb_oom(ldb_module_get_ctx(module));
56 : }
57 :
58 8654217 : 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 8654217 : LDB_REQ_SET_LOCATION(req);
68 8654217 : if (ret != LDB_SUCCESS) {
69 0 : talloc_free(tmp_ctx);
70 0 : return ret;
71 : }
72 :
73 8654217 : ret = dsdb_request_add_controls(req, dsdb_flags);
74 8654217 : if (ret != LDB_SUCCESS) {
75 0 : talloc_free(tmp_ctx);
76 0 : return ret;
77 : }
78 :
79 8654217 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
80 0 : ldb_req_mark_trusted(req);
81 : }
82 :
83 : /* Run the new request */
84 8654217 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
85 8653943 : 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 8654217 : if (ret == LDB_SUCCESS) {
94 8654215 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
95 : }
96 :
97 8654217 : if (ret != LDB_SUCCESS) {
98 156039 : talloc_free(tmp_ctx);
99 156039 : return ret;
100 : }
101 :
102 8498178 : if (res->count != 1) {
103 : /* we may be reading a DB that does not have the 'check base on search' option... */
104 11856 : ret = LDB_ERR_NO_SUCH_OBJECT;
105 11856 : 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 8486322 : *_res = talloc_steal(mem_ctx, res);
110 : }
111 8498178 : talloc_free(tmp_ctx);
112 8498178 : return ret;
113 : }
114 :
115 9048343 : 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 9048343 : tmp_ctx = talloc_new(mem_ctx);
131 :
132 : /* cross-partitions searches with a basedn break multi-domain support */
133 9048343 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
134 :
135 9048343 : res = talloc_zero(tmp_ctx, struct ldb_result);
136 9048343 : if (!res) {
137 0 : talloc_free(tmp_ctx);
138 0 : return ldb_oom(ldb_module_get_ctx(module));
139 : }
140 :
141 9048343 : 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 9048343 : LDB_REQ_SET_LOCATION(req);
151 9048343 : if (ret != LDB_SUCCESS) {
152 0 : talloc_free(tmp_ctx);
153 0 : return ret;
154 : }
155 :
156 9048343 : ret = dsdb_request_add_controls(req, dsdb_flags);
157 9048343 : if (ret != LDB_SUCCESS) {
158 0 : talloc_free(tmp_ctx);
159 0 : return ret;
160 : }
161 :
162 9048343 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
163 0 : ldb_req_mark_trusted(req);
164 : }
165 :
166 9048343 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
167 9048343 : ret = ldb_next_request(module, req);
168 0 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
169 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
170 : } else {
171 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
172 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
173 0 : ret = ops->search(module, req);
174 : }
175 9048343 : if (ret == LDB_SUCCESS) {
176 9048343 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
177 : }
178 :
179 9048343 : if (dsdb_flags & DSDB_SEARCH_ONE_ONLY) {
180 7267964 : if (res->count == 0) {
181 6965 : talloc_free(tmp_ctx);
182 6965 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
183 : }
184 7260999 : 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 9041378 : talloc_free(req);
192 9041378 : if (ret == LDB_SUCCESS) {
193 9040620 : *_res = talloc_steal(mem_ctx, res);
194 : }
195 9041378 : talloc_free(tmp_ctx);
196 9041378 : return ret;
197 : }
198 :
199 : /*
200 : search for attrs in the modules below
201 : */
202 9047103 : 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 9047103 : SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);
219 :
220 9047103 : tmp_ctx = talloc_new(mem_ctx);
221 :
222 9047103 : if (format) {
223 8608498 : va_start(ap, format);
224 8608498 : expression = talloc_vasprintf(tmp_ctx, format, ap);
225 8608498 : va_end(ap);
226 :
227 8608498 : if (!expression) {
228 0 : talloc_free(tmp_ctx);
229 0 : return ldb_oom(ldb_module_get_ctx(module));
230 : }
231 : } else {
232 438605 : expression = NULL;
233 : }
234 :
235 9047103 : tree = ldb_parse_tree(tmp_ctx, expression);
236 9047103 : 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 9047103 : 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 9047103 : talloc_free(tmp_ctx);
254 9047103 : return ret;
255 : }
256 :
257 : /*
258 : find a DN given a GUID. This searches across all partitions
259 : */
260 38027 : 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 38027 : const char *attrs[] = { NULL };
266 38027 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
267 : int ret;
268 :
269 38027 : 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 38027 : if (ret != LDB_SUCCESS) {
278 0 : talloc_free(tmp_ctx);
279 0 : return ret;
280 : }
281 38027 : if (res->count == 0) {
282 40 : talloc_free(tmp_ctx);
283 40 : return ldb_error(ldb_module_get_ctx(module), LDB_ERR_NO_SUCH_OBJECT, __func__);
284 : }
285 37987 : 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 37987 : *dn = talloc_steal(mem_ctx, res->msgs[0]->dn);
293 :
294 37987 : talloc_free(tmp_ctx);
295 37987 : return LDB_SUCCESS;
296 : }
297 :
298 : /*
299 : find a GUID given a DN.
300 : */
301 12417 : int dsdb_module_guid_by_dn(struct ldb_module *module, struct ldb_dn *dn, struct GUID *guid,
302 : struct ldb_request *parent)
303 : {
304 12417 : const char *attrs[] = { NULL };
305 : struct ldb_result *res;
306 12417 : TALLOC_CTX *tmp_ctx = talloc_new(module);
307 : int ret;
308 : NTSTATUS status;
309 :
310 12417 : 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 12417 : 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 12414 : status = dsdb_get_extended_dn_guid(res->msgs[0]->dn, guid, "GUID");
323 12414 : 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 12414 : talloc_free(tmp_ctx);
329 12414 : 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 11977304 : 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 11977304 : struct ldb_context *ldb = ldb_module_get_ctx(module);
350 11977304 : TALLOC_CTX *tmp_ctx = talloc_new(module);
351 : struct ldb_result *res;
352 :
353 11977304 : if (_res != NULL) {
354 11643867 : (*_res) = NULL;
355 : }
356 :
357 11977304 : res = talloc_zero(tmp_ctx, struct ldb_result);
358 11977304 : if (!res) {
359 0 : talloc_free(tmp_ctx);
360 0 : return ldb_oom(ldb_module_get_ctx(module));
361 : }
362 :
363 11977304 : 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 11977304 : LDB_REQ_SET_LOCATION(req);
372 11977304 : if (ret != LDB_SUCCESS) {
373 0 : talloc_free(tmp_ctx);
374 0 : return ret;
375 : }
376 :
377 11977304 : ret = dsdb_request_add_controls(req, dsdb_flags);
378 11977304 : if (ret != LDB_SUCCESS) {
379 0 : talloc_free(tmp_ctx);
380 0 : return ret;
381 : }
382 :
383 11977304 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
384 333437 : ldb_req_mark_trusted(req);
385 : }
386 :
387 : /* Run the new request */
388 11977304 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
389 11643867 : ret = ldb_next_request(module, req);
390 333437 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
391 333437 : 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 11977304 : if (ret == LDB_SUCCESS) {
398 11977304 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
399 : }
400 :
401 11977304 : if (_res != NULL && ret == LDB_SUCCESS) {
402 11643867 : (*_res) = talloc_steal(mem_ctx, res);
403 : }
404 :
405 11977304 : talloc_free(tmp_ctx);
406 11977304 : return ret;
407 : }
408 :
409 :
410 : /*
411 : a ldb_modify request operating on modules below the
412 : current module
413 : */
414 235260 : 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 235260 : struct ldb_context *ldb = ldb_module_get_ctx(module);
422 235260 : TALLOC_CTX *tmp_ctx = talloc_new(module);
423 : struct ldb_result *res;
424 :
425 235260 : res = talloc_zero(tmp_ctx, struct ldb_result);
426 235260 : if (!res) {
427 0 : talloc_free(tmp_ctx);
428 0 : return ldb_oom(ldb_module_get_ctx(module));
429 : }
430 :
431 235260 : ret = ldb_build_mod_req(&mod_req, ldb, tmp_ctx,
432 : message,
433 : NULL,
434 : res,
435 : ldb_modify_default_callback,
436 : parent);
437 235260 : LDB_REQ_SET_LOCATION(mod_req);
438 235260 : if (ret != LDB_SUCCESS) {
439 0 : talloc_free(tmp_ctx);
440 0 : return ret;
441 : }
442 :
443 235260 : ret = dsdb_request_add_controls(mod_req, dsdb_flags);
444 235260 : if (ret != LDB_SUCCESS) {
445 0 : talloc_free(tmp_ctx);
446 0 : return ret;
447 : }
448 :
449 235260 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
450 0 : ldb_req_mark_trusted(mod_req);
451 : }
452 :
453 : /* Run the new request */
454 235260 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
455 91115 : ret = ldb_next_request(module, mod_req);
456 144145 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
457 0 : ret = ldb_request(ldb_module_get_ctx(module), mod_req);
458 : } else {
459 144145 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
460 144145 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
461 144145 : ret = ops->modify(module, mod_req);
462 : }
463 235260 : if (ret == LDB_SUCCESS) {
464 235260 : ret = ldb_wait(mod_req->handle, LDB_WAIT_ALL);
465 : }
466 :
467 235260 : talloc_free(tmp_ctx);
468 235260 : return ret;
469 : }
470 :
471 :
472 :
473 : /*
474 : a ldb_rename request operating on modules below the
475 : current module
476 : */
477 110998 : 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 110998 : struct ldb_context *ldb = ldb_module_get_ctx(module);
485 110998 : TALLOC_CTX *tmp_ctx = talloc_new(module);
486 : struct ldb_result *res;
487 :
488 110998 : res = talloc_zero(tmp_ctx, struct ldb_result);
489 110998 : if (!res) {
490 0 : talloc_free(tmp_ctx);
491 0 : return ldb_oom(ldb_module_get_ctx(module));
492 : }
493 :
494 110998 : 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 110998 : LDB_REQ_SET_LOCATION(req);
502 110998 : if (ret != LDB_SUCCESS) {
503 0 : talloc_free(tmp_ctx);
504 0 : return ret;
505 : }
506 :
507 110998 : ret = dsdb_request_add_controls(req, dsdb_flags);
508 110998 : if (ret != LDB_SUCCESS) {
509 0 : talloc_free(tmp_ctx);
510 0 : return ret;
511 : }
512 :
513 110998 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
514 0 : ldb_req_mark_trusted(req);
515 : }
516 :
517 : /* Run the new request */
518 110998 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
519 110476 : ret = ldb_next_request(module, req);
520 522 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
521 0 : ret = ldb_request(ldb_module_get_ctx(module), req);
522 : } else {
523 522 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
524 522 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
525 522 : ret = ops->rename(module, req);
526 : }
527 110998 : if (ret == LDB_SUCCESS) {
528 110996 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
529 : }
530 :
531 110998 : talloc_free(tmp_ctx);
532 110998 : return ret;
533 : }
534 :
535 : /*
536 : a ldb_add request operating on modules below the
537 : current module
538 : */
539 1127 : 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 1127 : struct ldb_context *ldb = ldb_module_get_ctx(module);
547 1127 : TALLOC_CTX *tmp_ctx = talloc_new(module);
548 : struct ldb_result *res;
549 :
550 1127 : res = talloc_zero(tmp_ctx, struct ldb_result);
551 1127 : if (!res) {
552 0 : talloc_free(tmp_ctx);
553 0 : return ldb_oom(ldb_module_get_ctx(module));
554 : }
555 :
556 1127 : ret = ldb_build_add_req(&req, ldb, tmp_ctx,
557 : message,
558 : NULL,
559 : res,
560 : ldb_modify_default_callback,
561 : parent);
562 1127 : LDB_REQ_SET_LOCATION(req);
563 1127 : if (ret != LDB_SUCCESS) {
564 0 : talloc_free(tmp_ctx);
565 0 : return ret;
566 : }
567 :
568 1127 : ret = dsdb_request_add_controls(req, dsdb_flags);
569 1127 : if (ret != LDB_SUCCESS) {
570 0 : talloc_free(tmp_ctx);
571 0 : return ret;
572 : }
573 :
574 1127 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
575 0 : ldb_req_mark_trusted(req);
576 : }
577 :
578 : /* Run the new request */
579 1127 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
580 1067 : ret = ldb_next_request(module, req);
581 60 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
582 60 : 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 1127 : if (ret == LDB_SUCCESS) {
589 1127 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
590 : }
591 :
592 1127 : talloc_free(tmp_ctx);
593 1127 : return ret;
594 : }
595 :
596 : /*
597 : a ldb_delete request operating on modules below the
598 : current module
599 : */
600 18377 : int dsdb_module_del(struct ldb_module *module,
601 : struct ldb_dn *dn,
602 : uint32_t dsdb_flags,
603 : struct ldb_request *parent)
604 : {
605 : struct ldb_request *req;
606 : int ret;
607 18377 : struct ldb_context *ldb = ldb_module_get_ctx(module);
608 18377 : TALLOC_CTX *tmp_ctx = talloc_new(module);
609 : struct ldb_result *res;
610 :
611 18377 : res = talloc_zero(tmp_ctx, struct ldb_result);
612 18377 : if (!res) {
613 0 : talloc_free(tmp_ctx);
614 0 : return ldb_oom(ldb);
615 : }
616 :
617 18377 : ret = ldb_build_del_req(&req, ldb, tmp_ctx,
618 : dn,
619 : NULL,
620 : res,
621 : ldb_modify_default_callback,
622 : parent);
623 18377 : LDB_REQ_SET_LOCATION(req);
624 18377 : if (ret != LDB_SUCCESS) {
625 0 : talloc_free(tmp_ctx);
626 0 : return ret;
627 : }
628 :
629 18377 : ret = dsdb_request_add_controls(req, dsdb_flags);
630 18377 : if (ret != LDB_SUCCESS) {
631 0 : talloc_free(tmp_ctx);
632 0 : return ret;
633 : }
634 :
635 18377 : if (dsdb_flags & DSDB_FLAG_TRUSTED) {
636 18377 : ldb_req_mark_trusted(req);
637 : }
638 :
639 : /* Run the new request */
640 18377 : if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
641 0 : ret = ldb_next_request(module, req);
642 18377 : } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
643 18377 : ret = ldb_request(ldb_module_get_ctx(module), req);
644 : } else {
645 0 : const struct ldb_module_ops *ops = ldb_module_get_ops(module);
646 0 : SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
647 0 : ret = ops->del(module, req);
648 : }
649 18377 : if (ret == LDB_SUCCESS) {
650 18377 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
651 : }
652 :
653 18377 : talloc_free(tmp_ctx);
654 18377 : return ret;
655 : }
656 :
657 : /*
658 : check if a single valued link has multiple non-deleted values
659 :
660 : This is needed when we will be using the RELAX control to stop
661 : ldb_tdb from checking single valued links
662 : */
663 40925 : int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
664 : const struct ldb_message_element *el)
665 : {
666 40925 : bool found_active = false;
667 : unsigned int i;
668 :
669 47407 : if (!(attr->ldb_schema_attribute->flags & LDB_ATTR_FLAG_SINGLE_VALUE) ||
670 6692 : el->num_values < 2) {
671 40795 : return LDB_SUCCESS;
672 : }
673 :
674 388 : for (i=0; i<el->num_values; i++) {
675 261 : if (!dsdb_dn_is_deleted_val(&el->values[i])) {
676 121 : if (found_active) {
677 3 : return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
678 : }
679 118 : found_active = true;
680 : }
681 : }
682 :
683 127 : return LDB_SUCCESS;
684 : }
685 :
686 :
687 216026 : int dsdb_check_samba_compatible_feature(struct ldb_module *module,
688 : const char *feature,
689 : bool *found)
690 : {
691 216026 : 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 216026 : struct ldb_dn *samba_dsdb_dn = NULL;
699 216026 : TALLOC_CTX *tmp_ctx = talloc_new(ldb);
700 216026 : if (tmp_ctx == NULL) {
701 0 : *found = false;
702 0 : return ldb_oom(ldb);
703 : }
704 216026 : *found = false;
705 :
706 216026 : samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
707 216026 : if (samba_dsdb_dn == NULL) {
708 0 : TALLOC_FREE(tmp_ctx);
709 0 : return ldb_oom(ldb);
710 : }
711 :
712 216026 : 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 216026 : if (ret == LDB_SUCCESS) {
720 216026 : *found = ldb_msg_check_string_attribute(
721 216026 : 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 216026 : TALLOC_FREE(tmp_ctx);
729 216026 : 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 81086 : int dsdb_check_optional_feature(struct ldb_module *module, struct GUID op_feature_guid, bool *feature_enabled)
743 : {
744 : TALLOC_CTX *tmp_ctx;
745 81086 : 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 81086 : 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 81086 : tmp_ctx = talloc_new(ldb);
756 :
757 81086 : feature_dn = samdb_ntds_settings_dn(ldb_module_get_ctx(module), tmp_ctx);
758 81086 : if (feature_dn == NULL) {
759 0 : talloc_free(tmp_ctx);
760 0 : return ldb_operr(ldb_module_get_ctx(module));
761 : }
762 :
763 81086 : *feature_enabled = false;
764 :
765 81086 : ret = dsdb_module_search_dn(module, tmp_ctx, &res, feature_dn, attrs, DSDB_FLAG_NEXT_MODULE, NULL);
766 81086 : if (ret != LDB_SUCCESS) {
767 1273 : ldb_asprintf_errstring(ldb,
768 : "Could not find the feature object - dn: %s\n",
769 : ldb_dn_get_linearized(feature_dn));
770 1273 : talloc_free(tmp_ctx);
771 1273 : return LDB_ERR_NO_SUCH_OBJECT;
772 : }
773 79813 : 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 79813 : talloc_free(tmp_ctx);
800 79813 : 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 1212 : 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 1212 : attrs[0] = attribute;
845 1212 : attrs[1] = NULL;
846 :
847 1212 : ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs,
848 : DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_EXTENDED_DN, parent);
849 1212 : if (ret != LDB_SUCCESS) {
850 0 : return ret;
851 : }
852 :
853 1212 : *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
854 1212 : mem_ctx, res->msgs[0], attribute);
855 1212 : if (!*dn) {
856 28 : ldb_reset_err_string(ldb_module_get_ctx(module));
857 28 : talloc_free(res);
858 28 : return LDB_ERR_NO_SUCH_ATTRIBUTE;
859 : }
860 :
861 1184 : talloc_free(res);
862 1184 : return LDB_SUCCESS;
863 : }
864 :
865 : /*
866 : find the RID Manager$ DN via the rIDManagerReference attribute in the
867 : base DN
868 : */
869 356 : 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 356 : 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 104854748 : int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
881 : {
882 104854748 : struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
883 :
884 104854748 : if (!ares) {
885 0 : return ldb_module_done(up_req, NULL, NULL,
886 : LDB_ERR_OPERATIONS_ERROR);
887 : }
888 :
889 104854748 : if (ares->error != LDB_SUCCESS || ares->type == LDB_REPLY_DONE) {
890 35335991 : return ldb_module_done(up_req, ares->controls,
891 : ares->response, ares->error);
892 : }
893 :
894 : /* Otherwise pass on the callback */
895 69518757 : switch (ares->type) {
896 66870113 : case LDB_REPLY_ENTRY:
897 66870113 : return ldb_module_send_entry(up_req, ares->message,
898 : ares->controls);
899 :
900 2648644 : case LDB_REPLY_REFERRAL:
901 2648644 : 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 155328 : 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 155328 : 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 155328 : msg = ldb_msg_new(module);
1013 155328 : if (msg == NULL) {
1014 0 : return ldb_module_oom(module);
1015 : }
1016 :
1017 155328 : msg->dn = ldb_dn_new(msg, ldb, "@REPLCHANGED");
1018 155328 : if (msg->dn == NULL) {
1019 0 : talloc_free(msg);
1020 0 : return ldb_operr(ldb_module_get_ctx(module));
1021 : }
1022 :
1023 155328 : res = talloc_zero(msg, struct ldb_result);
1024 155328 : if (!res) {
1025 0 : talloc_free(msg);
1026 0 : return ldb_module_oom(module);
1027 : }
1028 :
1029 155328 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNHighest", uSN);
1030 155328 : if (ret != LDB_SUCCESS) {
1031 0 : talloc_free(msg);
1032 0 : return ret;
1033 : }
1034 155328 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1035 :
1036 : /* urgent_uSN is optional so may not be stored */
1037 155328 : if (urgent_uSN) {
1038 24840 : ret = samdb_msg_add_uint64(ldb, msg, msg, "uSNUrgent",
1039 : urgent_uSN);
1040 24840 : if (ret != LDB_SUCCESS) {
1041 0 : talloc_free(msg);
1042 0 : return ret;
1043 : }
1044 24840 : msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1045 : }
1046 :
1047 :
1048 155328 : p_ctrl = talloc(msg, struct dsdb_control_current_partition);
1049 155328 : if (p_ctrl == NULL) {
1050 0 : talloc_free(msg);
1051 0 : return ldb_oom(ldb);
1052 : }
1053 155328 : p_ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION;
1054 155328 : p_ctrl->dn = dn;
1055 155328 : ret = ldb_build_mod_req(&req, ldb, msg,
1056 : msg,
1057 : NULL,
1058 : res,
1059 : ldb_modify_default_callback,
1060 : parent);
1061 155328 : LDB_REQ_SET_LOCATION(req);
1062 156024 : again:
1063 156024 : if (ret != LDB_SUCCESS) {
1064 0 : talloc_free(msg);
1065 0 : return ret;
1066 : }
1067 :
1068 156024 : ret = ldb_request_add_control(req,
1069 : DSDB_CONTROL_CURRENT_PARTITION_OID,
1070 : false, p_ctrl);
1071 156024 : if (ret != LDB_SUCCESS) {
1072 0 : talloc_free(msg);
1073 0 : return ret;
1074 : }
1075 :
1076 : /* Run the new request */
1077 156024 : ret = ldb_next_request(module, req);
1078 :
1079 156024 : if (ret == LDB_SUCCESS) {
1080 156024 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1081 : }
1082 156024 : if (ret == LDB_ERR_NO_SUCH_OBJECT) {
1083 696 : ret = ldb_build_add_req(&req, ldb, msg,
1084 : msg,
1085 : NULL,
1086 : res,
1087 : ldb_modify_default_callback,
1088 : parent);
1089 696 : LDB_REQ_SET_LOCATION(req);
1090 696 : goto again;
1091 : }
1092 :
1093 155328 : talloc_free(msg);
1094 :
1095 155328 : return ret;
1096 : }
1097 :
1098 31567170 : bool dsdb_module_am_system(struct ldb_module *module)
1099 : {
1100 31567170 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1101 27956993 : struct auth_session_info *session_info
1102 31567170 : = talloc_get_type(
1103 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1104 : struct auth_session_info);
1105 31567170 : return security_session_user_level(session_info, NULL) == SECURITY_SYSTEM;
1106 : }
1107 :
1108 19963001 : bool dsdb_module_am_administrator(struct ldb_module *module)
1109 : {
1110 19963001 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1111 17718927 : struct auth_session_info *session_info
1112 19963001 : = talloc_get_type(
1113 : ldb_get_opaque(ldb, DSDB_SESSION_INFO),
1114 : struct auth_session_info);
1115 19963001 : return security_session_user_level(session_info, NULL) == SECURITY_ADMINISTRATOR;
1116 : }
1117 :
1118 : /*
1119 : check if the recyclebin is enabled
1120 : */
1121 81086 : int dsdb_recyclebin_enabled(struct ldb_module *module, bool *enabled)
1122 : {
1123 81086 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1124 : struct GUID recyclebin_guid;
1125 : int ret;
1126 :
1127 81086 : GUID_from_string(DS_GUID_FEATURE_RECYCLE_BIN, &recyclebin_guid);
1128 :
1129 81086 : ret = dsdb_check_optional_feature(module, recyclebin_guid, enabled);
1130 81086 : if (ret != LDB_SUCCESS) {
1131 1273 : ldb_asprintf_errstring(ldb, "Could not verify if Recycle Bin is enabled \n");
1132 1273 : return ret;
1133 : }
1134 :
1135 79813 : return LDB_SUCCESS;
1136 : }
1137 :
1138 46608 : 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 46608 : if (old_val) {
1149 23279 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1150 23279 : if (ret != LDB_SUCCESS) {
1151 0 : return ret;
1152 : }
1153 23279 : el->num_values = 1;
1154 23279 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1155 23279 : if (!el->values) {
1156 0 : return ldb_module_oom(module);
1157 : }
1158 23279 : vstring = talloc_asprintf(el->values, "%ld", (long)*old_val);
1159 23279 : if (!vstring) {
1160 0 : return ldb_module_oom(module);
1161 : }
1162 23279 : *el->values = data_blob_string_const(vstring);
1163 : }
1164 :
1165 46608 : if (new_val) {
1166 23404 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1167 23404 : if (ret != LDB_SUCCESS) {
1168 0 : return ret;
1169 : }
1170 23404 : el->num_values = 1;
1171 23404 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1172 23404 : if (!el->values) {
1173 0 : return ldb_module_oom(module);
1174 : }
1175 23404 : vstring = talloc_asprintf(el->values, "%ld", (long)*new_val);
1176 23404 : if (!vstring) {
1177 0 : return ldb_module_oom(module);
1178 : }
1179 23404 : *el->values = data_blob_string_const(vstring);
1180 : }
1181 :
1182 46608 : return LDB_SUCCESS;
1183 : }
1184 :
1185 46608 : 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 46608 : return dsdb_msg_constrainted_update_int32(module, msg, attr,
1192 : (const int32_t *)old_val,
1193 : (const int32_t *)new_val);
1194 : }
1195 :
1196 46713 : 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 46713 : if (old_val) {
1207 196 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
1208 196 : if (ret != LDB_SUCCESS) {
1209 0 : return ret;
1210 : }
1211 196 : el->num_values = 1;
1212 196 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1213 196 : if (!el->values) {
1214 0 : return ldb_module_oom(module);
1215 : }
1216 196 : vstring = talloc_asprintf(el->values, "%lld", (long long)*old_val);
1217 196 : if (!vstring) {
1218 0 : return ldb_module_oom(module);
1219 : }
1220 196 : *el->values = data_blob_string_const(vstring);
1221 : }
1222 :
1223 46713 : if (new_val) {
1224 320 : ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
1225 320 : if (ret != LDB_SUCCESS) {
1226 0 : return ret;
1227 : }
1228 320 : el->num_values = 1;
1229 320 : el->values = talloc_array(msg, struct ldb_val, el->num_values);
1230 320 : if (!el->values) {
1231 0 : return ldb_module_oom(module);
1232 : }
1233 320 : vstring = talloc_asprintf(el->values, "%lld", (long long)*new_val);
1234 320 : if (!vstring) {
1235 0 : return ldb_module_oom(module);
1236 : }
1237 320 : *el->values = data_blob_string_const(vstring);
1238 : }
1239 :
1240 46713 : return LDB_SUCCESS;
1241 : }
1242 :
1243 46608 : 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 46608 : return dsdb_msg_constrainted_update_int64(module, msg, attr,
1250 : (const int64_t *)old_val,
1251 : (const int64_t *)new_val);
1252 : }
1253 :
1254 : /*
1255 : update an int32 attribute safely via a constrained delete/add
1256 : */
1257 0 : int dsdb_module_constrainted_update_int32(struct ldb_module *module,
1258 : struct ldb_dn *dn,
1259 : const char *attr,
1260 : const int32_t *old_val,
1261 : const int32_t *new_val,
1262 : struct ldb_request *parent)
1263 : {
1264 : struct ldb_message *msg;
1265 : int ret;
1266 :
1267 0 : msg = ldb_msg_new(module);
1268 0 : if (msg == NULL) {
1269 0 : return ldb_module_oom(module);
1270 : }
1271 0 : msg->dn = dn;
1272 :
1273 0 : ret = dsdb_msg_constrainted_update_int32(module,
1274 : msg, attr,
1275 : old_val,
1276 : new_val);
1277 0 : if (ret != LDB_SUCCESS) {
1278 0 : talloc_free(msg);
1279 0 : return ret;
1280 : }
1281 :
1282 0 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1283 0 : talloc_free(msg);
1284 0 : return ret;
1285 : }
1286 :
1287 0 : int dsdb_module_constrainted_update_uint32(struct ldb_module *module,
1288 : struct ldb_dn *dn,
1289 : const char *attr,
1290 : const uint32_t *old_val,
1291 : const uint32_t *new_val,
1292 : struct ldb_request *parent)
1293 : {
1294 0 : return dsdb_module_constrainted_update_int32(module, dn, attr,
1295 : (const int32_t *)old_val,
1296 : (const int32_t *)new_val, parent);
1297 : }
1298 :
1299 : /*
1300 : update an int64 attribute safely via a constrained delete/add
1301 : */
1302 105 : 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 105 : msg = ldb_msg_new(module);
1313 105 : if (msg == NULL) {
1314 0 : return ldb_module_oom(module);
1315 : }
1316 105 : msg->dn = dn;
1317 :
1318 105 : ret = dsdb_msg_constrainted_update_int64(module,
1319 : msg, attr,
1320 : old_val,
1321 : new_val);
1322 105 : if (ret != LDB_SUCCESS) {
1323 0 : talloc_free(msg);
1324 0 : return ret;
1325 : }
1326 :
1327 105 : ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
1328 105 : talloc_free(msg);
1329 105 : return ret;
1330 : }
1331 :
1332 105 : 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 105 : 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 1048319 : 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 1048319 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1352 : static const char *attrs[] = { "dSHeuristics", NULL };
1353 : struct ldb_result *res;
1354 :
1355 1048319 : new_dn = ldb_dn_copy(mem_ctx, ldb_get_config_basedn(ldb));
1356 1048319 : 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 1048319 : ret = dsdb_module_search_dn(module, mem_ctx, &res,
1362 : new_dn,
1363 : attrs,
1364 : DSDB_FLAG_NEXT_MODULE,
1365 : parent);
1366 1048319 : if (ret == LDB_SUCCESS && res->count == 1) {
1367 893901 : talloc_free(new_dn);
1368 893901 : return ldb_msg_find_ldb_val(res->msgs[0],
1369 : "dSHeuristics");
1370 : }
1371 154418 : talloc_free(new_dn);
1372 154418 : return NULL;
1373 : }
1374 :
1375 108429 : bool dsdb_block_anonymous_ops(struct ldb_module *module, struct ldb_request *parent)
1376 : {
1377 108429 : TALLOC_CTX *tmp_ctx = talloc_new(module);
1378 : bool result;
1379 108429 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1380 : tmp_ctx, parent);
1381 108429 : if (hr_val == NULL || hr_val->length < DS_HR_BLOCK_ANONYMOUS_OPS) {
1382 96964 : result = true;
1383 11465 : } else if (hr_val->data[DS_HR_BLOCK_ANONYMOUS_OPS -1] == '2') {
1384 17 : result = false;
1385 : } else {
1386 11448 : result = true;
1387 : }
1388 :
1389 108429 : talloc_free(tmp_ctx);
1390 108429 : return result;
1391 : }
1392 :
1393 923610 : bool dsdb_user_password_support(struct ldb_module *module,
1394 : TALLOC_CTX *mem_ctx,
1395 : struct ldb_request *parent)
1396 : {
1397 923610 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1398 : bool result;
1399 923610 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1400 : tmp_ctx,
1401 : parent);
1402 923610 : if (hr_val == NULL || hr_val->length < DS_HR_USER_PASSWORD_SUPPORT) {
1403 898834 : result = false;
1404 43404 : } else if ((hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '2') ||
1405 24748 : (hr_val->data[DS_HR_USER_PASSWORD_SUPPORT -1] == '0')) {
1406 860 : result = false;
1407 : } else {
1408 23916 : result = true;
1409 : }
1410 :
1411 923610 : talloc_free(tmp_ctx);
1412 923610 : return result;
1413 : }
1414 :
1415 16280 : bool dsdb_do_list_object(struct ldb_module *module,
1416 : TALLOC_CTX *mem_ctx,
1417 : struct ldb_request *parent)
1418 : {
1419 16280 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1420 : bool result;
1421 16280 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1422 : tmp_ctx,
1423 : parent);
1424 16280 : if (hr_val == NULL || hr_val->length < DS_HR_DOLISTOBJECT) {
1425 26 : result = false;
1426 16254 : } else if (hr_val->data[DS_HR_DOLISTOBJECT -1] == '1') {
1427 8064 : result = true;
1428 : } else {
1429 8190 : result = false;
1430 : }
1431 :
1432 16280 : talloc_free(tmp_ctx);
1433 16280 : return result;
1434 : }
1435 :
1436 0 : bool dsdb_attribute_authz_on_ldap_add(struct ldb_module *module,
1437 : TALLOC_CTX *mem_ctx,
1438 : struct ldb_request *parent)
1439 : {
1440 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1441 0 : bool result = false;
1442 0 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1443 : tmp_ctx,
1444 : parent);
1445 0 : if (hr_val != NULL && hr_val->length >= DS_HR_ATTR_AUTHZ_ON_LDAP_ADD) {
1446 0 : uint8_t val = hr_val->data[DS_HR_ATTR_AUTHZ_ON_LDAP_ADD - 1];
1447 0 : if (val != '0' && val != '2') {
1448 0 : result = true;
1449 : }
1450 : }
1451 :
1452 0 : talloc_free(tmp_ctx);
1453 0 : return result;
1454 : }
1455 :
1456 0 : bool dsdb_block_owner_implicit_rights(struct ldb_module *module,
1457 : TALLOC_CTX *mem_ctx,
1458 : struct ldb_request *parent)
1459 : {
1460 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1461 0 : bool result = false;
1462 0 : const struct ldb_val *hr_val = dsdb_module_find_dsheuristics(module,
1463 : tmp_ctx,
1464 : parent);
1465 0 : if (hr_val != NULL && hr_val->length >= DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS) {
1466 0 : uint8_t val = hr_val->data[DS_HR_BLOCK_OWNER_IMPLICIT_RIGHTS - 1];
1467 0 : if (val != '0' && val != '2') {
1468 0 : result = true;
1469 : }
1470 : }
1471 :
1472 0 : talloc_free(tmp_ctx);
1473 0 : return result;
1474 : }
1475 :
1476 : /*
1477 : show the chain of requests, useful for debugging async requests
1478 : */
1479 0 : void dsdb_req_chain_debug(struct ldb_request *req, int level)
1480 : {
1481 0 : char *s = ldb_module_call_chain(req, req);
1482 0 : DEBUG(level, ("%s\n", s));
1483 0 : talloc_free(s);
1484 0 : }
1485 :
1486 : /*
1487 : * Get all the values that *might* be added by an ldb message, as a composite
1488 : * ldb element.
1489 : *
1490 : * This is useful when we need to check all the possible values against some
1491 : * criteria.
1492 : *
1493 : * In cases where a modify message mixes multiple ADDs, DELETEs, and REPLACES,
1494 : * the returned element might contain more values than would actually end up
1495 : * in the database if the message was run to its conclusion.
1496 : *
1497 : * If the operation is not LDB_ADD or LDB_MODIFY, an operations error is
1498 : * returned.
1499 : *
1500 : * The returned element might not be new, and should not be modified or freed
1501 : * before the message is finished.
1502 : */
1503 :
1504 252004 : int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
1505 : const struct ldb_message *msg,
1506 : const char *attr_name,
1507 : struct ldb_message_element **el,
1508 : enum ldb_request_type operation)
1509 : {
1510 : unsigned int i;
1511 252004 : unsigned int el_count = 0;
1512 252004 : unsigned int val_count = 0;
1513 252004 : struct ldb_val *v = NULL;
1514 252004 : struct ldb_message_element *_el = NULL;
1515 252004 : *el = NULL;
1516 :
1517 252004 : if (operation != LDB_ADD && operation != LDB_MODIFY) {
1518 0 : DBG_ERR("inapplicable operation type: %d\n", operation);
1519 0 : return LDB_ERR_OPERATIONS_ERROR;
1520 : }
1521 :
1522 : /* count the adding or replacing elements */
1523 4490534 : for (i = 0; i < msg->num_elements; i++) {
1524 4238530 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1525 : unsigned int tmp;
1526 261899 : if ((operation == LDB_MODIFY) &&
1527 27778 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1528 : == LDB_FLAG_MOD_DELETE)) {
1529 10670 : continue;
1530 : }
1531 232433 : el_count++;
1532 232433 : tmp = val_count + msg->elements[i].num_values;
1533 232433 : if (unlikely(tmp < val_count)) {
1534 0 : DBG_ERR("too many values for one element!");
1535 0 : return LDB_ERR_OPERATIONS_ERROR;
1536 : }
1537 232433 : val_count = tmp;
1538 : }
1539 : }
1540 252004 : if (el_count == 0) {
1541 : /* nothing to see here */
1542 19580 : return LDB_SUCCESS;
1543 : }
1544 :
1545 232424 : if (el_count == 1 || val_count == 0) {
1546 : /*
1547 : * There is one effective element, which we can return as-is,
1548 : * OR there are only elements with zero values -- any of which
1549 : * will do.
1550 : */
1551 1522613 : for (i = 0; i < msg->num_elements; i++) {
1552 1522613 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1553 261831 : if ((operation == LDB_MODIFY) &&
1554 27736 : (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
1555 : == LDB_FLAG_MOD_DELETE)) {
1556 10646 : continue;
1557 : }
1558 232415 : *el = &msg->elements[i];
1559 232415 : return LDB_SUCCESS;
1560 : }
1561 : }
1562 : }
1563 :
1564 9 : _el = talloc_zero(mem_ctx, struct ldb_message_element);
1565 9 : if (_el == NULL) {
1566 0 : return LDB_ERR_OPERATIONS_ERROR;
1567 : }
1568 9 : _el->name = attr_name;
1569 :
1570 9 : if (val_count == 0) {
1571 : /*
1572 : * Seems unlikely, but sometimes we might be adding zero
1573 : * values in multiple separate elements. The talloc zero has
1574 : * already set the expected values = NULL, num_values = 0.
1575 : */
1576 0 : *el = _el;
1577 0 : return LDB_SUCCESS;
1578 : }
1579 :
1580 9 : _el->values = talloc_array(_el, struct ldb_val, val_count);
1581 9 : if (_el->values == NULL) {
1582 0 : talloc_free(_el);
1583 0 : return LDB_ERR_OPERATIONS_ERROR;
1584 : }
1585 9 : _el->num_values = val_count;
1586 :
1587 9 : v = _el->values;
1588 :
1589 36 : for (i = 0; i < msg->num_elements; i++) {
1590 27 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
1591 18 : const struct ldb_message_element *tmp_el = &msg->elements[i];
1592 28 : if ((operation == LDB_MODIFY) &&
1593 18 : (LDB_FLAG_MOD_TYPE(tmp_el->flags)
1594 : == LDB_FLAG_MOD_DELETE)) {
1595 0 : continue;
1596 : }
1597 18 : if (tmp_el->values == NULL || tmp_el->num_values == 0) {
1598 0 : continue;
1599 : }
1600 28 : memcpy(v,
1601 18 : tmp_el->values,
1602 18 : tmp_el->num_values * sizeof(*v));
1603 18 : v += tmp_el->num_values;
1604 : }
1605 : }
1606 :
1607 9 : *el = _el;
1608 9 : return LDB_SUCCESS;
1609 : }
1610 :
1611 :
1612 : /*
1613 : * Get the value of a single-valued attribute from an ADDed message. 'val' will only live as
1614 : * long as 'msg' and 'original_val' do, and must not be freed.
1615 : */
1616 0 : int dsdb_msg_add_get_single_value(const struct ldb_message *msg,
1617 : const char *attr_name,
1618 : const struct ldb_val **val)
1619 : {
1620 0 : const struct ldb_message_element *el = NULL;
1621 :
1622 : /*
1623 : * The ldb_msg_normalize() call in ldb_request() ensures that
1624 : * there is at most one message element for each
1625 : * attribute. Thus, we don't need a loop to deal with an
1626 : * LDB_ADD.
1627 : */
1628 0 : el = ldb_msg_find_element(msg, attr_name);
1629 0 : if (el == NULL) {
1630 0 : *val = NULL;
1631 0 : return LDB_SUCCESS;
1632 : }
1633 0 : if (el->num_values != 1) {
1634 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1635 : }
1636 :
1637 0 : *val = &el->values[0];
1638 0 : return LDB_SUCCESS;
1639 : }
1640 :
1641 : /*
1642 : * Get the value of a single-valued attribute after processing a
1643 : * message. 'operation' is either LDB_ADD or LDB_MODIFY. 'val' will only live as
1644 : * long as 'msg' and 'original_val' do, and must not be freed.
1645 : */
1646 1247 : int dsdb_msg_get_single_value(const struct ldb_message *msg,
1647 : const char *attr_name,
1648 : const struct ldb_val *original_val,
1649 : const struct ldb_val **val,
1650 : enum ldb_request_type operation)
1651 : {
1652 : unsigned idx;
1653 :
1654 1247 : *val = NULL;
1655 :
1656 1247 : if (operation == LDB_ADD) {
1657 0 : if (original_val != NULL) {
1658 : /* This is an error on the caller's part. */
1659 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1660 : }
1661 0 : return dsdb_msg_add_get_single_value(msg, attr_name, val);
1662 : }
1663 :
1664 1247 : SMB_ASSERT(operation == LDB_MODIFY);
1665 :
1666 1247 : *val = original_val;
1667 :
1668 2821 : for (idx = 0; idx < msg->num_elements; ++idx) {
1669 1574 : const struct ldb_message_element *el = &msg->elements[idx];
1670 :
1671 1574 : if (ldb_attr_cmp(el->name, attr_name) != 0) {
1672 1496 : continue;
1673 : }
1674 :
1675 78 : switch (el->flags & LDB_FLAG_MOD_MASK) {
1676 0 : case LDB_FLAG_MOD_ADD:
1677 0 : if (el->num_values != 1) {
1678 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1679 : }
1680 0 : if (*val != NULL) {
1681 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1682 : }
1683 :
1684 0 : *val = &el->values[0];
1685 :
1686 0 : break;
1687 :
1688 78 : case LDB_FLAG_MOD_REPLACE:
1689 78 : if (el->num_values > 1) {
1690 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1691 : }
1692 :
1693 78 : *val = el->num_values ? &el->values[0] : NULL;
1694 :
1695 78 : break;
1696 :
1697 0 : case LDB_FLAG_MOD_DELETE:
1698 0 : if (el->num_values > 1) {
1699 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1700 : }
1701 :
1702 : /*
1703 : * If a value was specified for the delete, we don't
1704 : * bother checking it matches the value we currently
1705 : * have. Any mismatch will be caught later (e.g. in
1706 : * ldb_kv_modify_internal).
1707 : */
1708 :
1709 0 : *val = NULL;
1710 :
1711 0 : break;
1712 : }
1713 : }
1714 :
1715 1247 : return LDB_SUCCESS;
1716 : }
1717 :
1718 : /*
1719 : * This function determines the (last) structural or 88 object class of a passed
1720 : * "objectClass" attribute - per MS-ADTS 3.1.1.1.4 this is the last value.
1721 : * Without schema this does not work and hence NULL is returned.
1722 : */
1723 5206996 : const struct dsdb_class *dsdb_get_last_structural_class(const struct dsdb_schema *schema,
1724 : const struct ldb_message_element *element)
1725 : {
1726 : const struct dsdb_class *last_class;
1727 :
1728 5206996 : if (schema == NULL) {
1729 0 : return NULL;
1730 : }
1731 :
1732 5206996 : if (element->num_values == 0) {
1733 0 : return NULL;
1734 : }
1735 :
1736 5206996 : last_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema,
1737 5206996 : &element->values[element->num_values-1]);
1738 5206996 : if (last_class == NULL) {
1739 0 : return NULL;
1740 : }
1741 5206996 : if (last_class->objectClassCategory > 1) {
1742 3 : return NULL;
1743 : }
1744 :
1745 5206993 : return last_class;
1746 : }
1747 :
1748 3886353 : const struct dsdb_class *dsdb_get_structural_oc_from_msg(const struct dsdb_schema *schema,
1749 : const struct ldb_message *msg)
1750 : {
1751 : struct ldb_message_element *oc_el;
1752 :
1753 3886353 : oc_el = ldb_msg_find_element(msg, "objectClass");
1754 3886353 : if (!oc_el) {
1755 0 : return NULL;
1756 : }
1757 :
1758 3886353 : return dsdb_get_last_structural_class(schema, oc_el);
1759 : }
1760 :
1761 : /*
1762 : Get the parent class of an objectclass, or NULL if none exists.
1763 : */
1764 0 : const struct dsdb_class *dsdb_get_parent_class(const struct dsdb_schema *schema,
1765 : const struct dsdb_class *objectclass)
1766 : {
1767 0 : if (ldb_attr_cmp(objectclass->lDAPDisplayName, "top") == 0) {
1768 0 : return NULL;
1769 : }
1770 :
1771 0 : if (objectclass->subClassOf == NULL) {
1772 0 : return NULL;
1773 : }
1774 :
1775 0 : return dsdb_class_by_lDAPDisplayName(schema, objectclass->subClassOf);
1776 : }
1777 :
1778 : /*
1779 : Return true if 'struct_objectclass' is a subclass of 'other_objectclass'. The
1780 : two objectclasses must originate from the same schema, to allow for
1781 : pointer-based identity comparison.
1782 : */
1783 153 : bool dsdb_is_subclass_of(const struct dsdb_schema *schema,
1784 : const struct dsdb_class *struct_objectclass,
1785 : const struct dsdb_class *other_objectclass)
1786 : {
1787 250 : while (struct_objectclass != NULL) {
1788 : /* Pointer comparison can be used due to the same schema str. */
1789 153 : if (struct_objectclass == other_objectclass) {
1790 153 : return true;
1791 : }
1792 :
1793 0 : struct_objectclass = dsdb_get_parent_class(schema, struct_objectclass);
1794 : }
1795 :
1796 0 : return false;
1797 : }
1798 :
1799 : /* Fix the DN so that the relative attribute names are in upper case so that the DN:
1800 : cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
1801 : CN=Adminstrator,CN=users,DC=samba,DC=example,DC=com
1802 : */
1803 0 : int dsdb_fix_dn_rdncase(struct ldb_context *ldb, struct ldb_dn *dn)
1804 : {
1805 : int i, ret;
1806 : char *upper_rdn_attr;
1807 :
1808 0 : for (i=0; i < ldb_dn_get_comp_num(dn); i++) {
1809 : /* We need the attribute name in upper case */
1810 0 : upper_rdn_attr = strupper_talloc(dn,
1811 : ldb_dn_get_component_name(dn, i));
1812 0 : if (!upper_rdn_attr) {
1813 0 : return ldb_oom(ldb);
1814 : }
1815 0 : ret = ldb_dn_set_component(dn, i, upper_rdn_attr,
1816 0 : *ldb_dn_get_component_val(dn, i));
1817 0 : talloc_free(upper_rdn_attr);
1818 0 : if (ret != LDB_SUCCESS) {
1819 0 : return ret;
1820 : }
1821 : }
1822 0 : return LDB_SUCCESS;
1823 : }
1824 :
1825 : /**
1826 : * Make most specific objectCategory for the objectClass of passed object
1827 : * NOTE: In this implementation we count that it is called on already
1828 : * verified objectClass attribute value. See objectclass.c thorough
1829 : * implementation for all the magic that involves
1830 : *
1831 : * @param ldb ldb context
1832 : * @param schema cached schema for ldb. We may get it, but it is very time consuming.
1833 : * Hence leave the responsibility to the caller.
1834 : * @param obj AD object to determint objectCategory for
1835 : * @param mem_ctx Memory context - usually it is obj actually
1836 : * @param pobjectcategory location to store found objectCategory
1837 : *
1838 : * @return LDB_SUCCESS or error including out of memory error
1839 : */
1840 274 : int dsdb_make_object_category(struct ldb_context *ldb, const struct dsdb_schema *schema,
1841 : const struct ldb_message *obj,
1842 : TALLOC_CTX *mem_ctx, const char **pobjectcategory)
1843 : {
1844 : const struct dsdb_class *objectclass;
1845 : struct ldb_message_element *objectclass_element;
1846 : struct dsdb_extended_dn_store_format *dn_format;
1847 :
1848 274 : objectclass_element = ldb_msg_find_element(obj, "objectClass");
1849 274 : if (!objectclass_element) {
1850 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, no objectclass specified!",
1851 0 : ldb_dn_get_linearized(obj->dn));
1852 0 : return LDB_ERR_OBJECT_CLASS_VIOLATION;
1853 : }
1854 274 : if (objectclass_element->num_values == 0) {
1855 0 : ldb_asprintf_errstring(ldb, "dsdb: Cannot add %s, at least one (structural) objectclass has to be specified!",
1856 0 : ldb_dn_get_linearized(obj->dn));
1857 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
1858 : }
1859 :
1860 : /*
1861 : * Get the new top-most structural object class and check for
1862 : * unrelated structural classes
1863 : */
1864 274 : objectclass = dsdb_get_last_structural_class(schema,
1865 : objectclass_element);
1866 274 : if (objectclass == NULL) {
1867 0 : ldb_asprintf_errstring(ldb,
1868 : "Failed to find a structural class for %s",
1869 0 : ldb_dn_get_linearized(obj->dn));
1870 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
1871 : }
1872 :
1873 274 : dn_format = talloc_get_type(ldb_get_opaque(ldb, DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME),
1874 : struct dsdb_extended_dn_store_format);
1875 274 : if (dn_format && dn_format->store_extended_dn_in_ldb == false) {
1876 : /* Strip off extended components */
1877 0 : struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
1878 0 : objectclass->defaultObjectCategory);
1879 0 : *pobjectcategory = ldb_dn_alloc_linearized(mem_ctx, dn);
1880 0 : talloc_free(dn);
1881 : } else {
1882 274 : *pobjectcategory = talloc_strdup(mem_ctx, objectclass->defaultObjectCategory);
1883 : }
1884 :
1885 274 : if (*pobjectcategory == NULL) {
1886 0 : return ldb_oom(ldb);
1887 : }
1888 :
1889 274 : return LDB_SUCCESS;
1890 : }
|