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