s4:dsdb Simplfy match of objectclass in dsdb_schema_set_el_from_ldb_msg
[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         ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", NULL);
361         if (ret != LDB_SUCCESS) {
362                 return ret;
363         }
364
365         /* Set the new attributes based on the new schema */
366         ret = dsdb_schema_set_attributes(ldb, schema, true);
367         if (ret != LDB_SUCCESS) {
368                 return ret;
369         }
370
371         talloc_steal(ldb, schema);
372
373         return LDB_SUCCESS;
374 }
375
376 /**
377  * Global variable to hold one copy of the schema, used to avoid memory bloat
378  */
379 static struct dsdb_schema *global_schema;
380
381 /**
382  * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
383  */
384 int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
385                           bool write_attributes)
386 {
387         int ret;
388         ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
389         if (ret != LDB_SUCCESS) {
390                 return ret;
391         }
392
393         if (talloc_reference(ldb, schema) == NULL) {
394                 return LDB_ERR_OPERATIONS_ERROR;
395         }
396
397         ret = dsdb_schema_set_attributes(ldb, schema, write_attributes);
398         if (ret != LDB_SUCCESS) {
399                 return ret;
400         }
401
402         return LDB_SUCCESS;
403 }
404
405 /**
406  * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
407  */
408 int dsdb_set_global_schema(struct ldb_context *ldb)
409 {
410         int ret;
411         void *use_global_schema = (void *)1;
412         if (!global_schema) {
413                 return LDB_SUCCESS;
414         }
415
416         ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", use_global_schema);
417         if (ret != LDB_SUCCESS) {
418                 return ret;
419         }
420
421         /* Set the new attributes based on the new schema */
422         ret = dsdb_schema_set_attributes(ldb, global_schema, false /* Don't write attributes, it's expensive */);
423         if (ret == LDB_SUCCESS) {
424                 /* Keep a reference to this schema, just incase the original copy is replaced */
425                 if (talloc_reference(ldb, global_schema) == NULL) {
426                         return LDB_ERR_OPERATIONS_ERROR;
427                 }
428         }
429
430         return ret;
431 }
432
433 /**
434  * Find the schema object for this ldb
435  *
436  * If reference_ctx is not NULL, then talloc_reference onto that context
437  */
438
439 struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *reference_ctx)
440 {
441         const void *p;
442         struct dsdb_schema *schema_out;
443         struct dsdb_schema *schema_in;
444         bool use_global_schema;
445
446         /* see if we have a cached copy */
447         use_global_schema = (ldb_get_opaque(ldb, "dsdb_use_global_schema") != NULL);
448         if (use_global_schema) {
449                 schema_in = global_schema;
450         } else {
451                 p = ldb_get_opaque(ldb, "dsdb_schema");
452
453                 schema_in = talloc_get_type(p, struct dsdb_schema);
454                 if (!schema_in) {
455                         return NULL;
456                 }
457         }
458
459         if (schema_in->refresh_fn && !schema_in->refresh_in_progress) {
460                 schema_in->refresh_in_progress = true;
461                 /* This may change schema, if it needs to reload it from disk */
462                 schema_out = schema_in->refresh_fn(schema_in->loaded_from_module,
463                                                    schema_in,
464                                                    use_global_schema);
465                 schema_in->refresh_in_progress = false;
466                 if (schema_out != schema_in) {
467                         talloc_unlink(schema_in, ldb);
468                 }
469         } else {
470                 schema_out = schema_in;
471         }
472
473         if (!reference_ctx) {
474                 return schema_out;
475         } else {
476                 return talloc_reference(reference_ctx, schema_out);
477         }
478 }
479
480 /**
481  * Make the schema found on this ldb the 'global' schema
482  */
483
484 void dsdb_make_schema_global(struct ldb_context *ldb, struct dsdb_schema *schema)
485 {
486         if (!schema) {
487                 return;
488         }
489
490         if (global_schema) {
491                 talloc_unlink(talloc_autofree_context(), global_schema);
492         }
493
494         /* Wipe any reference to the exact schema - we will set 'use the global schema' below */
495         ldb_set_opaque(ldb, "dsdb_schema", NULL);
496
497         /* we want the schema to be around permanently */
498         talloc_reparent(ldb, talloc_autofree_context(), schema);
499         global_schema = schema;
500
501         /* This calls the talloc_reference() of the global schema back onto the ldb */
502         dsdb_set_global_schema(ldb);
503 }
504
505 /* When loading the schema from LDIF files, we don't get the extended DNs. 
506    
507    We need to set these up, so that from the moment we start the provision, the defaultObjectCategory links are set up correctly. 
508  */
509 int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *schema)
510 {
511         struct dsdb_class *cur;
512         const struct dsdb_class *target_class;
513         for (cur = schema->classes; cur; cur = cur->next) {
514                 const struct ldb_val *rdn;
515                 struct ldb_val guid;
516                 NTSTATUS status;
517                 struct ldb_dn *dn = ldb_dn_new(NULL, ldb, cur->defaultObjectCategory);
518
519                 if (!dn) {
520                         return LDB_ERR_INVALID_DN_SYNTAX;
521                 }
522                 rdn = ldb_dn_get_component_val(dn, 0);
523                 if (!rdn) {
524                         talloc_free(dn);
525                         return LDB_ERR_INVALID_DN_SYNTAX;
526                 }
527                 target_class = dsdb_class_by_cn_ldb_val(schema, rdn);
528                 if (!target_class) {
529                         talloc_free(dn);
530                         return LDB_ERR_CONSTRAINT_VIOLATION;
531                 }
532                 
533                 status = GUID_to_ndr_blob(&target_class->objectGUID, dn, &guid);
534                 if (!NT_STATUS_IS_OK(status)) {
535                         talloc_free(dn);
536                         return LDB_ERR_OPERATIONS_ERROR;
537                 }
538                 ldb_dn_set_extended_component(dn, "GUID", &guid);
539
540                 cur->defaultObjectCategory = ldb_dn_get_extended_linearized(cur, dn, 1);
541                 talloc_free(dn);
542         }
543         return LDB_SUCCESS;
544 }
545
546 /** 
547  * Add an element to the schema (attribute or class) from an LDB message
548  */
549 WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema, 
550                                        struct ldb_message *msg) 
551 {
552         if (samdb_find_attribute(ldb, msg,
553                                  "objectclass", "attributeSchema") != NULL) {
554                 return dsdb_attribute_from_ldb(ldb, schema, msg);
555         } else if (samdb_find_attribute(ldb, msg,
556                                  "objectclass", "classSchema") != NULL) {
557                 return dsdb_class_from_ldb(schema, msg);
558         }
559
560         /* Don't fail on things not classes or attributes */
561         return WERR_OK;
562 }
563
564 /**
565  * Rather than read a schema from the LDB itself, read it from an ldif
566  * file.  This allows schema to be loaded and used while adding the
567  * schema itself to the directory.
568  */
569
570 WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
571 {
572         struct ldb_ldif *ldif;
573         struct ldb_message *msg;
574         TALLOC_CTX *mem_ctx;
575         WERROR status;
576         int ret;
577         struct dsdb_schema *schema;
578         const struct ldb_val *prefix_val;
579         const struct ldb_val *info_val;
580         struct ldb_val info_val_default;
581
582
583         mem_ctx = talloc_new(ldb);
584         if (!mem_ctx) {
585                 goto nomem;
586         }
587
588         schema = dsdb_new_schema(mem_ctx);
589
590         schema->fsmo.we_are_master = true;
591         schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
592         if (!schema->fsmo.master_dn) {
593                 goto nomem;
594         }
595
596         /*
597          * load the prefixMap attribute from pf
598          */
599         ldif = ldb_ldif_read_string(ldb, &pf);
600         if (!ldif) {
601                 status = WERR_INVALID_PARAM;
602                 goto failed;
603         }
604         talloc_steal(mem_ctx, ldif);
605
606         msg = ldb_msg_canonicalize(ldb, ldif->msg);
607         if (!msg) {
608                 goto nomem;
609         }
610         talloc_steal(mem_ctx, msg);
611         talloc_free(ldif);
612
613         prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
614         if (!prefix_val) {
615                 status = WERR_INVALID_PARAM;
616                 goto failed;
617         }
618
619         info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
620         if (!info_val) {
621                 status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
622                 W_ERROR_NOT_OK_GOTO(status, failed);
623                 info_val = &info_val_default;
624         }
625
626         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
627         if (!W_ERROR_IS_OK(status)) {
628                 DEBUG(0,("ERROR: dsdb_load_oid_mappings_ldb() failed with %s\n", win_errstr(status)));
629                 goto failed;
630         }
631
632         /*
633          * load the attribute and class definitions outof df
634          */
635         while ((ldif = ldb_ldif_read_string(ldb, &df))) {
636                 talloc_steal(mem_ctx, ldif);
637
638                 msg = ldb_msg_canonicalize(ldb, ldif->msg);
639                 if (!msg) {
640                         goto nomem;
641                 }
642
643                 status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg);
644                 talloc_free(ldif);
645                 if (!W_ERROR_IS_OK(status)) {
646                         goto failed;
647                 }
648         }
649
650         ret = dsdb_set_schema(ldb, schema);
651         if (ret != LDB_SUCCESS) {
652                 status = WERR_FOOBAR;
653                 goto failed;
654         }
655
656         ret = dsdb_schema_fill_extended_dn(ldb, schema);
657         if (ret != LDB_SUCCESS) {
658                 status = WERR_FOOBAR;
659                 goto failed;
660         }
661
662         goto done;
663
664 nomem:
665         status = WERR_NOMEM;
666 failed:
667 done:
668         talloc_free(mem_ctx);
669         return status;
670 }