s4-dsdb: change samdb_replace() to dsdb_replace() and allow for dsdb_flags
[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 #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         uint32_t 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
418 struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
419 {
420         const void *p;
421         struct dsdb_schema *schema;
422
423         /* see if we have a cached copy */
424         p = ldb_get_opaque(ldb, "dsdb_schema");
425         if (!p) {
426                 return NULL;
427         }
428
429         schema = talloc_get_type(p, struct dsdb_schema);
430         if (!schema) {
431                 return NULL;
432         }
433
434         return schema;
435 }
436
437 /**
438  * Make the schema found on this ldb the 'global' schema
439  */
440
441 void dsdb_make_schema_global(struct ldb_context *ldb)
442 {
443         struct dsdb_schema *schema = dsdb_get_schema(ldb);
444         if (!schema) {
445                 return;
446         }
447
448         if (global_schema) {
449                 talloc_unlink(talloc_autofree_context(), global_schema);
450         }
451
452         /* we want the schema to be around permanently */
453         talloc_reparent(talloc_parent(schema), talloc_autofree_context(), schema);
454
455         global_schema = schema;
456
457         dsdb_set_global_schema(ldb);
458 }
459
460 /* When loading the schema from LDIF files, we don't get the extended DNs. 
461    
462    We need to set these up, so that from the moment we start the provision, the defaultObjectCategory links are set up correctly. 
463  */
464 int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *schema)
465 {
466         struct dsdb_class *cur;
467         const struct dsdb_class *target_class;
468         for (cur = schema->classes; cur; cur = cur->next) {
469                 const struct ldb_val *rdn;
470                 struct ldb_val guid;
471                 NTSTATUS status;
472                 struct ldb_dn *dn = ldb_dn_new(NULL, ldb, cur->defaultObjectCategory);
473
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                 status = GUID_to_ndr_blob(&target_class->objectGUID, dn, &guid);
489                 if (!NT_STATUS_IS_OK(status)) {
490                         talloc_free(dn);
491                         return LDB_ERR_OPERATIONS_ERROR;
492                 }
493                 ldb_dn_set_extended_component(dn, "GUID", &guid);
494
495                 cur->defaultObjectCategory = ldb_dn_get_extended_linearized(cur, dn, 1);
496                 talloc_free(dn);
497         }
498         return LDB_SUCCESS;
499 }
500
501 /** 
502  * Add an element to the schema (attribute or class) from an LDB message
503  */
504 WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema, 
505                                        struct ldb_message *msg) 
506 {
507         static struct ldb_parse_tree *attr_tree, *class_tree;
508         if (!attr_tree) {
509                 attr_tree = ldb_parse_tree(talloc_autofree_context(), "(objectClass=attributeSchema)");
510                 if (!attr_tree) {
511                         return WERR_NOMEM;
512                 }
513         }
514
515         if (!class_tree) {
516                 class_tree = ldb_parse_tree(talloc_autofree_context(), "(objectClass=classSchema)");
517                 if (!class_tree) {
518                         return WERR_NOMEM;
519                 }
520         }
521
522         if (ldb_match_msg(ldb, msg, attr_tree, NULL, LDB_SCOPE_BASE)) {
523                 return dsdb_attribute_from_ldb(ldb, schema, msg);
524         } else if (ldb_match_msg(ldb, msg, class_tree, NULL, LDB_SCOPE_BASE)) {
525                 return dsdb_class_from_ldb(schema, msg);
526         }
527
528         /* Don't fail on things not classes or attributes */
529         return WERR_OK;
530 }
531
532 /**
533  * Rather than read a schema from the LDB itself, read it from an ldif
534  * file.  This allows schema to be loaded and used while adding the
535  * schema itself to the directory.
536  */
537
538 WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
539 {
540         struct ldb_ldif *ldif;
541         struct ldb_message *msg;
542         TALLOC_CTX *mem_ctx;
543         WERROR status;
544         int ret;
545         struct dsdb_schema *schema;
546         const struct ldb_val *prefix_val;
547         const struct ldb_val *info_val;
548         struct ldb_val info_val_default;
549
550
551         mem_ctx = talloc_new(ldb);
552         if (!mem_ctx) {
553                 goto nomem;
554         }
555
556         schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
557
558         schema->fsmo.we_are_master = true;
559         schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
560         if (!schema->fsmo.master_dn) {
561                 goto nomem;
562         }
563
564         /*
565          * load the prefixMap attribute from pf
566          */
567         ldif = ldb_ldif_read_string(ldb, &pf);
568         if (!ldif) {
569                 status = WERR_INVALID_PARAM;
570                 goto failed;
571         }
572         talloc_steal(mem_ctx, ldif);
573
574         msg = ldb_msg_canonicalize(ldb, ldif->msg);
575         if (!msg) {
576                 goto nomem;
577         }
578         talloc_steal(mem_ctx, msg);
579         talloc_free(ldif);
580
581         prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
582         if (!prefix_val) {
583                 status = WERR_INVALID_PARAM;
584                 goto failed;
585         }
586
587         info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
588         if (!info_val) {
589                 info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000");
590                 if (!info_val_default.data) {
591                         goto nomem;
592                 }
593                 info_val = &info_val_default;
594         }
595
596         status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
597         if (!W_ERROR_IS_OK(status)) {
598                 goto failed;
599         }
600
601         /*
602          * load the attribute and class definitions outof df
603          */
604         while ((ldif = ldb_ldif_read_string(ldb, &df))) {
605                 talloc_steal(mem_ctx, ldif);
606
607                 msg = ldb_msg_canonicalize(ldb, ldif->msg);
608                 if (!msg) {
609                         goto nomem;
610                 }
611
612                 status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg);
613                 talloc_free(ldif);
614                 if (!W_ERROR_IS_OK(status)) {
615                         goto failed;
616                 }
617         }
618
619         ret = dsdb_set_schema(ldb, schema);
620         if (ret != LDB_SUCCESS) {
621                 status = WERR_FOOBAR;
622                 goto failed;
623         }
624
625         ret = dsdb_schema_fill_extended_dn(ldb, schema);
626         if (ret != LDB_SUCCESS) {
627                 status = WERR_FOOBAR;
628                 goto failed;
629         }
630
631         goto done;
632
633 nomem:
634         status = WERR_NOMEM;
635 failed:
636 done:
637         talloc_free(mem_ctx);
638         return status;
639 }