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