2 Unix SMB/CIFS implementation.
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
7 Copyright (C) Matthieu Patou <mat@matws.net> 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/util/dlinklist.h"
26 #include "dsdb/samdb/samdb.h"
27 #include <ldb_module.h>
28 #include "param/param.h"
29 #include "librpc/ndr/libndr.h"
30 #include "librpc/gen_ndr/ndr_misc.h"
31 #include "lib/util/tsort.h"
33 /* change this when we change something in our schema code that
34 * requires a re-index of the database
36 #define SAMDB_INDEXING_VERSION "2"
39 override the name to attribute handler function
41 const struct ldb_schema_attribute
*dsdb_attribute_handler_override(struct ldb_context
*ldb
,
45 struct dsdb_schema
*schema
= talloc_get_type_abort(private_data
, struct dsdb_schema
);
46 const struct dsdb_attribute
*a
= dsdb_attribute_by_lDAPDisplayName(schema
, name
);
48 /* this will fall back to ldb internal handling */
51 return a
->ldb_schema_attribute
;
54 static int dsdb_schema_set_attributes(struct ldb_context
*ldb
, struct dsdb_schema
*schema
, bool write_attributes
)
56 int ret
= LDB_SUCCESS
;
57 struct ldb_result
*res
;
58 struct ldb_result
*res_idx
;
59 struct dsdb_attribute
*attr
;
60 struct ldb_message
*mod_msg
;
62 struct ldb_message
*msg
;
63 struct ldb_message
*msg_idx
;
65 /* setup our own attribute name to schema handler */
66 ldb_schema_attribute_set_override_handler(ldb
, dsdb_attribute_handler_override
, schema
);
68 if (!write_attributes
) {
72 mem_ctx
= talloc_new(ldb
);
77 msg
= ldb_msg_new(mem_ctx
);
82 msg_idx
= ldb_msg_new(mem_ctx
);
87 msg
->dn
= ldb_dn_new(msg
, ldb
, "@ATTRIBUTES");
92 msg_idx
->dn
= ldb_dn_new(msg_idx
, ldb
, "@INDEXLIST");
98 ret
= ldb_msg_add_string(msg_idx
, "@IDXONE", "1");
99 if (ret
!= LDB_SUCCESS
) {
104 ret
= ldb_msg_add_string(msg_idx
, "@IDXVERSION", SAMDB_INDEXING_VERSION
);
105 if (ret
!= LDB_SUCCESS
) {
109 for (attr
= schema
->attributes
; attr
; attr
= attr
->next
) {
110 const char *syntax
= attr
->syntax
->ldb_syntax
;
113 syntax
= attr
->syntax
->ldap_oid
;
117 * Write out a rough approximation of the schema
118 * as an @ATTRIBUTES value, for bootstrapping
120 if (strcmp(syntax
, LDB_SYNTAX_INTEGER
) == 0) {
121 ret
= ldb_msg_add_string(msg
, attr
->lDAPDisplayName
, "INTEGER");
122 } else if (strcmp(syntax
, LDB_SYNTAX_DIRECTORY_STRING
) == 0) {
123 ret
= ldb_msg_add_string(msg
, attr
->lDAPDisplayName
, "CASE_INSENSITIVE");
125 if (ret
!= LDB_SUCCESS
) {
129 if (attr
->searchFlags
& SEARCH_FLAG_ATTINDEX
) {
130 ret
= ldb_msg_add_string(msg_idx
, "@IDXATTR", attr
->lDAPDisplayName
);
131 if (ret
!= LDB_SUCCESS
) {
137 if (ret
!= LDB_SUCCESS
) {
138 talloc_free(mem_ctx
);
143 * Try to avoid churning the attributes too much,
144 * we only want to do this if they have changed
146 ret
= ldb_search(ldb
, mem_ctx
, &res
, msg
->dn
, LDB_SCOPE_BASE
, NULL
,
148 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
149 ret
= ldb_add(ldb
, msg
);
150 } else if (ret
!= LDB_SUCCESS
) {
151 } else if (res
->count
!= 1) {
152 ret
= ldb_add(ldb
, msg
);
155 /* Annoyingly added to our search results */
156 ldb_msg_remove_attr(res
->msgs
[0], "distinguishedName");
158 ret
= ldb_msg_difference(ldb
, mem_ctx
,
159 res
->msgs
[0], msg
, &mod_msg
);
160 if (ret
!= LDB_SUCCESS
) {
163 if (mod_msg
->num_elements
> 0) {
164 ret
= dsdb_replace(ldb
, mod_msg
, 0);
166 talloc_free(mod_msg
);
169 if (ret
== LDB_ERR_OPERATIONS_ERROR
|| ret
== LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
170 /* We might be on a read-only DB or LDAP */
173 if (ret
!= LDB_SUCCESS
) {
174 talloc_free(mem_ctx
);
178 /* Now write out the indexes, as found in the schema (if they have changed) */
180 ret
= ldb_search(ldb
, mem_ctx
, &res_idx
, msg_idx
->dn
, LDB_SCOPE_BASE
,
182 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
183 ret
= ldb_add(ldb
, msg_idx
);
184 } else if (ret
!= LDB_SUCCESS
) {
185 } else if (res_idx
->count
!= 1) {
186 ret
= ldb_add(ldb
, msg_idx
);
189 /* Annoyingly added to our search results */
190 ldb_msg_remove_attr(res_idx
->msgs
[0], "distinguishedName");
192 ret
= ldb_msg_difference(ldb
, mem_ctx
,
193 res_idx
->msgs
[0], msg_idx
, &mod_msg
);
194 if (ret
!= LDB_SUCCESS
) {
197 if (mod_msg
->num_elements
> 0) {
198 ret
= dsdb_replace(ldb
, mod_msg
, 0);
200 talloc_free(mod_msg
);
202 if (ret
== LDB_ERR_OPERATIONS_ERROR
|| ret
== LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
|| ret
== LDB_ERR_INVALID_DN_SYNTAX
) {
203 /* We might be on a read-only DB */
206 talloc_free(mem_ctx
);
210 talloc_free(mem_ctx
);
211 return ldb_operr(ldb
);
216 create extra attribute shortcuts
218 static void dsdb_setup_attribute_shortcuts(struct ldb_context
*ldb
, struct dsdb_schema
*schema
)
220 struct dsdb_attribute
*attribute
;
222 /* setup fast access to one_way_link and DN format */
223 for (attribute
=schema
->attributes
; attribute
; attribute
=attribute
->next
) {
224 attribute
->dn_format
= dsdb_dn_oid_to_format(attribute
->syntax
->ldap_oid
);
226 if (attribute
->dn_format
== DSDB_INVALID_DN
) {
227 attribute
->one_way_link
= false;
231 /* these are not considered to be one way links for
232 the purpose of DN link fixups */
233 if (ldb_attr_cmp("distinguishedName", attribute
->lDAPDisplayName
) == 0 ||
234 ldb_attr_cmp("objectCategory", attribute
->lDAPDisplayName
) == 0) {
235 attribute
->one_way_link
= false;
239 if (attribute
->linkID
== 0) {
240 attribute
->one_way_link
= true;
243 /* handle attributes with a linkID but no backlink */
244 if (dsdb_attribute_by_linkID(schema
, attribute
->linkID
) == NULL
) {
245 attribute
->one_way_link
= true;
248 attribute
->one_way_link
= false;
252 static int uint32_cmp(uint32_t c1
, uint32_t c2
)
254 if (c1
== c2
) return 0;
255 return c1
> c2
? 1 : -1;
258 static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class
**c1
, struct dsdb_class
**c2
)
260 return strcasecmp((*c1
)->lDAPDisplayName
, (*c2
)->lDAPDisplayName
);
262 static int dsdb_compare_class_by_governsID_id(struct dsdb_class
**c1
, struct dsdb_class
**c2
)
264 return uint32_cmp((*c1
)->governsID_id
, (*c2
)->governsID_id
);
266 static int dsdb_compare_class_by_governsID_oid(struct dsdb_class
**c1
, struct dsdb_class
**c2
)
268 return strcasecmp((*c1
)->governsID_oid
, (*c2
)->governsID_oid
);
270 static int dsdb_compare_class_by_cn(struct dsdb_class
**c1
, struct dsdb_class
**c2
)
272 return strcasecmp((*c1
)->cn
, (*c2
)->cn
);
275 static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute
**a1
, struct dsdb_attribute
**a2
)
277 return strcasecmp((*a1
)->lDAPDisplayName
, (*a2
)->lDAPDisplayName
);
279 static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute
**a1
, struct dsdb_attribute
**a2
)
281 return uint32_cmp((*a1
)->attributeID_id
, (*a2
)->attributeID_id
);
283 static int dsdb_compare_attribute_by_msDS_IntId(struct dsdb_attribute
**a1
, struct dsdb_attribute
**a2
)
285 return uint32_cmp((*a1
)->msDS_IntId
, (*a2
)->msDS_IntId
);
287 static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute
**a1
, struct dsdb_attribute
**a2
)
289 return strcasecmp((*a1
)->attributeID_oid
, (*a2
)->attributeID_oid
);
291 static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute
**a1
, struct dsdb_attribute
**a2
)
293 return uint32_cmp((*a1
)->linkID
, (*a2
)->linkID
);
297 * Clean up Classes and Attributes accessor arrays
299 static void dsdb_sorted_accessors_free(struct dsdb_schema
*schema
)
301 /* free classes accessors */
302 TALLOC_FREE(schema
->classes_by_lDAPDisplayName
);
303 TALLOC_FREE(schema
->classes_by_governsID_id
);
304 TALLOC_FREE(schema
->classes_by_governsID_oid
);
305 TALLOC_FREE(schema
->classes_by_cn
);
306 /* free attribute accessors */
307 TALLOC_FREE(schema
->attributes_by_lDAPDisplayName
);
308 TALLOC_FREE(schema
->attributes_by_attributeID_id
);
309 TALLOC_FREE(schema
->attributes_by_msDS_IntId
);
310 TALLOC_FREE(schema
->attributes_by_attributeID_oid
);
311 TALLOC_FREE(schema
->attributes_by_linkID
);
315 create the sorted accessor arrays for the schema
317 int dsdb_setup_sorted_accessors(struct ldb_context
*ldb
,
318 struct dsdb_schema
*schema
)
320 struct dsdb_class
*cur
;
321 struct dsdb_attribute
*a
;
323 unsigned int num_int_id
;
325 /* free all caches */
326 dsdb_sorted_accessors_free(schema
);
328 /* count the classes */
329 for (i
=0, cur
=schema
->classes
; cur
; i
++, cur
=cur
->next
) /* noop */ ;
330 schema
->num_classes
= i
;
332 /* setup classes_by_* */
333 schema
->classes_by_lDAPDisplayName
= talloc_array(schema
, struct dsdb_class
*, i
);
334 schema
->classes_by_governsID_id
= talloc_array(schema
, struct dsdb_class
*, i
);
335 schema
->classes_by_governsID_oid
= talloc_array(schema
, struct dsdb_class
*, i
);
336 schema
->classes_by_cn
= talloc_array(schema
, struct dsdb_class
*, i
);
337 if (schema
->classes_by_lDAPDisplayName
== NULL
||
338 schema
->classes_by_governsID_id
== NULL
||
339 schema
->classes_by_governsID_oid
== NULL
||
340 schema
->classes_by_cn
== NULL
) {
344 for (i
=0, cur
=schema
->classes
; cur
; i
++, cur
=cur
->next
) {
345 schema
->classes_by_lDAPDisplayName
[i
] = cur
;
346 schema
->classes_by_governsID_id
[i
] = cur
;
347 schema
->classes_by_governsID_oid
[i
] = cur
;
348 schema
->classes_by_cn
[i
] = cur
;
351 /* sort the arrays */
352 TYPESAFE_QSORT(schema
->classes_by_lDAPDisplayName
, schema
->num_classes
, dsdb_compare_class_by_lDAPDisplayName
);
353 TYPESAFE_QSORT(schema
->classes_by_governsID_id
, schema
->num_classes
, dsdb_compare_class_by_governsID_id
);
354 TYPESAFE_QSORT(schema
->classes_by_governsID_oid
, schema
->num_classes
, dsdb_compare_class_by_governsID_oid
);
355 TYPESAFE_QSORT(schema
->classes_by_cn
, schema
->num_classes
, dsdb_compare_class_by_cn
);
357 /* now build the attribute accessor arrays */
359 /* count the attributes
360 * and attributes with msDS-IntId set */
362 for (i
=0, a
=schema
->attributes
; a
; i
++, a
=a
->next
) {
363 if (a
->msDS_IntId
!= 0) {
367 schema
->num_attributes
= i
;
368 schema
->num_int_id_attr
= num_int_id
;
370 /* setup attributes_by_* */
371 schema
->attributes_by_lDAPDisplayName
= talloc_array(schema
, struct dsdb_attribute
*, i
);
372 schema
->attributes_by_attributeID_id
= talloc_array(schema
, struct dsdb_attribute
*, i
);
373 schema
->attributes_by_msDS_IntId
= talloc_array(schema
,
374 struct dsdb_attribute
*, num_int_id
);
375 schema
->attributes_by_attributeID_oid
= talloc_array(schema
, struct dsdb_attribute
*, i
);
376 schema
->attributes_by_linkID
= talloc_array(schema
, struct dsdb_attribute
*, i
);
377 if (schema
->attributes_by_lDAPDisplayName
== NULL
||
378 schema
->attributes_by_attributeID_id
== NULL
||
379 schema
->attributes_by_msDS_IntId
== NULL
||
380 schema
->attributes_by_attributeID_oid
== NULL
||
381 schema
->attributes_by_linkID
== NULL
) {
386 for (i
=0, a
=schema
->attributes
; a
; i
++, a
=a
->next
) {
387 schema
->attributes_by_lDAPDisplayName
[i
] = a
;
388 schema
->attributes_by_attributeID_id
[i
] = a
;
389 schema
->attributes_by_attributeID_oid
[i
] = a
;
390 schema
->attributes_by_linkID
[i
] = a
;
391 /* append attr-by-msDS-IntId values */
392 if (a
->msDS_IntId
!= 0) {
393 schema
->attributes_by_msDS_IntId
[num_int_id
] = a
;
397 SMB_ASSERT(num_int_id
== schema
->num_int_id_attr
);
399 /* sort the arrays */
400 TYPESAFE_QSORT(schema
->attributes_by_lDAPDisplayName
, schema
->num_attributes
, dsdb_compare_attribute_by_lDAPDisplayName
);
401 TYPESAFE_QSORT(schema
->attributes_by_attributeID_id
, schema
->num_attributes
, dsdb_compare_attribute_by_attributeID_id
);
402 TYPESAFE_QSORT(schema
->attributes_by_msDS_IntId
, schema
->num_int_id_attr
, dsdb_compare_attribute_by_msDS_IntId
);
403 TYPESAFE_QSORT(schema
->attributes_by_attributeID_oid
, schema
->num_attributes
, dsdb_compare_attribute_by_attributeID_oid
);
404 TYPESAFE_QSORT(schema
->attributes_by_linkID
, schema
->num_attributes
, dsdb_compare_attribute_by_linkID
);
406 dsdb_setup_attribute_shortcuts(ldb
, schema
);
411 dsdb_sorted_accessors_free(schema
);
415 int dsdb_setup_schema_inversion(struct ldb_context
*ldb
, struct dsdb_schema
*schema
)
417 /* Walk the list of schema classes */
419 /* For each subClassOf, add us to subclasses of the parent */
421 /* collect these subclasses into a recursive list of total subclasses, preserving order */
423 /* For each subclass under 'top', write the index from it's
424 * order as an integer in the dsdb_class (for sorting
425 * objectClass lists efficiently) */
427 /* Walk the list of schema classes */
429 /* Create a 'total possible superiors' on each class */
434 * Attach the schema to an opaque pointer on the ldb,
435 * so ldb modules can find it
437 int dsdb_set_schema(struct ldb_context
*ldb
, struct dsdb_schema
*schema
)
439 struct dsdb_schema
*old_schema
;
442 ret
= dsdb_setup_sorted_accessors(ldb
, schema
);
443 if (ret
!= LDB_SUCCESS
) {
447 ret
= schema_fill_constructed(schema
);
448 if (ret
!= LDB_SUCCESS
) {
452 old_schema
= ldb_get_opaque(ldb
, "dsdb_schema");
454 ret
= ldb_set_opaque(ldb
, "dsdb_schema", schema
);
455 if (ret
!= LDB_SUCCESS
) {
459 /* Remove the reference to the schema we just overwrote - if there was
460 * none, NULL is harmless here */
461 if (old_schema
!= schema
) {
462 talloc_unlink(ldb
, old_schema
);
463 talloc_steal(ldb
, schema
);
466 ret
= ldb_set_opaque(ldb
, "dsdb_use_global_schema", NULL
);
467 if (ret
!= LDB_SUCCESS
) {
471 /* Set the new attributes based on the new schema */
472 ret
= dsdb_schema_set_attributes(ldb
, schema
, true);
473 if (ret
!= LDB_SUCCESS
) {
481 * Global variable to hold one copy of the schema, used to avoid memory bloat
483 static struct dsdb_schema
*global_schema
;
486 * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
488 int dsdb_reference_schema(struct ldb_context
*ldb
, struct dsdb_schema
*schema
,
489 bool write_attributes
)
492 struct dsdb_schema
*old_schema
;
493 old_schema
= ldb_get_opaque(ldb
, "dsdb_schema");
494 ret
= ldb_set_opaque(ldb
, "dsdb_schema", schema
);
495 if (ret
!= LDB_SUCCESS
) {
499 /* Remove the reference to the schema we just overwrote - if there was
500 * none, NULL is harmless here */
501 talloc_unlink(ldb
, old_schema
);
503 if (talloc_reference(ldb
, schema
) == NULL
) {
507 /* Make this ldb use local schema preferably */
508 ret
= ldb_set_opaque(ldb
, "dsdb_use_global_schema", NULL
);
509 if (ret
!= LDB_SUCCESS
) {
513 ret
= dsdb_schema_set_attributes(ldb
, schema
, write_attributes
);
514 if (ret
!= LDB_SUCCESS
) {
522 * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
524 int dsdb_set_global_schema(struct ldb_context
*ldb
)
527 void *use_global_schema
= (void *)1;
528 if (!global_schema
) {
531 ret
= ldb_set_opaque(ldb
, "dsdb_use_global_schema", use_global_schema
);
532 if (ret
!= LDB_SUCCESS
) {
536 /* Set the new attributes based on the new schema */
537 ret
= dsdb_schema_set_attributes(ldb
, global_schema
, false /* Don't write attributes, it's expensive */);
538 if (ret
== LDB_SUCCESS
) {
539 /* Keep a reference to this schema, just in case the original copy is replaced */
540 if (talloc_reference(ldb
, global_schema
) == NULL
) {
548 bool dsdb_uses_global_schema(struct ldb_context
*ldb
)
550 return (ldb_get_opaque(ldb
, "dsdb_use_global_schema") != NULL
);
554 * Find the schema object for this ldb
556 * If reference_ctx is not NULL, then talloc_reference onto that context
559 struct dsdb_schema
*dsdb_get_schema(struct ldb_context
*ldb
, TALLOC_CTX
*reference_ctx
)
562 struct dsdb_schema
*schema_out
;
563 struct dsdb_schema
*schema_in
;
564 bool use_global_schema
;
565 TALLOC_CTX
*tmp_ctx
= talloc_new(reference_ctx
);
570 /* see if we have a cached copy */
571 use_global_schema
= dsdb_uses_global_schema(ldb
);
572 if (use_global_schema
) {
573 schema_in
= global_schema
;
575 p
= ldb_get_opaque(ldb
, "dsdb_schema");
577 schema_in
= talloc_get_type(p
, struct dsdb_schema
);
579 talloc_free(tmp_ctx
);
584 if (schema_in
->refresh_fn
&& !schema_in
->refresh_in_progress
) {
585 if (!talloc_reference(tmp_ctx
, schema_in
)) {
587 * ensure that the schema_in->refresh_in_progress
588 * remains valid for the right amount of time
590 talloc_free(tmp_ctx
);
593 schema_in
->refresh_in_progress
= true;
594 /* This may change schema, if it needs to reload it from disk */
595 schema_out
= schema_in
->refresh_fn(schema_in
->loaded_from_module
,
598 schema_in
->refresh_in_progress
= false;
600 schema_out
= schema_in
;
603 /* This removes the extra reference above */
604 talloc_free(tmp_ctx
);
605 if (!reference_ctx
) {
608 return talloc_reference(reference_ctx
, schema_out
);
613 * Make the schema found on this ldb the 'global' schema
616 void dsdb_make_schema_global(struct ldb_context
*ldb
, struct dsdb_schema
*schema
)
623 talloc_unlink(talloc_autofree_context(), global_schema
);
626 /* we want the schema to be around permanently */
627 talloc_reparent(ldb
, talloc_autofree_context(), schema
);
628 global_schema
= schema
;
630 /* This calls the talloc_reference() of the global schema back onto the ldb */
631 dsdb_set_global_schema(ldb
);
635 * When loading the schema from LDIF files, we don't get the extended DNs.
637 * We need to set these up, so that from the moment we start the provision,
638 * the defaultObjectCategory links are set up correctly.
640 int dsdb_schema_fill_extended_dn(struct ldb_context
*ldb
, struct dsdb_schema
*schema
)
642 struct dsdb_class
*cur
;
643 const struct dsdb_class
*target_class
;
644 for (cur
= schema
->classes
; cur
; cur
= cur
->next
) {
645 const struct ldb_val
*rdn
;
648 struct ldb_dn
*dn
= ldb_dn_new(NULL
, ldb
, cur
->defaultObjectCategory
);
651 return LDB_ERR_INVALID_DN_SYNTAX
;
653 rdn
= ldb_dn_get_component_val(dn
, 0);
656 return LDB_ERR_INVALID_DN_SYNTAX
;
658 target_class
= dsdb_class_by_cn_ldb_val(schema
, rdn
);
661 return LDB_ERR_CONSTRAINT_VIOLATION
;
664 status
= GUID_to_ndr_blob(&target_class
->objectGUID
, dn
, &guid
);
665 if (!NT_STATUS_IS_OK(status
)) {
667 return ldb_operr(ldb
);
669 ldb_dn_set_extended_component(dn
, "GUID", &guid
);
671 cur
->defaultObjectCategory
= ldb_dn_get_extended_linearized(cur
, dn
, 1);
678 * Add an element to the schema (attribute or class) from an LDB message
680 WERROR
dsdb_schema_set_el_from_ldb_msg(struct ldb_context
*ldb
, struct dsdb_schema
*schema
,
681 struct ldb_message
*msg
)
683 if (samdb_find_attribute(ldb
, msg
,
684 "objectclass", "attributeSchema") != NULL
) {
685 return dsdb_attribute_from_ldb(ldb
, schema
, msg
);
686 } else if (samdb_find_attribute(ldb
, msg
,
687 "objectclass", "classSchema") != NULL
) {
688 return dsdb_class_from_ldb(schema
, msg
);
691 /* Don't fail on things not classes or attributes */
696 * Rather than read a schema from the LDB itself, read it from an ldif
697 * file. This allows schema to be loaded and used while adding the
698 * schema itself to the directory.
701 WERROR
dsdb_set_schema_from_ldif(struct ldb_context
*ldb
, const char *pf
, const char *df
)
703 struct ldb_ldif
*ldif
;
704 struct ldb_message
*msg
;
708 struct dsdb_schema
*schema
;
709 const struct ldb_val
*prefix_val
;
710 const struct ldb_val
*info_val
;
711 struct ldb_val info_val_default
;
714 mem_ctx
= talloc_new(ldb
);
719 schema
= dsdb_new_schema(mem_ctx
);
721 schema
->fsmo
.we_are_master
= true;
722 schema
->fsmo
.master_dn
= ldb_dn_new_fmt(schema
, ldb
, "@PROVISION_SCHEMA_MASTER");
723 if (!schema
->fsmo
.master_dn
) {
728 * load the prefixMap attribute from pf
730 ldif
= ldb_ldif_read_string(ldb
, &pf
);
732 status
= WERR_INVALID_PARAM
;
735 talloc_steal(mem_ctx
, ldif
);
737 ret
= ldb_msg_normalize(ldb
, mem_ctx
, ldif
->msg
, &msg
);
738 if (ret
!= LDB_SUCCESS
) {
743 prefix_val
= ldb_msg_find_ldb_val(msg
, "prefixMap");
745 status
= WERR_INVALID_PARAM
;
749 info_val
= ldb_msg_find_ldb_val(msg
, "schemaInfo");
751 status
= dsdb_schema_info_blob_new(mem_ctx
, &info_val_default
);
752 W_ERROR_NOT_OK_GOTO(status
, failed
);
753 info_val
= &info_val_default
;
756 status
= dsdb_load_oid_mappings_ldb(schema
, prefix_val
, info_val
);
757 if (!W_ERROR_IS_OK(status
)) {
758 DEBUG(0,("ERROR: dsdb_load_oid_mappings_ldb() failed with %s\n", win_errstr(status
)));
762 /* load the attribute and class definitions out of df */
763 while ((ldif
= ldb_ldif_read_string(ldb
, &df
))) {
764 talloc_steal(mem_ctx
, ldif
);
766 ret
= ldb_msg_normalize(ldb
, ldif
, ldif
->msg
, &msg
);
767 if (ret
!= LDB_SUCCESS
) {
771 status
= dsdb_schema_set_el_from_ldb_msg(ldb
, schema
, msg
);
773 if (!W_ERROR_IS_OK(status
)) {
778 ret
= dsdb_set_schema(ldb
, schema
);
779 if (ret
!= LDB_SUCCESS
) {
780 status
= WERR_FOOBAR
;
784 ret
= dsdb_schema_fill_extended_dn(ldb
, schema
);
785 if (ret
!= LDB_SUCCESS
) {
786 status
= WERR_FOOBAR
;
796 talloc_free(mem_ctx
);