1 /*
2    Unix SMB/CIFS mplementation.
3    DSDB schema header
4 
5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #include "includes.h"
24 #include "dsdb/samdb/samdb.h"
25 #include "dsdb/common/util.h"
26 #include <ldb_errors.h>
27 #include "../lib/util/dlinklist.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_drsuapi.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "param/param.h"
32 #include <ldb_module.h>
33 #include "../lib/util/asn1.h"
34 
35 
dsdb_new_schema(TALLOC_CTX * mem_ctx)36 struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx)
37 {
38 	struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema);
39 	if (!schema) {
40 		return NULL;
41 	}
42 
43 	return schema;
44 }
45 
dsdb_schema_copy_shallow(TALLOC_CTX * mem_ctx,struct ldb_context * ldb,const struct dsdb_schema * schema)46 struct dsdb_schema *dsdb_schema_copy_shallow(TALLOC_CTX *mem_ctx,
47 					     struct ldb_context *ldb,
48 					     const struct dsdb_schema *schema)
49 {
50 	int ret;
51 	struct dsdb_class *cls;
52 	struct dsdb_attribute *attr;
53 	struct dsdb_schema *schema_copy;
54 
55 	schema_copy = dsdb_new_schema(mem_ctx);
56 	if (!schema_copy) {
57 		return NULL;
58 	}
59 
60 	/* copy prexiMap & schemaInfo */
61 	schema_copy->prefixmap = dsdb_schema_pfm_copy_shallow(schema_copy,
62 							      schema->prefixmap);
63 	if (!schema_copy->prefixmap) {
64 		goto failed;
65 	}
66 
67 	schema_copy->schema_info = talloc(schema_copy, struct dsdb_schema_info);
68 	if (!schema_copy->schema_info) {
69 		goto failed;
70 	}
71 	*schema_copy->schema_info = *schema->schema_info;
72 
73 	/* copy classes and attributes*/
74 	for (cls = schema->classes; cls; cls = cls->next) {
75 		struct dsdb_class *class_copy = talloc_memdup(schema_copy,
76 							      cls, sizeof(*cls));
77 		if (!class_copy) {
78 			goto failed;
79 		}
80 		DLIST_ADD(schema_copy->classes, class_copy);
81 	}
82 	schema_copy->num_classes = schema->num_classes;
83 
84 	for (attr = schema->attributes; attr; attr = attr->next) {
85 		struct dsdb_attribute *a_copy = talloc_memdup(schema_copy,
86 							      attr, sizeof(*attr));
87 		if (!a_copy) {
88 			goto failed;
89 		}
90 		DLIST_ADD(schema_copy->attributes, a_copy);
91 	}
92 	schema_copy->num_attributes = schema->num_attributes;
93 
94 	/* rebuild indexes */
95 	ret = dsdb_setup_sorted_accessors(ldb, schema_copy);
96 	if (ret != LDB_SUCCESS) {
97 		goto failed;
98 	}
99 
100 	/* leave reload_seq_number = 0 so it will be refresh ASAP */
101 
102 	return schema_copy;
103 
104 failed:
105 	talloc_free(schema_copy);
106 	return NULL;
107 }
108 
109 
dsdb_load_prefixmap_from_drsuapi(struct dsdb_schema * schema,const struct drsuapi_DsReplicaOIDMapping_Ctr * ctr)110 WERROR dsdb_load_prefixmap_from_drsuapi(struct dsdb_schema *schema,
111 					const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
112 {
113 	WERROR werr;
114 	struct dsdb_schema_info *schema_info = NULL;
115 	struct dsdb_schema_prefixmap *pfm = NULL;
116 
117 	werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, schema, &pfm, &schema_info);
118 	W_ERROR_NOT_OK_RETURN(werr);
119 
120 	/* set loaded prefixMap */
121 	talloc_free(schema->prefixmap);
122 	schema->prefixmap = pfm;
123 
124 	talloc_free(schema->schema_info);
125 	schema->schema_info = schema_info;
126 
127 	return WERR_OK;
128 }
129 
_dsdb_prefixmap_from_ldb_val(const struct ldb_val * pfm_ldb_val,TALLOC_CTX * mem_ctx,struct dsdb_schema_prefixmap ** _pfm)130 static WERROR _dsdb_prefixmap_from_ldb_val(const struct ldb_val *pfm_ldb_val,
131 					   TALLOC_CTX *mem_ctx,
132 					   struct dsdb_schema_prefixmap **_pfm)
133 {
134 	WERROR werr;
135 	enum ndr_err_code ndr_err;
136 	struct prefixMapBlob pfm_blob;
137 
138 	TALLOC_CTX *temp_ctx = talloc_new(mem_ctx);
139 	W_ERROR_HAVE_NO_MEMORY(temp_ctx);
140 
141 	ndr_err = ndr_pull_struct_blob(pfm_ldb_val, temp_ctx,
142 				&pfm_blob,
143 				(ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
144 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
145 		NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
146 		DEBUG(0,("_dsdb_prefixmap_from_ldb_val: Failed to parse prefixmap of length %u: %s\n",
147 			 (unsigned int)pfm_ldb_val->length, ndr_map_error2string(ndr_err)));
148 		talloc_free(temp_ctx);
149 		return ntstatus_to_werror(nt_status);
150 	}
151 
152 	if (pfm_blob.version != PREFIX_MAP_VERSION_DSDB) {
153 		DEBUG(0,("_dsdb_prefixmap_from_ldb_val: pfm_blob->version %u incorrect\n", (unsigned int)pfm_blob.version));
154 		talloc_free(temp_ctx);
155 		return WERR_VERSION_PARSE_ERROR;
156 	}
157 
158 	/* call the drsuapi version */
159 	werr = dsdb_schema_pfm_from_drsuapi_pfm(&pfm_blob.ctr.dsdb, false, mem_ctx, _pfm, NULL);
160 	if (!W_ERROR_IS_OK(werr)) {
161 		DEBUG(0, (__location__ " dsdb_schema_pfm_from_drsuapi_pfm failed: %s\n", win_errstr(werr)));
162 		talloc_free(temp_ctx);
163 		return werr;
164 	}
165 
166 	talloc_free(temp_ctx);
167 
168 	return werr;
169 }
170 
dsdb_load_oid_mappings_ldb(struct dsdb_schema * schema,const struct ldb_val * prefixMap,const struct ldb_val * schemaInfo)171 WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
172 				  const struct ldb_val *prefixMap,
173 				  const struct ldb_val *schemaInfo)
174 {
175 	WERROR werr;
176 	struct dsdb_schema_info *schema_info = NULL;
177 	struct dsdb_schema_prefixmap *pfm = NULL;
178 	TALLOC_CTX *mem_ctx;
179 
180 	/* verify schemaInfo blob is valid one */
181 	if (!dsdb_schema_info_blob_is_valid(schemaInfo)) {
182 		DEBUG(0,(__location__": dsdb_schema_info_blob_is_valid() failed.\n"));
183 	        return WERR_INVALID_PARAMETER;
184 	}
185 
186 	mem_ctx = talloc_new(schema);
187 	W_ERROR_HAVE_NO_MEMORY(mem_ctx);
188 
189 	/* fetch prefixMap */
190 	werr = _dsdb_prefixmap_from_ldb_val(prefixMap,
191 					    mem_ctx, &pfm);
192 	if (!W_ERROR_IS_OK(werr)) {
193 		DEBUG(0, (__location__ " _dsdb_prefixmap_from_ldb_val failed: %s\n", win_errstr(werr)));
194 		talloc_free(mem_ctx);
195 		return werr;
196 	}
197 
198 	/* decode schema_info */
199 	werr = dsdb_schema_info_from_blob(schemaInfo, mem_ctx, &schema_info);
200 	if (!W_ERROR_IS_OK(werr)) {
201 		DEBUG(0, (__location__ " dsdb_schema_info_from_blob failed: %s\n", win_errstr(werr)));
202 		talloc_free(mem_ctx);
203 		return werr;
204 	}
205 
206 	/* store prefixMap and schema_info into cached Schema */
207 	talloc_free(schema->prefixmap);
208 	schema->prefixmap = talloc_steal(schema, pfm);
209 
210 	talloc_free(schema->schema_info);
211 	schema->schema_info = talloc_steal(schema, schema_info);
212 
213 	/* clean up locally allocated mem */
214 	talloc_free(mem_ctx);
215 
216 	return WERR_OK;
217 }
218 
dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema * schema,bool include_schema_info,TALLOC_CTX * mem_ctx,struct drsuapi_DsReplicaOIDMapping_Ctr ** _ctr)219 WERROR dsdb_get_oid_mappings_drsuapi(const struct dsdb_schema *schema,
220 				     bool include_schema_info,
221 				     TALLOC_CTX *mem_ctx,
222 				     struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
223 {
224 	return dsdb_drsuapi_pfm_from_schema_pfm(schema->prefixmap,
225 						include_schema_info ? schema->schema_info : NULL,
226 						mem_ctx, _ctr);
227 }
228 
dsdb_get_drsuapi_prefixmap_as_blob(const struct drsuapi_DsReplicaOIDMapping_Ctr * ctr,TALLOC_CTX * mem_ctx,struct ldb_val * prefixMap)229 WERROR dsdb_get_drsuapi_prefixmap_as_blob(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
230 					  TALLOC_CTX *mem_ctx,
231 					  struct ldb_val *prefixMap)
232 {
233 	struct prefixMapBlob pfm;
234 	enum ndr_err_code ndr_err;
235 	pfm.version	= PREFIX_MAP_VERSION_DSDB;
236 	pfm.reserved	= 0;
237 	pfm.ctr.dsdb	= *ctr;
238 
239 	ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, &pfm,
240 					(ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
241 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242 		NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
243 		return ntstatus_to_werror(nt_status);
244 	}
245 	return WERR_OK;
246 }
247 
dsdb_get_oid_mappings_ldb(const struct dsdb_schema * schema,TALLOC_CTX * mem_ctx,struct ldb_val * prefixMap,struct ldb_val * schemaInfo)248 WERROR dsdb_get_oid_mappings_ldb(const struct dsdb_schema *schema,
249 				 TALLOC_CTX *mem_ctx,
250 				 struct ldb_val *prefixMap,
251 				 struct ldb_val *schemaInfo)
252 {
253 	WERROR status;
254 	struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
255 
256 	status = dsdb_get_oid_mappings_drsuapi(schema, false, mem_ctx, &ctr);
257 	W_ERROR_NOT_OK_RETURN(status);
258 
259 	status = dsdb_get_drsuapi_prefixmap_as_blob(ctr, mem_ctx, prefixMap);
260 	talloc_free(ctr);
261 	W_ERROR_NOT_OK_RETURN(status);
262 
263 	status = dsdb_blob_from_schema_info(schema->schema_info, mem_ctx, schemaInfo);
264 	W_ERROR_NOT_OK_RETURN(status);
265 
266 	return WERR_OK;
267 }
268 
269 
270 /*
271  * this function is called from within a ldb transaction from the schema_fsmo module
272  */
dsdb_create_prefix_mapping(struct ldb_context * ldb,struct dsdb_schema * schema,const char * full_oid)273 WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
274 {
275 	WERROR status;
276 	uint32_t attid;
277 	TALLOC_CTX *mem_ctx;
278 	struct dsdb_schema_prefixmap *pfm;
279 	struct dsdb_schema_prefixmap *orig_pfm = NULL;
280 
281 	mem_ctx = talloc_new(ldb);
282 	W_ERROR_HAVE_NO_MEMORY(mem_ctx);
283 
284 	/* Read prefixes from disk*/
285 	status = dsdb_read_prefixes_from_ldb(ldb, mem_ctx, &pfm);
286 	if (!W_ERROR_IS_OK(status)) {
287 		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb: %s\n",
288 			win_errstr(status)));
289 		talloc_free(mem_ctx);
290 		return status;
291 	}
292 
293 	/* Check if there is a prefix for the oid in the prefixes array*/
294 	status = dsdb_schema_pfm_find_oid(pfm, full_oid, NULL);
295 	if (W_ERROR_IS_OK(status)) {
296 		/* prefix found*/
297 		talloc_free(mem_ctx);
298 		return status;
299 	} else if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
300 		/* error */
301 		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_find_prefix_for_oid: %s\n",
302 			win_errstr(status)));
303 		talloc_free(mem_ctx);
304 		return status;
305 	}
306 
307 	/* Create the new mapping for the prefix of full_oid */
308 	status = dsdb_schema_pfm_make_attid(pfm, full_oid, &attid);
309 	if (!W_ERROR_IS_OK(status)) {
310 		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_schema_pfm_make_attid: %s\n",
311 			win_errstr(status)));
312 		talloc_free(mem_ctx);
313 		return status;
314 	}
315 
316 	/*
317 	 * We temporary replcate schema->prefixmap.
318 	 */
319 	orig_pfm = schema->prefixmap;
320 	schema->prefixmap = pfm;
321 
322 	/* Update prefixMap in ldb*/
323 	status = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, ldb, schema);
324 	if (!W_ERROR_IS_OK(status)) {
325 		DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb: %s\n",
326 			win_errstr(status)));
327 		talloc_free(mem_ctx);
328 		return status;
329 	}
330 
331 	DEBUG(2,(__location__ " Added prefixMap %s - now have %u prefixes\n",
332 		 full_oid, schema->prefixmap->length));
333 
334 	/*
335 	 * We restore the original prefix map.
336 	 *
337 	 * The next schema reload should get an updated prefix map!
338 	 */
339 	schema->prefixmap = orig_pfm;
340 
341 	talloc_free(mem_ctx);
342 	return status;
343 }
344 
345 
dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX * mem_ctx,struct ldb_context * ldb,const struct dsdb_schema * schema)346 WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
347 					      const struct dsdb_schema *schema)
348 {
349 	WERROR status;
350 	int ldb_ret;
351 	struct ldb_message *msg;
352 	struct ldb_dn *schema_dn;
353 	struct prefixMapBlob pfm_blob;
354 	struct ldb_val ndr_blob;
355 	enum ndr_err_code ndr_err;
356 	TALLOC_CTX *temp_ctx;
357 	struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
358 
359 	schema_dn = ldb_get_schema_basedn(ldb);
360 	if (!schema_dn) {
361 		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
362 		return WERR_FOOBAR;
363 	}
364 
365 	temp_ctx = talloc_new(mem_ctx);
366 	W_ERROR_HAVE_NO_MEMORY(temp_ctx);
367 
368 	/* convert schema_prefixMap to prefixMap blob */
369 	status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr);
370 	if (!W_ERROR_IS_OK(status)) {
371 		talloc_free(temp_ctx);
372 		return status;
373 	}
374 
375 	pfm_blob.version	= PREFIX_MAP_VERSION_DSDB;
376 	pfm_blob.ctr.dsdb	= *ctr;
377 
378 	ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx,
379 				       &pfm_blob,
380 				       (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
381 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
382 		talloc_free(temp_ctx);
383 		return WERR_FOOBAR;
384 	}
385 
386 	/* write serialized prefixMap into LDB */
387 	msg = ldb_msg_new(temp_ctx);
388 	if (!msg) {
389 		talloc_free(temp_ctx);
390 		return WERR_NOT_ENOUGH_MEMORY;
391 	}
392 
393 	msg->dn = schema_dn;
394 	ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
395 	if (ldb_ret != 0) {
396 		talloc_free(temp_ctx);
397 		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));
398 		return WERR_NOT_ENOUGH_MEMORY;
399  	}
400 
401 	ldb_ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM);
402 
403 	talloc_free(temp_ctx);
404 
405 	if (ldb_ret != 0) {
406 		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: dsdb_replace failed\n"));
407 		return WERR_FOOBAR;
408  	}
409 
410 	return WERR_OK;
411 }
412 
dsdb_read_prefixes_from_ldb(struct ldb_context * ldb,TALLOC_CTX * mem_ctx,struct dsdb_schema_prefixmap ** _pfm)413 WERROR dsdb_read_prefixes_from_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
414 {
415 	WERROR werr;
416 	int ldb_ret;
417 	const struct ldb_val *prefix_val;
418 	struct ldb_dn *schema_dn;
419 	struct ldb_result *schema_res = NULL;
420 	static const char *schema_attrs[] = {
421 		"prefixMap",
422 		NULL
423 	};
424 
425 	schema_dn = ldb_get_schema_basedn(ldb);
426 	if (!schema_dn) {
427 		DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
428 		return WERR_FOOBAR;
429 	}
430 
431 	ldb_ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
432 	if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
433 		DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
434 		talloc_free(schema_res);
435 		return WERR_FOOBAR;
436 	} else if (ldb_ret != LDB_SUCCESS) {
437 		DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
438 		talloc_free(schema_res);
439 		return WERR_FOOBAR;
440 	}
441 
442 	prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
443 	if (!prefix_val) {
444 		DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
445 		talloc_free(schema_res);
446 		return WERR_FOOBAR;
447 	}
448 
449 	werr = _dsdb_prefixmap_from_ldb_val(prefix_val,
450 					    mem_ctx,
451 					    _pfm);
452 	talloc_free(schema_res);
453 	W_ERROR_NOT_OK_RETURN(werr);
454 
455 	return WERR_OK;
456 }
457 
458 /*
459   this will be replaced with something that looks at the right part of
460   the schema once we know where unique indexing information is hidden
461  */
dsdb_schema_unique_attribute(const char * attr)462 static bool dsdb_schema_unique_attribute(const char *attr)
463 {
464 	const char *attrs[] = { "objectGUID", NULL };
465 	unsigned int i;
466 	for (i=0;attrs[i];i++) {
467 		if (ldb_attr_cmp(attr, attrs[i]) == 0) {
468 			return true;
469 		}
470 	}
471 	return false;
472 }
473 
474 
475 /*
476   setup the ldb_schema_attribute field for a dsdb_attribute
477  */
dsdb_schema_setup_ldb_schema_attribute(struct ldb_context * ldb,struct dsdb_attribute * attr)478 static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb,
479 						  struct dsdb_attribute *attr)
480 {
481 	const char *syntax = attr->syntax->ldb_syntax;
482 	const struct ldb_schema_syntax *s;
483 	struct ldb_schema_attribute *a;
484 
485 	if (!syntax) {
486 		syntax = attr->syntax->ldap_oid;
487 	}
488 
489 	s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
490 	if (s == NULL) {
491 		s = ldb_samba_syntax_by_name(ldb, syntax);
492 	}
493 	if (s == NULL) {
494 		s = ldb_standard_syntax_by_name(ldb, syntax);
495 	}
496 
497 	if (s == NULL) {
498 		return ldb_operr(ldb);
499 	}
500 
501 	attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
502 	if (attr->ldb_schema_attribute == NULL) {
503 		return ldb_oom(ldb);
504 	}
505 
506 	a->name = attr->lDAPDisplayName;
507 	a->flags = 0;
508 	a->syntax = s;
509 
510 	if (dsdb_schema_unique_attribute(a->name)) {
511 		a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
512 	}
513 	if (attr->isSingleValued) {
514 		a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
515 	}
516 
517 	if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
518 		a->flags |= LDB_ATTR_FLAG_INDEXED;
519 	}
520 
521 
522 	return LDB_SUCCESS;
523 }
524 
525 
526 #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
527 	const struct ldb_val *get_string_val = ldb_msg_find_ldb_val(msg, attr); \
528 	if (get_string_val == NULL) { \
529 		if (strict) {					  \
530 			d_printf("%s: %s == NULL in %s\n", __location__, attr, ldb_dn_get_linearized(msg->dn)); \
531 			return WERR_INVALID_PARAMETER;			\
532 		} else {						\
533 			(p)->elem = NULL;				\
534 		}							\
535 	} else {							\
536 		(p)->elem = talloc_strndup(mem_ctx,			\
537 					   (const char *)get_string_val->data, \
538 					   get_string_val->length); \
539 		if (!(p)->elem) {					\
540 			d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
541 			return WERR_NOT_ENOUGH_MEMORY;				\
542 		}							\
543 	}								\
544 } while (0)
545 
546 #define GET_STRING_LIST_LDB(msg, attr, mem_ctx, p, elem) do {	\
547 	int get_string_list_counter;					\
548 	struct ldb_message_element *get_string_list_el = ldb_msg_find_element(msg, attr); \
549 	/* We may get empty attributes over the replication channel */	\
550 	if (get_string_list_el == NULL || get_string_list_el->num_values == 0) {				\
551 		(p)->elem = NULL;					\
552 		break;							\
553 	}								\
554 	(p)->elem = talloc_array(mem_ctx, const char *, get_string_list_el->num_values + 1); \
555         for (get_string_list_counter=0;					\
556 	     get_string_list_counter < get_string_list_el->num_values;	\
557 	     get_string_list_counter++) {				\
558 		(p)->elem[get_string_list_counter] = talloc_strndup((p)->elem, \
559 								    (const char *)get_string_list_el->values[get_string_list_counter].data, \
560 								    get_string_list_el->values[get_string_list_counter].length); \
561 		if (!(p)->elem[get_string_list_counter]) {		\
562 			d_printf("%s: talloc_strndup failed for %s\n", __location__, attr); \
563 			return WERR_NOT_ENOUGH_MEMORY;				\
564 		}							\
565 		(p)->elem[get_string_list_counter+1] = NULL;		\
566 	}								\
567 	talloc_steal(mem_ctx, (p)->elem);				\
568 } while (0)
569 
570 #define GET_BOOL_LDB(msg, attr, p, elem, strict) do { \
571 	const char *str; \
572 	str = ldb_msg_find_attr_as_string(msg, attr, NULL);\
573 	if (str == NULL) { \
574 		if (strict) { \
575 			d_printf("%s: %s == NULL\n", __location__, attr); \
576 			return WERR_INVALID_PARAMETER; \
577 		} else { \
578 			(p)->elem = false; \
579 		} \
580 	} else if (strcasecmp("TRUE", str) == 0) { \
581 		(p)->elem = true; \
582 	} else if (strcasecmp("FALSE", str) == 0) { \
583 		(p)->elem = false; \
584 	} else { \
585 		d_printf("%s: %s == %s\n", __location__, attr, str); \
586 		return WERR_INVALID_PARAMETER; \
587 	} \
588 } while (0)
589 
590 #define GET_UINT32_LDB(msg, attr, p, elem) do { \
591 	(p)->elem = ldb_msg_find_attr_as_uint(msg, attr, 0);\
592 } while (0)
593 
594 #define GET_UINT32_PTR_LDB(msg, attr, mem_ctx, p, elem) do {		\
595 	uint64_t _v = ldb_msg_find_attr_as_uint64(msg, attr, UINT64_MAX);\
596 	if (_v == UINT64_MAX) { \
597 		(p)->elem = NULL; \
598 	} else if (_v > UINT32_MAX) { \
599 		d_printf("%s: %s == 0x%llX\n", __location__, \
600 			 attr, (unsigned long long)_v); \
601 		return WERR_INVALID_PARAMETER; \
602 	} else { \
603 		(p)->elem = talloc(mem_ctx, uint32_t); \
604 		if (!(p)->elem) { \
605 			d_printf("%s: talloc failed for %s\n", __location__, attr); \
606 			return WERR_NOT_ENOUGH_MEMORY; \
607 		} \
608 		*(p)->elem = (uint32_t)_v; \
609 	} \
610 } while (0)
611 
612 #define GET_GUID_LDB(msg, attr, p, elem) do { \
613 	(p)->elem = samdb_result_guid(msg, attr);\
614 } while (0)
615 
616 #define GET_BLOB_LDB(msg, attr, mem_ctx, p, elem) do { \
617 	const struct ldb_val *_val;\
618 	_val = ldb_msg_find_ldb_val(msg, attr);\
619 	if (_val) {\
620 		(p)->elem = *_val;\
621 		talloc_steal(mem_ctx, (p)->elem.data);\
622 	} else {\
623 		ZERO_STRUCT((p)->elem);\
624 	}\
625 } while (0)
626 
627 /** Create an dsdb_attribute out of ldb message, attr must be already talloced
628  *
629  * If supplied the attribute will be checked against the prefixmap to
630  * ensure it can be mapped.  However we can't have this attribute
631  * const as dsdb_schema_pfm_attid_from_oid calls
632  * dsdb_schema_pfm_make_attid_impl() which may modify prefixmap in
633  * other situations.
634  */
635 
dsdb_attribute_from_ldb(struct dsdb_schema_prefixmap * prefixmap,struct ldb_message * msg,struct dsdb_attribute * attr)636 WERROR dsdb_attribute_from_ldb(struct dsdb_schema_prefixmap *prefixmap,
637 			       struct ldb_message *msg,
638 			       struct dsdb_attribute *attr)
639 {
640 	WERROR status;
641 	if (attr == NULL) {
642 		DEBUG(0, ("%s: attr is null, it's expected not to be so\n", __location__));
643 		return WERR_INVALID_PARAMETER;
644 	}
645 
646 	GET_STRING_LDB(msg, "cn", attr, attr, cn, false);
647 
648 	/*
649 	 * This allows for the fact that the CN attribute is not
650 	 * replicated over DRS, it is only replicated under the alias
651 	 * 'name'.
652 	 */
653 	if (attr->cn == NULL) {
654 		GET_STRING_LDB(msg, "name", attr, attr, cn, true);
655 	}
656 
657 	GET_STRING_LDB(msg, "lDAPDisplayName", attr, attr, lDAPDisplayName, true);
658 	GET_STRING_LDB(msg, "attributeID", attr, attr, attributeID_oid, true);
659 	if (!prefixmap || prefixmap->length == 0) {
660 		/* set an invalid value */
661 		attr->attributeID_id = DRSUAPI_ATTID_INVALID;
662 	} else {
663 		status = dsdb_schema_pfm_attid_from_oid(prefixmap,
664 							attr->attributeID_oid,
665 							&attr->attributeID_id);
666 		if (!W_ERROR_IS_OK(status)) {
667 			DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
668 				__location__, attr->lDAPDisplayName, attr->attributeID_oid,
669 				win_errstr(status)));
670 			return status;
671 		}
672 	}
673 	/* fetch msDS-IntId to be used in resolving ATTRTYP values */
674 	GET_UINT32_LDB(msg, "msDS-IntId", attr, msDS_IntId);
675 
676 	GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
677 	GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);
678 
679 	GET_GUID_LDB(msg, "attributeSecurityGUID", attr, attributeSecurityGUID);
680 
681 	GET_GUID_LDB(msg, "objectGUID", attr, objectGUID);
682 
683 	GET_UINT32_LDB(msg, "searchFlags", attr, searchFlags);
684 	GET_UINT32_LDB(msg, "systemFlags", attr, systemFlags);
685 	GET_BOOL_LDB(msg, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
686 	GET_UINT32_LDB(msg, "linkID", attr, linkID);
687 
688 	GET_STRING_LDB(msg, "attributeSyntax", attr, attr, attributeSyntax_oid, true);
689 	if (!prefixmap || prefixmap->length == 0) {
690 		/* set an invalid value */
691 		attr->attributeSyntax_id = DRSUAPI_ATTID_INVALID;
692 	} else {
693 		status = dsdb_schema_pfm_attid_from_oid(prefixmap,
694 							attr->attributeSyntax_oid,
695 							&attr->attributeSyntax_id);
696 		if (!W_ERROR_IS_OK(status)) {
697 			DEBUG(0,("%s: '%s': unable to map attributeSyntax_ %s: %s\n",
698 				__location__, attr->lDAPDisplayName, attr->attributeSyntax_oid,
699 				win_errstr(status)));
700 			return status;
701 		}
702 	}
703 	GET_UINT32_LDB(msg, "oMSyntax", attr, oMSyntax);
704 	GET_BLOB_LDB(msg, "oMObjectClass", attr, attr, oMObjectClass);
705 
706 	GET_BOOL_LDB(msg, "isSingleValued", attr, isSingleValued, true);
707 	GET_UINT32_PTR_LDB(msg, "rangeLower", attr, attr, rangeLower);
708 	GET_UINT32_PTR_LDB(msg, "rangeUpper", attr, attr, rangeUpper);
709 	GET_BOOL_LDB(msg, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
710 
711 	GET_UINT32_LDB(msg, "schemaFlagsEx", attr, schemaFlagsEx);
712 	GET_BLOB_LDB(msg, "msDs-Schema-Extensions", attr, attr, msDs_Schema_Extensions);
713 
714 	GET_BOOL_LDB(msg, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
715 	GET_STRING_LDB(msg, "adminDisplayName", attr, attr, adminDisplayName, false);
716 	GET_STRING_LDB(msg, "adminDescription", attr, attr, adminDescription, false);
717 	GET_STRING_LDB(msg, "classDisplayName", attr, attr, classDisplayName, false);
718 	GET_BOOL_LDB(msg, "isEphemeral", attr, isEphemeral, false);
719 	GET_BOOL_LDB(msg, "isDefunct", attr, isDefunct, false);
720 	GET_BOOL_LDB(msg, "systemOnly", attr, systemOnly, false);
721 
722 	return WERR_OK;
723 }
724 
dsdb_set_attribute_from_ldb_dups(struct ldb_context * ldb,struct dsdb_schema * schema,struct ldb_message * msg,bool checkdups)725 WERROR dsdb_set_attribute_from_ldb_dups(struct ldb_context *ldb,
726 					struct dsdb_schema *schema,
727 					struct ldb_message *msg,
728 					bool checkdups)
729 {
730 	WERROR status;
731 	struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute);
732 	if (!attr) {
733 		return WERR_NOT_ENOUGH_MEMORY;
734 	}
735 
736 	status = dsdb_attribute_from_ldb(schema->prefixmap, msg, attr);
737 	if (!W_ERROR_IS_OK(status)) {
738 		return status;
739 	}
740 
741 	attr->syntax = dsdb_syntax_for_attribute(attr);
742 	if (!attr->syntax) {
743 		DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
744 			 attr->lDAPDisplayName));
745 		return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
746 	}
747 
748 	if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
749 		DEBUG(0,(__location__ ": Unknown schema syntax for %s - ldb_syntax: %s, ldap_oid: %s\n",
750 			 attr->lDAPDisplayName,
751 			 attr->syntax->ldb_syntax,
752 			 attr->syntax->ldap_oid));
753 		return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
754 	}
755 
756 	if (checkdups) {
757 		const struct dsdb_attribute *a2;
758 		struct dsdb_attribute **a;
759 		uint32_t i;
760 
761 		a2 = dsdb_attribute_by_attributeID_id(schema,
762 						      attr->attributeID_id);
763 		if (a2 == NULL) {
764 			goto done;
765 		}
766 
767 		i = schema->attributes_to_remove_size;
768 		a = talloc_realloc(schema, schema->attributes_to_remove,
769 				   struct dsdb_attribute *, i + 1);
770 		if (a == NULL) {
771 			return WERR_NOT_ENOUGH_MEMORY;
772 		}
773 		/* Mark the old attribute as to be removed */
774 		a[i] = discard_const_p(struct dsdb_attribute, a2);
775 		schema->attributes_to_remove = a;
776 		schema->attributes_to_remove_size++;
777 	}
778 
779 done:
780 	DLIST_ADD(schema->attributes, attr);
781 	return WERR_OK;
782 }
783 
dsdb_set_attribute_from_ldb(struct ldb_context * ldb,struct dsdb_schema * schema,struct ldb_message * msg)784 WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb,
785 				   struct dsdb_schema *schema,
786 				   struct ldb_message *msg)
787 {
788 	return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, false);
789 }
790 
dsdb_set_class_from_ldb_dups(struct dsdb_schema * schema,struct ldb_message * msg,bool checkdups)791 WERROR dsdb_set_class_from_ldb_dups(struct dsdb_schema *schema,
792 				    struct ldb_message *msg,
793 				    bool checkdups)
794 {
795 	WERROR status;
796 	struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class);
797 	if (!obj) {
798 		return WERR_NOT_ENOUGH_MEMORY;
799 	}
800 	GET_STRING_LDB(msg, "cn", obj, obj, cn, false);
801 
802 	/*
803 	 * This allows for the fact that the CN attribute is not
804 	 * replicated over DRS, it is only replicated under the alias
805 	 * 'name'.
806 	 */
807 	if (obj->cn == NULL) {
808 		GET_STRING_LDB(msg, "name", obj, obj, cn, true);
809 	}
810 
811 	GET_STRING_LDB(msg, "lDAPDisplayName", obj, obj, lDAPDisplayName, true);
812 	GET_STRING_LDB(msg, "governsID", obj, obj, governsID_oid, true);
813 	if (!schema->prefixmap || schema->prefixmap->length == 0) {
814 		/* set an invalid value */
815 		obj->governsID_id = DRSUAPI_ATTID_INVALID;
816 	} else {
817 		status = dsdb_schema_pfm_attid_from_oid(schema->prefixmap,
818 							obj->governsID_oid,
819 							&obj->governsID_id);
820 		if (!W_ERROR_IS_OK(status)) {
821 			DEBUG(0,("%s: '%s': unable to map governsID %s: %s\n",
822 				__location__, obj->lDAPDisplayName, obj->governsID_oid,
823 				win_errstr(status)));
824 			return status;
825 		}
826 	}
827 	GET_GUID_LDB(msg, "schemaIDGUID", obj, schemaIDGUID);
828 	GET_GUID_LDB(msg, "objectGUID", obj, objectGUID);
829 
830 	GET_UINT32_LDB(msg, "objectClassCategory", obj, objectClassCategory);
831 	GET_STRING_LDB(msg, "rDNAttID", obj, obj, rDNAttID, false);
832 	GET_STRING_LDB(msg, "defaultObjectCategory", obj, obj, defaultObjectCategory, true);
833 
834 	GET_STRING_LDB(msg, "subClassOf", obj, obj, subClassOf, true);
835 
836 	GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", obj, obj, systemAuxiliaryClass);
837 	GET_STRING_LIST_LDB(msg, "auxiliaryClass", obj, obj, auxiliaryClass);
838 
839 	GET_STRING_LIST_LDB(msg, "systemMustContain", obj, obj, systemMustContain);
840 	GET_STRING_LIST_LDB(msg, "systemMayContain", obj, obj, systemMayContain);
841 	GET_STRING_LIST_LDB(msg, "mustContain", obj, obj, mustContain);
842 	GET_STRING_LIST_LDB(msg, "mayContain", obj, obj, mayContain);
843 
844 	GET_STRING_LIST_LDB(msg, "systemPossSuperiors", obj, obj, systemPossSuperiors);
845 	GET_STRING_LIST_LDB(msg, "possSuperiors", obj, obj, possSuperiors);
846 
847 	GET_STRING_LDB(msg, "defaultSecurityDescriptor", obj, obj, defaultSecurityDescriptor, false);
848 
849 	GET_UINT32_LDB(msg, "schemaFlagsEx", obj, schemaFlagsEx);
850 	GET_UINT32_LDB(msg, "systemFlags", obj, systemFlags);
851 	GET_BLOB_LDB(msg, "msDs-Schema-Extensions", obj, obj, msDs_Schema_Extensions);
852 
853 	GET_BOOL_LDB(msg, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
854 	GET_STRING_LDB(msg, "adminDisplayName", obj, obj, adminDisplayName, false);
855 	GET_STRING_LDB(msg, "adminDescription", obj, obj, adminDescription, false);
856 	GET_STRING_LDB(msg, "classDisplayName", obj, obj, classDisplayName, false);
857 	GET_BOOL_LDB(msg, "defaultHidingValue", obj, defaultHidingValue, false);
858 	GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false);
859 	GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false);
860 
861 	if (checkdups) {
862 		const struct dsdb_class *c2;
863 		struct dsdb_class **c;
864 		uint32_t i;
865 
866 		c2 = dsdb_class_by_governsID_id(schema, obj->governsID_id);
867 		if (c2 == NULL) {
868 			goto done;
869 		}
870 
871 		i = schema->classes_to_remove_size;
872 		c = talloc_realloc(schema, schema->classes_to_remove,
873 				   struct dsdb_class *, i + 1);
874 		if (c == NULL) {
875 			return WERR_NOT_ENOUGH_MEMORY;
876 		}
877 		/* Mark the old class to be removed */
878 		c[i] = discard_const_p(struct dsdb_class, c2);
879 		schema->classes_to_remove = c;
880 		schema->classes_to_remove_size++;
881 	}
882 
883 done:
884 	DLIST_ADD(schema->classes, obj);
885 	return WERR_OK;
886 }
887 
dsdb_set_class_from_ldb(struct dsdb_schema * schema,struct ldb_message * msg)888 WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema,
889 			       struct ldb_message *msg)
890 {
891 	return dsdb_set_class_from_ldb_dups(schema, msg, false);
892 }
893 
894 #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
895 
896 /*
897  Fill a DSDB schema from the ldb results provided.  This is called
898  directly when a schema must be created with a pre-initialised prefixMap
899 */
900 
dsdb_load_ldb_results_into_schema(TALLOC_CTX * mem_ctx,struct ldb_context * ldb,struct dsdb_schema * schema,struct ldb_result * attrs_class_res,char ** error_string)901 int dsdb_load_ldb_results_into_schema(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
902 				      struct dsdb_schema *schema,
903 				      struct ldb_result *attrs_class_res,
904 				      char **error_string)
905 {
906 	unsigned int i;
907 	WERROR status;
908 
909 	schema->ts_last_change = 0;
910 	for (i=0; i < attrs_class_res->count; i++) {
911 		const char *prefixMap = NULL;
912 		/*
913 		 * attrs_class_res also includes the schema object;
914 		 * we only want to process classes & attributes
915 		 */
916 		prefixMap = ldb_msg_find_attr_as_string(
917 				attrs_class_res->msgs[i],
918 				"prefixMap", NULL);
919 		if (prefixMap != NULL) {
920 			continue;
921 		}
922 
923 		status = dsdb_schema_set_el_from_ldb_msg(ldb, schema,
924 							 attrs_class_res->msgs[i]);
925 		if (!W_ERROR_IS_OK(status)) {
926 			*error_string = talloc_asprintf(mem_ctx,
927 				      "dsdb_load_ldb_results_into_schema: failed to load attribute or class definition: %s:%s",
928 				      ldb_dn_get_linearized(attrs_class_res->msgs[i]->dn),
929 				      win_errstr(status));
930 			DEBUG(0,(__location__ ": %s\n", *error_string));
931 			return LDB_ERR_CONSTRAINT_VIOLATION;
932 		}
933 	}
934 
935 	return LDB_SUCCESS;
936 }
937 
938 /*
939  Create a DSDB schema from the ldb results provided.  This is called
940  directly when the schema is provisioned from an on-disk LDIF file, or
941  from dsdb_schema_from_schema_dn in schema_fsmo
942 */
943 
dsdb_schema_from_ldb_results(TALLOC_CTX * mem_ctx,struct ldb_context * ldb,struct ldb_message * schema_msg,struct ldb_result * attrs_class_res,struct dsdb_schema ** schema_out,char ** error_string)944 int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
945 				 struct ldb_message *schema_msg,
946 				 struct ldb_result *attrs_class_res,
947 				 struct dsdb_schema **schema_out,
948 				 char **error_string)
949 {
950 	WERROR status;
951 	const struct ldb_val *prefix_val;
952 	const struct ldb_val *info_val;
953 	struct ldb_val info_val_default;
954 	struct dsdb_schema *schema;
955 	void *lp_opaque = ldb_get_opaque(ldb, "loadparm");
956 	int ret;
957 
958 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
959 	if (!tmp_ctx) {
960 		dsdb_oom(error_string, mem_ctx);
961 		return ldb_operr(ldb);
962 	}
963 
964 	schema = dsdb_new_schema(tmp_ctx);
965 	if (!schema) {
966 		dsdb_oom(error_string, mem_ctx);
967 		talloc_free(tmp_ctx);
968 		return ldb_operr(ldb);
969 	}
970 
971 	if (lp_opaque) {
972 		struct loadparm_context *lp_ctx = talloc_get_type_abort(lp_opaque, struct loadparm_context);
973 		schema->fsmo.update_allowed = lpcfg_parm_bool(lp_ctx, NULL,
974 							      "dsdb", "schema update allowed",
975 							      false);
976 	}
977 
978 	prefix_val = ldb_msg_find_ldb_val(schema_msg, "prefixMap");
979 	if (!prefix_val) {
980 		*error_string = talloc_asprintf(mem_ctx,
981 						"schema_fsmo_init: no prefixMap attribute found");
982 		DEBUG(0,(__location__ ": %s\n", *error_string));
983 		talloc_free(tmp_ctx);
984 		return LDB_ERR_CONSTRAINT_VIOLATION;
985 	}
986 	info_val = ldb_msg_find_ldb_val(schema_msg, "schemaInfo");
987 	if (!info_val) {
988 		status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
989 		if (!W_ERROR_IS_OK(status)) {
990 			*error_string = talloc_asprintf(mem_ctx,
991 			                                "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s",
992 			                                win_errstr(status));
993 			DEBUG(0,(__location__ ": %s\n", *error_string));
994 			talloc_free(tmp_ctx);
995 			return ldb_operr(ldb);
996 		}
997 		info_val = &info_val_default;
998 	}
999 
1000 	status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
1001 	if (!W_ERROR_IS_OK(status)) {
1002 		*error_string = talloc_asprintf(mem_ctx,
1003 			      "schema_fsmo_init: failed to load oid mappings: %s",
1004 			      win_errstr(status));
1005 		DEBUG(0,(__location__ ": %s\n", *error_string));
1006 		talloc_free(tmp_ctx);
1007 		return LDB_ERR_CONSTRAINT_VIOLATION;
1008 	}
1009 
1010 	ret = dsdb_load_ldb_results_into_schema(mem_ctx, ldb, schema, attrs_class_res, error_string);
1011 	if (ret != LDB_SUCCESS) {
1012 		talloc_free(tmp_ctx);
1013 		return ret;
1014 	}
1015 
1016 	schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_msg, "fSMORoleOwner");
1017 	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb, tmp_ctx), schema->fsmo.master_dn) == 0) {
1018 		schema->fsmo.we_are_master = true;
1019 	} else {
1020 		schema->fsmo.we_are_master = false;
1021 	}
1022 
1023 	DEBUG(5, ("schema_fsmo_init: we are master[%s] updates allowed[%s]\n",
1024 		  (schema->fsmo.we_are_master?"yes":"no"),
1025 		  (schema->fsmo.update_allowed?"yes":"no")));
1026 
1027 	*schema_out = talloc_steal(mem_ctx, schema);
1028 	talloc_free(tmp_ctx);
1029 	return LDB_SUCCESS;
1030 }
1031