s4:dsdb Add a memory context for dsdb_get_schema()
[samba.git] / source4 / dsdb / schema / schema_set.c
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 "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"
31
32 /*
33   override the name to attribute handler function
34  */
35 const struct ldb_schema_attribute *dsdb_attribute_handler_override(struct ldb_context *ldb, 
36                                                                    void *private_data,
37                                                                    const char *name)
38 {
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;
44         }
45         return a->ldb_schema_attribute;
46 }
47
48 static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
49 {
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;
58
59         /* setup our own attribute name to schema handler */
60         ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema);
61
62         if (!write_attributes) {
63                 return ret;
64         }
65
66         mem_ctx = talloc_new(ldb);
67         if (!mem_ctx) {
68                 return LDB_ERR_OPERATIONS_ERROR;
69         }
70
71         msg = ldb_msg_new(mem_ctx);
72         if (!msg) {
73                 ldb_oom(ldb);
74                 goto op_error;
75         }
76         msg_idx = ldb_msg_new(mem_ctx);
77         if (!msg_idx) {
78                 ldb_oom(ldb);
79                 goto op_error;
80         }
81         msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
82         if (!msg->dn) {
83                 ldb_oom(ldb);
84                 goto op_error;
85         }
86         msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST");
87         if (!msg_idx->dn) {
88                 ldb_oom(ldb);
89                 goto op_error;
90         }
91
92         ret = ldb_msg_add_string(msg_idx, "@IDXONE", "1");
93         if (ret != LDB_SUCCESS) {
94                 goto op_error;
95         }
96
97         for (attr = schema->attributes; attr; attr = attr->next) {
98                 const char *syntax = attr->syntax->ldb_syntax;
99                 
100                 if (!syntax) {
101                         syntax = attr->syntax->ldap_oid;
102                 }
103
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");
109                 } 
110                 if (ret != LDB_SUCCESS) {
111                         break;
112                 }
113
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;
118                         }
119                 }
120         }
121
122         if (ret != LDB_SUCCESS) {
123                 talloc_free(mem_ctx);
124                 return ret;
125         }
126
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");
138                 
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);
142                 }
143         }
144
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;
148         }
149         if (ret != LDB_SUCCESS) {
150                 talloc_free(mem_ctx);
151                 return ret;
152         }
153
154         /* Now write out the indexs, as found in the schema (if they have changed) */
155
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");
166
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);
170                 }
171         }
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;
175         }
176         talloc_free(mem_ctx);
177         return ret;
178
179 op_error:
180         talloc_free(mem_ctx);
181         return LDB_ERR_OPERATIONS_ERROR;
182 }
183
184 static int uint32_cmp(uint32_t c1, uint32_t c2)
185 {
186         if (c1 == c2) return 0;
187         return c1 > c2 ? 1 : -1;
188 }
189
190 static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2)
191 {
192         return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName);
193 }
194 static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2)
195 {
196         return uint32_cmp((*c1)->governsID_id, (*c2)->governsID_id);
197 }
198 static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2)
199 {
200         return strcasecmp((*c1)->governsID_oid, (*c2)->governsID_oid);
201 }
202 static int dsdb_compare_class_by_cn(struct dsdb_class **c1, struct dsdb_class **c2)
203 {
204         return strcasecmp((*c1)->cn, (*c2)->cn);
205 }
206
207 static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
208 {
209         return strcasecmp((*a1)->lDAPDisplayName, (*a2)->lDAPDisplayName);
210 }
211 static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
212 {
213         return uint32_cmp((*a1)->attributeID_id, (*a2)->attributeID_id);
214 }
215 static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
216 {
217         return strcasecmp((*a1)->attributeID_oid, (*a2)->attributeID_oid);
218 }
219 static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
220 {
221         return uint32_cmp((*a1)->linkID, (*a2)->linkID);
222 }
223
224 /*
225   create the sorted accessor arrays for the schema
226  */
227 static int dsdb_setup_sorted_accessors(struct ldb_context *ldb,
228                                        struct dsdb_schema *schema)
229 {
230         struct dsdb_class *cur;
231         struct dsdb_attribute *a;
232         unsigned int i;
233
234         talloc_free(schema->classes_by_lDAPDisplayName);
235         talloc_free(schema->classes_by_governsID_id);
236         talloc_free(schema->classes_by_governsID_oid);
237         talloc_free(schema->classes_by_cn);
238
239         /* count the classes */
240         for (i=0, cur=schema->classes; cur; i++, cur=cur->next) /* noop */ ;
241         schema->num_classes = i;
242
243         /* setup classes_by_* */
244         schema->classes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_class *, i);
245         schema->classes_by_governsID_id    = talloc_array(schema, struct dsdb_class *, i);
246         schema->classes_by_governsID_oid   = talloc_array(schema, struct dsdb_class *, i);
247         schema->classes_by_cn              = talloc_array(schema, struct dsdb_class *, i);
248         if (schema->classes_by_lDAPDisplayName == NULL ||
249             schema->classes_by_governsID_id == NULL ||
250             schema->classes_by_governsID_oid == NULL ||
251             schema->classes_by_cn == NULL) {
252                 goto failed;
253         }
254
255         for (i=0, cur=schema->classes; cur; i++, cur=cur->next) {
256                 schema->classes_by_lDAPDisplayName[i] = cur;
257                 schema->classes_by_governsID_id[i]    = cur;
258                 schema->classes_by_governsID_oid[i]   = cur;
259                 schema->classes_by_cn[i]              = cur;
260         }
261
262         /* sort the arrays */
263         TYPESAFE_QSORT(schema->classes_by_lDAPDisplayName, schema->num_classes, dsdb_compare_class_by_lDAPDisplayName);
264         TYPESAFE_QSORT(schema->classes_by_governsID_id, schema->num_classes, dsdb_compare_class_by_governsID_id);
265         TYPESAFE_QSORT(schema->classes_by_governsID_oid, schema->num_classes, dsdb_compare_class_by_governsID_oid);
266         TYPESAFE_QSORT(schema->classes_by_cn, schema->num_classes, dsdb_compare_class_by_cn);
267
268         /* now build the attribute accessor arrays */
269         talloc_free(schema->attributes_by_lDAPDisplayName);
270         talloc_free(schema->attributes_by_attributeID_id);
271         talloc_free(schema->attributes_by_attributeID_oid);
272         talloc_free(schema->attributes_by_linkID);
273
274         /* count the attributes */
275         for (i=0, a=schema->attributes; a; i++, a=a->next) /* noop */ ;
276         schema->num_attributes = i;
277
278         /* setup attributes_by_* */
279         schema->attributes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_attribute *, i);
280         schema->attributes_by_attributeID_id    = talloc_array(schema, struct dsdb_attribute *, i);
281         schema->attributes_by_attributeID_oid   = talloc_array(schema, struct dsdb_attribute *, i);
282         schema->attributes_by_linkID              = talloc_array(schema, struct dsdb_attribute *, i);
283         if (schema->attributes_by_lDAPDisplayName == NULL ||
284             schema->attributes_by_attributeID_id == NULL ||
285             schema->attributes_by_attributeID_oid == NULL ||
286             schema->attributes_by_linkID == NULL) {
287                 goto failed;
288         }
289
290         for (i=0, a=schema->attributes; a; i++, a=a->next) {
291                 schema->attributes_by_lDAPDisplayName[i] = a;
292                 schema->attributes_by_attributeID_id[i]    = a;
293                 schema->attributes_by_attributeID_oid[i]   = a;
294                 schema->attributes_by_linkID[i]          = a;
295         }
296
297         /* sort the arrays */
298         TYPESAFE_QSORT(schema->attributes_by_lDAPDisplayName, schema->num_attributes, dsdb_compare_attribute_by_lDAPDisplayName);
299         TYPESAFE_QSORT(schema->attributes_by_attributeID_id, schema->num_attributes, dsdb_compare_attribute_by_attributeID_id);
300         TYPESAFE_QSORT(schema->attributes_by_attributeID_oid, schema->num_attributes, dsdb_compare_attribute_by_attributeID_oid);
301         TYPESAFE_QSORT(schema->attributes_by_linkID, schema->num_attributes, dsdb_compare_attribute_by_linkID);
302
303         return LDB_SUCCESS;
304
305 failed:
306         schema->classes_by_lDAPDisplayName = NULL;
307         schema->classes_by_governsID_id = NULL;
308         schema->classes_by_governsID_oid = NULL;
309         schema->classes_by_cn = NULL;
310         schema->attributes_by_lDAPDisplayName = NULL;
311         schema->attributes_by_attributeID_id = NULL;
312         schema->attributes_by_attributeID_oid = NULL;
313         schema->attributes_by_linkID = NULL;
314         ldb_oom(ldb);
315         return LDB_ERR_OPERATIONS_ERROR;
316 }
317
318 int dsdb_setup_schema_inversion(struct ldb_context *ldb, struct dsdb_schema *schema)
319 {
320         /* Walk the list of schema classes */
321
322         /*  For each subClassOf, add us to subclasses of the parent */
323
324         /* collect these subclasses into a recursive list of total subclasses, preserving order */
325
326         /* For each subclass under 'top', write the index from it's
327          * order as an integer in the dsdb_class (for sorting
328          * objectClass lists efficiently) */
329
330         /* Walk the list of scheam classes */
331         
332         /*  Create a 'total possible superiors' on each class */
333         return LDB_SUCCESS;
334 }
335
336 /**
337  * Attach the schema to an opaque pointer on the ldb, so ldb modules
338  * can find it 
339  */
340
341 int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
342 {
343         int ret;
344
345         ret = dsdb_setup_sorted_accessors(ldb, schema);
346         if (ret != LDB_SUCCESS) {
347                 return ret;
348         }
349
350         ret = schema_fill_constructed(schema);
351         if (ret != LDB_SUCCESS) {
352                 return ret;
353         }
354
355         ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
356         if (ret != LDB_SUCCESS) {
357                 return ret;
358         }
359
360         /* Set the new attributes based on the new schema */
361         ret = dsdb_schema_set_attributes(ldb, schema, true);
362         if (ret != LDB_SUCCESS) {
363                 return ret;
364         }
365
366         talloc_steal(ldb, schema);
367
368         return LDB_SUCCESS;
369 }
370
371 /**
372  * Global variable to hold one copy of the schema, used to avoid memory bloat
373  */
374 static struct dsdb_schema *global_schema;
375
376 /**
377  * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
378  */
379 int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
380                           bool write_attributes)
381 {
382         int ret;
383         ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
384         if (ret != LDB_SUCCESS) {
385                 return ret;
386         }
387
388         /* Set the new attributes based on the new schema */
389         ret = dsdb_schema_set_attributes(ldb, schema, write_attributes);
390         if (ret != LDB_SUCCESS) {
391                 return ret;
392         }
393
394         /* Keep a reference to this schema, just incase the original copy is replaced */
395         if (talloc_reference(ldb, schema) == NULL) {
396                 return LDB_ERR_OPERATIONS_ERROR;
397         }
398
399         return LDB_SUCCESS;
400 }
401
402 /**
403  * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
404  */
405 int dsdb_set_global_schema(struct ldb_context *ldb)
406 {
407         if (!global_schema) {
408                 return LDB_SUCCESS;
409         }
410
411         return dsdb_reference_schema(ldb, global_schema, false /* Don't write attributes, it's expensive */);
412 }
413
414 /**
415  * Find the schema object for this ldb
416  *
417  * If reference_ctx is not NULL, then talloc_reference onto that context
418  */
419
420 struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *reference_ctx)
421 {
422         const void *p;
423         struct dsdb_schema *schema;
424
425         /* see if we have a cached copy */
426         p = ldb_get_opaque(ldb, "dsdb_schema");
427         if (!p) {
428                 return NULL;
429         }
430
431         schema = talloc_get_type(p, struct dsdb_schema);
432         if (!schema) {
433                 return NULL;
434         }
435
436         if (!reference_ctx) {
437                 return schema;
438         } else {
439                 return talloc_reference(reference_ctx, schema);
440         }
441 }
442
443 /**
444  * Make the schema found on this ldb the 'global' schema
445  */
446
447 void dsdb_make_schema_global(struct ldb_context *ldb)
448 {
449         struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
450         if (!schema) {
451                 return;
452         }
453
454         if (global_schema) {
455                 talloc_unlink(talloc_autofree_context(), global_schema);
456         }
457
458         /* we want the schema to be around permanently */
459         talloc_reparent(talloc_parent(schema), talloc_autofree_context(), schema);
460
461         global_schema = schema;
462
463         dsdb_set_global_schema(ldb);
464 }
465
466 /* When loading the schema from LDIF files, we don't get the extended DNs. 
467    
468    We need to set these up, so that from the moment we start the provision, the defaultObjectCategory links are set up correctly. 
469  */
470 int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *schema)
471 {
472         struct dsdb_class *cur;
473         const struct dsdb_class *target_class;
474         for (cur = schema->classes; cur; cur = cur->next) {
475                 const struct ldb_val *rdn;
476                 struct ldb_val guid;
477                 NTSTATUS status;
478                 struct ldb_dn *dn = ldb_dn_new(NULL, ldb, cur->defaultObjectCategory);
479
480                 if (!dn) {
481                         return LDB_ERR_INVALID_DN_SYNTAX;
482                 }
483                 rdn = ldb_dn_get_component_val(dn, 0);
484                 if (!rdn) {
485                         talloc_free(dn);
486                         return LDB_ERR_INVALID_DN_SYNTAX;
487                 }
488                 target_class = dsdb_class_by_cn_ldb_val(schema, rdn);
489                 if (!target_class) {
490                         talloc_free(dn);
491                         return LDB_ERR_CONSTRAINT_VIOLATION;
492                 }
493                 
494                 status = GUID_to_ndr_blob(&target_class->objectGUID, dn, &guid);
495                 if (!NT_STATUS_IS_OK(status)) {
496                         talloc_free(dn);
497                         return LDB_ERR_OPERATIONS_ERROR;
498                 }
499                 ldb_dn_set_extended_component(dn, "GUID", &guid);
500
501                 cur->defaultObjectCategory = ldb_dn_get_extended_linearized(cur, dn, 1);
502                 talloc_free(dn);
503         }
504         return LDB_SUCCESS;
505 }
506
507 /** 
508  * Add an element to the schema (attribute or class) from an LDB message
509  */
510 WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema, 
511                                        struct ldb_message *msg) 
512 {
513         static struct ldb_parse_tree *attr_tree, *class_tree;
514         if (!attr_tree) {
515                 attr_tree = ldb_parse_tree(talloc_autofree_context(), "(objectClass=attributeSchema)");
516                 if (!attr_tree) {
517                         return WERR_NOMEM;
518                 }
519         }
520
521         if (!class_tree) {
522                 class_tree = ldb_parse_tree(talloc_autofree_context(), "(objectClass=classSchema)");
523                 if (!class_tree) {
524                         return WERR_NOMEM;
525                 }
526         }
527
528         if (ldb_match_msg(ldb, msg, attr_tree, NULL, LDB_SCOPE_BASE)) {
529                 return dsdb_attribute_from_ldb(ldb, schema, msg);
530         } else if (ldb_match_msg(ldb, msg, class_tree, NULL, LDB_SCOPE_BASE)) {
531                 return dsdb_class_from_ldb(schema, msg);
532         }
533
534         /* Don't fail on things not classes or attributes */
535         return WERR_OK;
536 }
537
538 /**
539  * Rather than read a schema from the LDB itself, read it from an ldif
540  * file.  This allows schema to be loaded and used while adding the
541  * schema itself to the directory.
542  */
543
544 WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
545 {
546         struct ldb_ldif *ldif;
547         struct ldb_message *msg;
548         TALLOC_CTX *mem_ctx;
549         WERROR status;
550         int ret;
551         struct dsdb_schema *schema;
552         const struct ldb_val *prefix_val;
553         const struct ldb_val *info_val;
554         struct ldb_val info_val_default;
555
556
557         mem_ctx = talloc_new(ldb);
558         if (!mem_ctx) {
559                 goto nomem;
560         }
561
562         schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
563
564         schema->fsmo.we_are_master = true;
565         schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
566         if (!schema->fsmo.master_dn) {
567                 goto nomem;
568         }
569
570         /*
571          * load the prefixMap attribute from pf
572          */
573         ldif = ldb_ldif_read_string(ldb, &pf);
574         if (!ldif) {
575                 status = WERR_INVALID_PARAM;
576                 goto failed;
577         }
578         talloc_steal(mem_ctx, ldif);
579
580         msg = ldb_msg_canonicalize(ldb, ldif->msg);
581         if (!msg) {
582                 goto nomem;
583         }
584         talloc_steal(mem_ctx, msg);
585         talloc_free(ldif);
586
587         prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
588         if (!prefix_val) {
589                 status = WERR_INVALID_PARAM;
590                 goto failed;
591         }
592
593         info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
594         if (!info_val) {
595                 info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000");
596                 if (!info_val_default.data) {
597                         goto nomem;
598                 }
599                 info_val = &info_val_default;
600         }
601
602         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
603         if (!W_ERROR_IS_OK(status)) {
604                 goto failed;
605         }
606
607         /*
608          * load the attribute and class definitions outof df
609          */
610         while ((ldif = ldb_ldif_read_string(ldb, &df))) {
611                 talloc_steal(mem_ctx, ldif);
612
613                 msg = ldb_msg_canonicalize(ldb, ldif->msg);
614                 if (!msg) {
615                         goto nomem;
616                 }
617
618                 status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg);
619                 talloc_free(ldif);
620                 if (!W_ERROR_IS_OK(status)) {
621                         goto failed;
622                 }
623         }
624
625         ret = dsdb_set_schema(ldb, schema);
626         if (ret != LDB_SUCCESS) {
627                 status = WERR_FOOBAR;
628                 goto failed;
629         }
630
631         ret = dsdb_schema_fill_extended_dn(ldb, schema);
632         if (ret != LDB_SUCCESS) {
633                 status = WERR_FOOBAR;
634                 goto failed;
635         }
636
637         goto done;
638
639 nomem:
640         status = WERR_NOMEM;
641 failed:
642 done:
643         talloc_free(mem_ctx);
644         return status;
645 }