s4/dsdb: msg_idx->dn should be allocated in msg_idx mem context
[Samba.git] / source4 / dsdb / schema / schema_set.c
blob0e04f5b35eb16aaa7074e738f834c9efaf80bd9a
1 /*
2 Unix SMB/CIFS mplementation.
3 DSDB schema header
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
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.
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.
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/>.
23 #include "includes.h"
24 #include "lib/util/dlinklist.h"
25 #include "dsdb/samdb/samdb.h"
26 #include "lib/ldb/include/ldb_module.h"
27 #include "param/param.h"
28 #include "librpc/ndr/libndr.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "lib/util/tsort.h"
33 override the name to attribute handler function
35 const struct ldb_schema_attribute *dsdb_attribute_handler_override(struct ldb_context *ldb,
36 void *private_data,
37 const char *name)
39 struct dsdb_schema *schema = talloc_get_type_abort(private_data, struct dsdb_schema);
40 const struct dsdb_attribute *a = dsdb_attribute_by_lDAPDisplayName(schema, name);
41 if (a == NULL) {
42 /* this will fall back to ldb internal handling */
43 return NULL;
45 return a->ldb_schema_attribute;
48 static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
50 int ret = LDB_SUCCESS;
51 struct ldb_result *res;
52 struct ldb_result *res_idx;
53 struct dsdb_attribute *attr;
54 struct ldb_message *mod_msg;
55 TALLOC_CTX *mem_ctx;
56 struct ldb_message *msg;
57 struct ldb_message *msg_idx;
59 /* setup our own attribute name to schema handler */
60 ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
62 if (!write_attributes) {
63 return ret;
66 mem_ctx = talloc_new(ldb);
67 if (!mem_ctx) {
68 return LDB_ERR_OPERATIONS_ERROR;
71 msg = ldb_msg_new(mem_ctx);
72 if (!msg) {
73 ldb_oom(ldb);
74 goto op_error;
76 msg_idx = ldb_msg_new(mem_ctx);
77 if (!msg_idx) {
78 ldb_oom(ldb);
79 goto op_error;
81 msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
82 if (!msg->dn) {
83 ldb_oom(ldb);
84 goto op_error;
86 msg_idx->dn = ldb_dn_new(msg_idx, ldb, "@INDEXLIST");
87 if (!msg_idx->dn) {
88 ldb_oom(ldb);
89 goto op_error;
92 ret = ldb_msg_add_string(msg_idx, "@IDXONE", "1");
93 if (ret != LDB_SUCCESS) {
94 goto op_error;
97 for (attr = schema->attributes; attr; attr = attr->next) {
98 const char *syntax = attr->syntax->ldb_syntax;
100 if (!syntax) {
101 syntax = attr->syntax->ldap_oid;
104 /* Write out a rough approximation of the schema as an @ATTRIBUTES value, for bootstrapping */
105 if (strcmp(syntax, LDB_SYNTAX_INTEGER) == 0) {
106 ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "INTEGER");
107 } else if (strcmp(syntax, LDB_SYNTAX_DIRECTORY_STRING) == 0) {
108 ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE");
110 if (ret != LDB_SUCCESS) {
111 break;
114 if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
115 ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName);
116 if (ret != LDB_SUCCESS) {
117 break;
122 if (ret != LDB_SUCCESS) {
123 talloc_free(mem_ctx);
124 return ret;
127 /* Try to avoid churning the attributes too much - we only want to do this if they have changed */
128 ret = ldb_search(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn));
129 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
130 ret = ldb_add(ldb, msg);
131 } else if (ret != LDB_SUCCESS) {
132 } else if (res->count != 1) {
133 ret = ldb_add(ldb, msg);
134 } else {
135 ret = LDB_SUCCESS;
136 /* Annoyingly added to our search results */
137 ldb_msg_remove_attr(res->msgs[0], "distinguishedName");
139 mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
140 if (mod_msg->num_elements > 0) {
141 ret = dsdb_replace(ldb, mod_msg, 0);
145 if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS || ret == LDB_ERR_INVALID_DN_SYNTAX) {
146 /* We might be on a read-only DB or LDAP */
147 ret = LDB_SUCCESS;
149 if (ret != LDB_SUCCESS) {
150 talloc_free(mem_ctx);
151 return ret;
154 /* Now write out the indexs, as found in the schema (if they have changed) */
156 ret = ldb_search(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg_idx->dn));
157 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
158 ret = ldb_add(ldb, msg_idx);
159 } else if (ret != LDB_SUCCESS) {
160 } else if (res_idx->count != 1) {
161 ret = ldb_add(ldb, msg_idx);
162 } else {
163 ret = LDB_SUCCESS;
164 /* Annoyingly added to our search results */
165 ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName");
167 mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
168 if (mod_msg->num_elements > 0) {
169 ret = dsdb_replace(ldb, mod_msg, 0);
172 if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS || ret == LDB_ERR_INVALID_DN_SYNTAX) {
173 /* We might be on a read-only DB */
174 ret = LDB_SUCCESS;
176 talloc_free(mem_ctx);
177 return ret;
179 op_error:
180 talloc_free(mem_ctx);
181 return LDB_ERR_OPERATIONS_ERROR;
184 static int uint32_cmp(uint32_t c1, uint32_t c2)
186 if (c1 == c2) return 0;
187 return c1 > c2 ? 1 : -1;
190 static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2)
192 return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName);
194 static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2)
196 return uint32_cmp((*c1)->governsID_id, (*c2)->governsID_id);
198 static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2)
200 return strcasecmp((*c1)->governsID_oid, (*c2)->governsID_oid);
202 static int dsdb_compare_class_by_cn(struct dsdb_class **c1, struct dsdb_class **c2)
204 return strcasecmp((*c1)->cn, (*c2)->cn);
207 static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
209 return strcasecmp((*a1)->lDAPDisplayName, (*a2)->lDAPDisplayName);
211 static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
213 return uint32_cmp((*a1)->attributeID_id, (*a2)->attributeID_id);
215 static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
217 return strcasecmp((*a1)->attributeID_oid, (*a2)->attributeID_oid);
219 static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
221 return uint32_cmp((*a1)->linkID, (*a2)->linkID);
225 * Clean up Classes and Attributes accessor arrays
227 static void dsdb_sorted_accessors_free(struct dsdb_schema *schema)
229 /* free classes accessors */
230 TALLOC_FREE(schema->classes_by_lDAPDisplayName);
231 TALLOC_FREE(schema->classes_by_governsID_id);
232 TALLOC_FREE(schema->classes_by_governsID_oid);
233 TALLOC_FREE(schema->classes_by_cn);
234 /* free attribute accessors */
235 TALLOC_FREE(schema->attributes_by_lDAPDisplayName);
236 TALLOC_FREE(schema->attributes_by_attributeID_id);
237 TALLOC_FREE(schema->attributes_by_msDS_IntId);
238 TALLOC_FREE(schema->attributes_by_attributeID_oid);
239 TALLOC_FREE(schema->attributes_by_linkID);
243 create the sorted accessor arrays for the schema
245 static int dsdb_setup_sorted_accessors(struct ldb_context *ldb,
246 struct dsdb_schema *schema)
248 struct dsdb_class *cur;
249 struct dsdb_attribute *a;
250 unsigned int i;
251 unsigned int num_int_id;
253 /* free all caches */
254 dsdb_sorted_accessors_free(schema);
256 /* count the classes */
257 for (i=0, cur=schema->classes; cur; i++, cur=cur->next) /* noop */ ;
258 schema->num_classes = i;
260 /* setup classes_by_* */
261 schema->classes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_class *, i);
262 schema->classes_by_governsID_id = talloc_array(schema, struct dsdb_class *, i);
263 schema->classes_by_governsID_oid = talloc_array(schema, struct dsdb_class *, i);
264 schema->classes_by_cn = talloc_array(schema, struct dsdb_class *, i);
265 if (schema->classes_by_lDAPDisplayName == NULL ||
266 schema->classes_by_governsID_id == NULL ||
267 schema->classes_by_governsID_oid == NULL ||
268 schema->classes_by_cn == NULL) {
269 goto failed;
272 for (i=0, cur=schema->classes; cur; i++, cur=cur->next) {
273 schema->classes_by_lDAPDisplayName[i] = cur;
274 schema->classes_by_governsID_id[i] = cur;
275 schema->classes_by_governsID_oid[i] = cur;
276 schema->classes_by_cn[i] = cur;
279 /* sort the arrays */
280 TYPESAFE_QSORT(schema->classes_by_lDAPDisplayName, schema->num_classes, dsdb_compare_class_by_lDAPDisplayName);
281 TYPESAFE_QSORT(schema->classes_by_governsID_id, schema->num_classes, dsdb_compare_class_by_governsID_id);
282 TYPESAFE_QSORT(schema->classes_by_governsID_oid, schema->num_classes, dsdb_compare_class_by_governsID_oid);
283 TYPESAFE_QSORT(schema->classes_by_cn, schema->num_classes, dsdb_compare_class_by_cn);
285 /* now build the attribute accessor arrays */
287 /* count the attributes
288 * and attributes with msDS-IntId set */
289 num_int_id = 0;
290 for (i=0, a=schema->attributes; a; i++, a=a->next) {
291 if (a->msDS_IntId != 0) {
292 num_int_id++;
295 schema->num_attributes = i;
296 schema->num_int_id_attr = num_int_id;
298 /* setup attributes_by_* */
299 schema->attributes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_attribute *, i);
300 schema->attributes_by_attributeID_id = talloc_array(schema, struct dsdb_attribute *, i);
301 schema->attributes_by_msDS_IntId = talloc_array(schema,
302 struct dsdb_attribute *, num_int_id);
303 schema->attributes_by_attributeID_oid = talloc_array(schema, struct dsdb_attribute *, i);
304 schema->attributes_by_linkID = talloc_array(schema, struct dsdb_attribute *, i);
305 if (schema->attributes_by_lDAPDisplayName == NULL ||
306 schema->attributes_by_attributeID_id == NULL ||
307 schema->attributes_by_msDS_IntId == NULL ||
308 schema->attributes_by_attributeID_oid == NULL ||
309 schema->attributes_by_linkID == NULL) {
310 goto failed;
313 num_int_id = 0;
314 for (i=0, a=schema->attributes; a; i++, a=a->next) {
315 schema->attributes_by_lDAPDisplayName[i] = a;
316 schema->attributes_by_attributeID_id[i] = a;
317 schema->attributes_by_attributeID_oid[i] = a;
318 schema->attributes_by_linkID[i] = a;
319 /* append attr-by-msDS-IntId values */
320 if (a->msDS_IntId != 0) {
321 schema->attributes_by_msDS_IntId[num_int_id] = a;
322 num_int_id++;
325 SMB_ASSERT(num_int_id == schema->num_int_id_attr);
327 /* sort the arrays */
328 TYPESAFE_QSORT(schema->attributes_by_lDAPDisplayName, schema->num_attributes, dsdb_compare_attribute_by_lDAPDisplayName);
329 TYPESAFE_QSORT(schema->attributes_by_attributeID_id, schema->num_attributes, dsdb_compare_attribute_by_attributeID_id);
330 TYPESAFE_QSORT(schema->attributes_by_msDS_IntId, schema->num_int_id_attr, dsdb_compare_attribute_by_attributeID_id);
331 TYPESAFE_QSORT(schema->attributes_by_attributeID_oid, schema->num_attributes, dsdb_compare_attribute_by_attributeID_oid);
332 TYPESAFE_QSORT(schema->attributes_by_linkID, schema->num_attributes, dsdb_compare_attribute_by_linkID);
334 return LDB_SUCCESS;
336 failed:
337 dsdb_sorted_accessors_free(schema);
338 ldb_oom(ldb);
339 return LDB_ERR_OPERATIONS_ERROR;
342 int dsdb_setup_schema_inversion(struct ldb_context *ldb, struct dsdb_schema *schema)
344 /* Walk the list of schema classes */
346 /* For each subClassOf, add us to subclasses of the parent */
348 /* collect these subclasses into a recursive list of total subclasses, preserving order */
350 /* For each subclass under 'top', write the index from it's
351 * order as an integer in the dsdb_class (for sorting
352 * objectClass lists efficiently) */
354 /* Walk the list of scheam classes */
356 /* Create a 'total possible superiors' on each class */
357 return LDB_SUCCESS;
361 * Attach the schema to an opaque pointer on the ldb, so ldb modules
362 * can find it
365 int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
367 int ret;
369 ret = dsdb_setup_sorted_accessors(ldb, schema);
370 if (ret != LDB_SUCCESS) {
371 return ret;
374 ret = schema_fill_constructed(schema);
375 if (ret != LDB_SUCCESS) {
376 return ret;
379 ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
380 if (ret != LDB_SUCCESS) {
381 return ret;
384 ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", NULL);
385 if (ret != LDB_SUCCESS) {
386 return ret;
389 /* Set the new attributes based on the new schema */
390 ret = dsdb_schema_set_attributes(ldb, schema, true);
391 if (ret != LDB_SUCCESS) {
392 return ret;
395 talloc_steal(ldb, schema);
397 return LDB_SUCCESS;
401 * Global variable to hold one copy of the schema, used to avoid memory bloat
403 static struct dsdb_schema *global_schema;
406 * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
408 int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
409 bool write_attributes)
411 int ret;
412 ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
413 if (ret != LDB_SUCCESS) {
414 return ret;
417 if (talloc_reference(ldb, schema) == NULL) {
418 return LDB_ERR_OPERATIONS_ERROR;
421 ret = dsdb_schema_set_attributes(ldb, schema, write_attributes);
422 if (ret != LDB_SUCCESS) {
423 return ret;
426 return LDB_SUCCESS;
430 * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
432 int dsdb_set_global_schema(struct ldb_context *ldb)
434 int ret;
435 void *use_global_schema = (void *)1;
436 if (!global_schema) {
437 return LDB_SUCCESS;
440 ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", use_global_schema);
441 if (ret != LDB_SUCCESS) {
442 return ret;
445 /* Set the new attributes based on the new schema */
446 ret = dsdb_schema_set_attributes(ldb, global_schema, false /* Don't write attributes, it's expensive */);
447 if (ret == LDB_SUCCESS) {
448 /* Keep a reference to this schema, just incase the original copy is replaced */
449 if (talloc_reference(ldb, global_schema) == NULL) {
450 return LDB_ERR_OPERATIONS_ERROR;
454 return ret;
458 * Find the schema object for this ldb
460 * If reference_ctx is not NULL, then talloc_reference onto that context
463 struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *reference_ctx)
465 const void *p;
466 struct dsdb_schema *schema_out;
467 struct dsdb_schema *schema_in;
468 bool use_global_schema;
470 /* see if we have a cached copy */
471 use_global_schema = (ldb_get_opaque(ldb, "dsdb_use_global_schema") != NULL);
472 if (use_global_schema) {
473 schema_in = global_schema;
474 } else {
475 p = ldb_get_opaque(ldb, "dsdb_schema");
477 schema_in = talloc_get_type(p, struct dsdb_schema);
478 if (!schema_in) {
479 return NULL;
483 if (schema_in->refresh_fn && !schema_in->refresh_in_progress) {
484 schema_in->refresh_in_progress = true;
485 /* This may change schema, if it needs to reload it from disk */
486 schema_out = schema_in->refresh_fn(schema_in->loaded_from_module,
487 schema_in,
488 use_global_schema);
489 schema_in->refresh_in_progress = false;
490 if (schema_out != schema_in) {
491 talloc_unlink(schema_in, ldb);
493 } else {
494 schema_out = schema_in;
497 if (!reference_ctx) {
498 return schema_out;
499 } else {
500 return talloc_reference(reference_ctx, schema_out);
505 * Make the schema found on this ldb the 'global' schema
508 void dsdb_make_schema_global(struct ldb_context *ldb, struct dsdb_schema *schema)
510 if (!schema) {
511 return;
514 if (global_schema) {
515 talloc_unlink(talloc_autofree_context(), global_schema);
518 /* Wipe any reference to the exact schema - we will set 'use the global schema' below */
519 ldb_set_opaque(ldb, "dsdb_schema", NULL);
521 /* we want the schema to be around permanently */
522 talloc_reparent(ldb, talloc_autofree_context(), schema);
523 global_schema = schema;
525 /* This calls the talloc_reference() of the global schema back onto the ldb */
526 dsdb_set_global_schema(ldb);
529 /* When loading the schema from LDIF files, we don't get the extended DNs.
531 We need to set these up, so that from the moment we start the provision, the defaultObjectCategory links are set up correctly.
533 int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *schema)
535 struct dsdb_class *cur;
536 const struct dsdb_class *target_class;
537 for (cur = schema->classes; cur; cur = cur->next) {
538 const struct ldb_val *rdn;
539 struct ldb_val guid;
540 NTSTATUS status;
541 struct ldb_dn *dn = ldb_dn_new(NULL, ldb, cur->defaultObjectCategory);
543 if (!dn) {
544 return LDB_ERR_INVALID_DN_SYNTAX;
546 rdn = ldb_dn_get_component_val(dn, 0);
547 if (!rdn) {
548 talloc_free(dn);
549 return LDB_ERR_INVALID_DN_SYNTAX;
551 target_class = dsdb_class_by_cn_ldb_val(schema, rdn);
552 if (!target_class) {
553 talloc_free(dn);
554 return LDB_ERR_CONSTRAINT_VIOLATION;
557 status = GUID_to_ndr_blob(&target_class->objectGUID, dn, &guid);
558 if (!NT_STATUS_IS_OK(status)) {
559 talloc_free(dn);
560 return LDB_ERR_OPERATIONS_ERROR;
562 ldb_dn_set_extended_component(dn, "GUID", &guid);
564 cur->defaultObjectCategory = ldb_dn_get_extended_linearized(cur, dn, 1);
565 talloc_free(dn);
567 return LDB_SUCCESS;
570 /**
571 * Add an element to the schema (attribute or class) from an LDB message
573 WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema,
574 struct ldb_message *msg)
576 if (samdb_find_attribute(ldb, msg,
577 "objectclass", "attributeSchema") != NULL) {
578 return dsdb_attribute_from_ldb(ldb, schema, msg);
579 } else if (samdb_find_attribute(ldb, msg,
580 "objectclass", "classSchema") != NULL) {
581 return dsdb_class_from_ldb(schema, msg);
584 /* Don't fail on things not classes or attributes */
585 return WERR_OK;
589 * Rather than read a schema from the LDB itself, read it from an ldif
590 * file. This allows schema to be loaded and used while adding the
591 * schema itself to the directory.
594 WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
596 struct ldb_ldif *ldif;
597 struct ldb_message *msg;
598 TALLOC_CTX *mem_ctx;
599 WERROR status;
600 int ret;
601 struct dsdb_schema *schema;
602 const struct ldb_val *prefix_val;
603 const struct ldb_val *info_val;
604 struct ldb_val info_val_default;
607 mem_ctx = talloc_new(ldb);
608 if (!mem_ctx) {
609 goto nomem;
612 schema = dsdb_new_schema(mem_ctx);
614 schema->fsmo.we_are_master = true;
615 schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
616 if (!schema->fsmo.master_dn) {
617 goto nomem;
621 * load the prefixMap attribute from pf
623 ldif = ldb_ldif_read_string(ldb, &pf);
624 if (!ldif) {
625 status = WERR_INVALID_PARAM;
626 goto failed;
628 talloc_steal(mem_ctx, ldif);
630 msg = ldb_msg_canonicalize(ldb, ldif->msg);
631 if (!msg) {
632 goto nomem;
634 talloc_steal(mem_ctx, msg);
635 talloc_free(ldif);
637 prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
638 if (!prefix_val) {
639 status = WERR_INVALID_PARAM;
640 goto failed;
643 info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
644 if (!info_val) {
645 status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
646 W_ERROR_NOT_OK_GOTO(status, failed);
647 info_val = &info_val_default;
650 status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
651 if (!W_ERROR_IS_OK(status)) {
652 DEBUG(0,("ERROR: dsdb_load_oid_mappings_ldb() failed with %s\n", win_errstr(status)));
653 goto failed;
657 * load the attribute and class definitions outof df
659 while ((ldif = ldb_ldif_read_string(ldb, &df))) {
660 talloc_steal(mem_ctx, ldif);
662 msg = ldb_msg_canonicalize(ldb, ldif->msg);
663 if (!msg) {
664 goto nomem;
667 status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg);
668 talloc_free(ldif);
669 if (!W_ERROR_IS_OK(status)) {
670 goto failed;
674 ret = dsdb_set_schema(ldb, schema);
675 if (ret != LDB_SUCCESS) {
676 status = WERR_FOOBAR;
677 goto failed;
680 ret = dsdb_schema_fill_extended_dn(ldb, schema);
681 if (ret != LDB_SUCCESS) {
682 status = WERR_FOOBAR;
683 goto failed;
686 goto done;
688 nomem:
689 status = WERR_NOMEM;
690 failed:
691 done:
692 talloc_free(mem_ctx);
693 return status;