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