struct ldb_context *ldb = ldb_module_get_ctx(module);
TALLOC_CTX *tmp_ctx;
char *error_string;
- int ret;
+ int ret, i;
struct ldb_dn *schema_dn = ldb_get_schema_basedn(ldb);
- struct ldb_result *schema_res;
struct ldb_result *res;
- static const char *schema_head_attrs[] = {
- "prefixMap",
- "schemaInfo",
- "fSMORoleOwner",
- NULL
- };
+ struct ldb_message *schema_msg = NULL;
static const char *schema_attrs[] = {
DSDB_SCHEMA_COMMON_ATTRS,
DSDB_SCHEMA_ATTR_ATTRS,
DSDB_SCHEMA_CLASS_ATTRS,
+ "prefixMap",
+ "schemaInfo",
+ "fSMORoleOwner",
NULL
};
unsigned flags;
ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
/*
- * setup the prefix mappings and schema info
- */
- ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
- schema_dn, schema_head_attrs,
- DSDB_FLAG_NEXT_MODULE, NULL);
- if (ret == LDB_ERR_NO_SUCH_OBJECT) {
- ldb_reset_err_string(ldb);
- ldb_debug(ldb, LDB_DEBUG_WARNING,
- "schema_load_init: no schema head present: (skip schema loading)\n");
- goto failed;
- } else if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb,
- "dsdb_schema: failed to search the schema head: %s",
- ldb_errstring(ldb));
- goto failed;
- }
-
- /*
- * load the attribute definitions.
+ * Load the attribute and class definitions, as well as
+ * the schema object. We do this in one search and then
+ * split it so that there isn't a race condition when
+ * the schema is changed between two searches.
*/
ret = dsdb_module_search(module, tmp_ctx, &res,
- schema_dn, LDB_SCOPE_ONELEVEL,
+ schema_dn, LDB_SCOPE_SUBTREE,
schema_attrs,
DSDB_FLAG_NEXT_MODULE |
DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT,
NULL,
- "(|(objectClass=attributeSchema)(objectClass=classSchema))");
+ "(|(objectClass=attributeSchema)"
+ "(objectClass=classSchema)"
+ "(objectClass=dMD))");
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb,
"dsdb_schema: failed to search attributeSchema and classSchema objects: %s",
goto failed;
}
+ /*
+ * Separate the schema object from the attribute and
+ * class objects.
+ */
+ for (i = 0; i < res->count; i++) {
+ if (ldb_msg_find_element(res->msgs[i], "prefixMap")) {
+ schema_msg = res->msgs[i];
+ break;
+ }
+ }
+
+ if (schema_msg == NULL) {
+ ldb_asprintf_errstring(ldb,
+ "dsdb_schema load failed: failed to find prefixMap");
+ ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
+ goto failed;
+ }
+
ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
- schema_res, res, schema, &error_string);
+ schema_msg, res, schema, &error_string);
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb,
"dsdb_schema load failed: %s",
char **error_string)
{
unsigned int i;
+ WERROR status;
schema->ts_last_change = 0;
for (i=0; i < attrs_class_res->count; i++) {
- WERROR status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, attrs_class_res->msgs[i]);
+ const char *prefixMap = NULL;
+ /*
+ * attrs_class_res also includes the schema object;
+ * we only want to process classes & attributes
+ */
+ prefixMap = ldb_msg_find_attr_as_string(
+ attrs_class_res->msgs[i],
+ "prefixMap", NULL);
+ if (prefixMap != NULL) {
+ continue;
+ }
+
+ status = dsdb_schema_set_el_from_ldb_msg(ldb, schema,
+ attrs_class_res->msgs[i]);
if (!W_ERROR_IS_OK(status)) {
*error_string = talloc_asprintf(mem_ctx,
"dsdb_load_ldb_results_into_schema: failed to load attribute or class definition: %s:%s",
*/
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
- struct ldb_result *schema_res,
+ struct ldb_message *schema_msg,
struct ldb_result *attrs_class_res,
struct dsdb_schema **schema_out,
char **error_string)
false);
}
- prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
+ prefix_val = ldb_msg_find_ldb_val(schema_msg, "prefixMap");
if (!prefix_val) {
*error_string = talloc_asprintf(mem_ctx,
"schema_fsmo_init: no prefixMap attribute found");
talloc_free(tmp_ctx);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
+ info_val = ldb_msg_find_ldb_val(schema_msg, "schemaInfo");
if (!info_val) {
status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
if (!W_ERROR_IS_OK(status)) {
return ret;
}
- schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
+ schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_msg, "fSMORoleOwner");
if (ldb_dn_compare(samdb_ntds_settings_dn(ldb, tmp_ctx), schema->fsmo.master_dn) == 0) {
schema->fsmo.we_are_master = true;
} else {