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