Unix SMB/CIFS mplementation.
DSDB schema header
- Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
-
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_drsuapi.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "param/param.h"
+
+struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience)
+{
+ struct dsdb_schema *schema = talloc_zero(mem_ctx, struct dsdb_schema);
+ if (!schema) {
+ return NULL;
+ }
+
+ schema->iconv_convenience = iconv_convenience;
+ return schema;
+}
+
WERROR dsdb_load_oid_mappings_drsuapi(struct dsdb_schema *schema, const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
{
struct prefixMapBlob pfm;
char *schema_info;
- ndr_err = ndr_pull_struct_blob(prefixMap, schema, &pfm,
- (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+ TALLOC_CTX *mem_ctx = talloc_new(schema);
+ W_ERROR_HAVE_NO_MEMORY(mem_ctx);
+
+ ndr_err = ndr_pull_struct_blob(prefixMap, mem_ctx, schema->iconv_convenience, &pfm, (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
+ talloc_free(mem_ctx);
return ntstatus_to_werror(nt_status);
}
if (pfm.version != PREFIX_MAP_VERSION_DSDB) {
+ talloc_free(mem_ctx);
return WERR_FOOBAR;
}
if (schemaInfo->length != 21 && schemaInfo->data[0] == 0xFF) {
+ talloc_free(mem_ctx);
return WERR_FOOBAR;
}
/* append the schema info as last element */
pfm.ctr.dsdb.num_mappings++;
- pfm.ctr.dsdb.mappings = talloc_realloc(schema, pfm.ctr.dsdb.mappings,
+ pfm.ctr.dsdb.mappings = talloc_realloc(mem_ctx, pfm.ctr.dsdb.mappings,
struct drsuapi_DsReplicaOIDMapping,
pfm.ctr.dsdb.num_mappings);
W_ERROR_HAVE_NO_MEMORY(pfm.ctr.dsdb.mappings);
/* call the drsuapi version */
status = dsdb_load_oid_mappings_drsuapi(schema, &pfm.ctr.dsdb);
- talloc_free(pfm.ctr.dsdb.mappings);
+ talloc_free(mem_ctx);
+
W_ERROR_NOT_OK_RETURN(status);
return WERR_OK;
pfm.reserved = 0;
pfm.ctr.dsdb = *ctr;
- ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, &pfm,
- (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
+ ndr_err = ndr_push_struct_blob(prefixMap, mem_ctx, schema->iconv_convenience, &pfm, (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
talloc_free(ctr);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
return WERR_DS_NO_MSDS_INTID;
}
+/*
+ * this function is called from within a ldb transaction from the schema_fsmo module
+ */
+WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+{
+ /*
+ * TODO:
+ * - (maybe) read the old prefixMap attribute and parse it
+ *
+ * - recheck the prefix doesn't exist (because the ldb
+ * has maybe a more uptodate value than schem->prefixes
+ *
+ * - calculate a new mapping for the oid prefix of full_oid
+ * - store the new prefixMap attribute
+ *
+ * - (maybe) update schema->prefixes
+ * or
+ * - better find a way to indicate a schema reload,
+ * so that other processes also notice the schema change
+ */
+ return WERR_NOT_SUPPORTED;
+}
+
#define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
(p)->elem = samdb_result_string(msg, attr, NULL);\
if (strict && (p)->elem == NULL) { \
GET_STRING_LDB(msg, "subClassOf", mem_ctx, obj, subClassOf, true);
- obj->systemAuxiliaryClass = NULL;
-
- obj->auxiliaryClass = NULL;
+ GET_STRING_LIST_LDB(msg, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass, false);
+ GET_STRING_LIST_LDB(msg, "auxiliaryClass", mem_ctx, obj, auxiliaryClass, false);
GET_STRING_LIST_LDB(msg, "systemMustContain", mem_ctx, obj, systemMustContain, false);
GET_STRING_LIST_LDB(msg, "systemMayContain", mem_ctx, obj, systemMayContain, false);
return WERR_OK;
}
+#define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__)
+
+int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+ struct smb_iconv_convenience *iconv_convenience,
+ struct ldb_result *schema_res,
+ struct ldb_result *attrs_res, struct ldb_result *objectclass_res,
+ struct dsdb_schema **schema_out,
+ char **error_string)
+{
+ WERROR status;
+ uint32_t i;
+ const struct ldb_val *prefix_val;
+ const struct ldb_val *info_val;
+ struct ldb_val info_val_default;
+ struct dsdb_schema *schema;
+
+ schema = dsdb_new_schema(mem_ctx, iconv_convenience);
+ if (!schema) {
+ dsdb_oom(error_string, mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
+ if (!prefix_val) {
+ *error_string = talloc_asprintf(mem_ctx,
+ "schema_fsmo_init: no prefixMap attribute found");
+ talloc_free(mem_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
+ if (!info_val) {
+ info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
+ if (!info_val_default.data) {
+ dsdb_oom(error_string, mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ talloc_steal(mem_ctx, info_val_default.data);
+ info_val = &info_val_default;
+ }
+
+ status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
+ if (!W_ERROR_IS_OK(status)) {
+ *error_string = talloc_asprintf(mem_ctx,
+ "schema_fsmo_init: failed to load oid mappings: %s",
+ win_errstr(status));
+ talloc_free(mem_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ for (i=0; i < attrs_res->count; i++) {
+ struct dsdb_attribute *sa;
+
+ sa = talloc_zero(schema, struct dsdb_attribute);
+ if (!sa) {
+ dsdb_oom(error_string, mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ status = dsdb_attribute_from_ldb(schema, attrs_res->msgs[i], sa, sa);
+ if (!W_ERROR_IS_OK(status)) {
+ *error_string = talloc_asprintf(mem_ctx,
+ "schema_fsmo_init: failed to load attribute definition: %s:%s",
+ ldb_dn_get_linearized(attrs_res->msgs[i]->dn),
+ win_errstr(status));
+ talloc_free(mem_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
+ }
+
+ for (i=0; i < objectclass_res->count; i++) {
+ struct dsdb_class *sc;
+
+ sc = talloc_zero(schema, struct dsdb_class);
+ if (!sc) {
+ dsdb_oom(error_string, mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ status = dsdb_class_from_ldb(schema, objectclass_res->msgs[i], sc, sc);
+ if (!W_ERROR_IS_OK(status)) {
+ *error_string = talloc_asprintf(mem_ctx,
+ "schema_fsmo_init: failed to load class definition: %s:%s",
+ ldb_dn_get_linearized(objectclass_res->msgs[i]->dn),
+ win_errstr(status));
+ talloc_free(mem_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
+ }
+
+ schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
+ if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) {
+ schema->fsmo.we_are_master = true;
+ } else {
+ schema->fsmo.we_are_master = false;
+ }
+
+ DEBUG(5, ("schema_fsmo_init: we are master: %s\n",
+ (schema->fsmo.we_are_master?"yes":"no")));
+
+ *schema_out = schema;
+ return LDB_SUCCESS;
+}
+
+/* This recursive load of the objectClasses presumes that they
+ * everything is in a strict subClassOf hirarchy.
+ *
+ * We load this in order so we produce certain outputs (such as the
+ * exported schema for openldap, and sorted objectClass attribute) 'in
+ * order' */
+
+static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result *search_from,
+ struct ldb_result *res_list)
+{
+ int i;
+ int ret = 0;
+ for (i=0; i < search_from->count; i++) {
+ struct ldb_result *res;
+ const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i],
+ "lDAPDisplayname", NULL);
+
+ ret = ldb_search_exp_fmt(ldb, mem_ctx, &res,
+ schemadn, LDB_SCOPE_SUBTREE, NULL,
+ "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))",
+ name, name);
+ if (ret != LDB_SUCCESS) {
+ printf("Search failed: %s\n", ldb_errstring(ldb));
+ return ret;
+ }
+
+ res_list->msgs = talloc_realloc(res_list, res_list->msgs,
+ struct ldb_message *, res_list->count + 2);
+ if (!res_list->msgs) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ res_list->msgs[res_list->count] = talloc_move(res_list,
+ &search_from->msgs[i]);
+ res_list->count++;
+ res_list->msgs[res_list->count] = NULL;
+
+ if (res->count > 0) {
+ ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list);
+ }
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **objectclasses_res)
+{
+ TALLOC_CTX *local_ctx = talloc_new(mem_ctx);
+ struct ldb_result *top_res, *ret_res;
+ int ret;
+ if (!local_ctx) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* Downlaod 'top' */
+ ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,
+ "(&(objectClass=classSchema)(lDAPDisplayName=top))",
+ NULL, &top_res);
+ if (ret != LDB_SUCCESS) {
+ printf("Search failed: %s\n", ldb_errstring(ldb));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_steal(local_ctx, top_res);
+
+ if (top_res->count != 1) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret_res = talloc_zero(local_ctx, struct ldb_result);
+ if (!ret_res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res);
+
+ if (ret != LDB_SUCCESS) {
+ printf("Search failed: %s\n", ldb_errstring(ldb));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ *objectclasses_res = talloc_move(mem_ctx, &ret_res);
+ return ret;
+}
+
+int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+ struct smb_iconv_convenience *iconv_convenience,
+ struct ldb_dn *schema_dn,
+ struct dsdb_schema **schema,
+ char **error_string_out)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *error_string;
+ int ret;
+
+ struct ldb_result *schema_res;
+ struct ldb_result *a_res;
+ struct ldb_result *c_res;
+ static const char *schema_attrs[] = {
+ "prefixMap",
+ "schemaInfo",
+ "fSMORoleOwner",
+ NULL
+ };
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ dsdb_oom(error_string_out, mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /*
+ * setup the prefix mappings and schema info
+ */
+ ret = ldb_search(ldb, schema_dn,
+ LDB_SCOPE_BASE,
+ NULL, schema_attrs,
+ &schema_res);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ return ret;
+ } else if (ret != LDB_SUCCESS) {
+ *error_string_out = talloc_asprintf(mem_ctx,
+ "dsdb_schema: failed to search the schema head: %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ talloc_steal(tmp_ctx, schema_res);
+ if (schema_res->count != 1) {
+ *error_string_out = talloc_asprintf(mem_ctx,
+ "dsdb_schema: [%u] schema heads found on a base search",
+ schema_res->count);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ /*
+ * load the attribute definitions
+ */
+ ret = ldb_search(ldb, schema_dn,
+ LDB_SCOPE_ONELEVEL,
+ "(objectClass=attributeSchema)", NULL,
+ &a_res);
+ if (ret != LDB_SUCCESS) {
+ *error_string_out = talloc_asprintf(mem_ctx,
+ "dsdb_schema: failed to search attributeSchema objects: %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ talloc_steal(tmp_ctx, a_res);
+
+ /*
+ * load the objectClass definitions
+ */
+ ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res);
+ if (ret != LDB_SUCCESS) {
+ *error_string_out = talloc_asprintf(mem_ctx,
+ "Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ schema_res, a_res, c_res, schema, &error_string);
+ if (ret != LDB_SUCCESS) {
+ *error_string_out = talloc_asprintf(mem_ctx,
+ "dsdb_schema load failed: %s",
+ error_string);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ talloc_steal(mem_ctx, *schema);
+ talloc_free(tmp_ctx);
+
+ return LDB_SUCCESS;
+}
+
+
static const struct {
const char *name;
const char *oid;
} \
if (_a && _a->value_ctr.num_values >= 1) { \
ssize_t _ret; \
- _ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, \
+ _ret = convert_string_talloc(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \
_a->value_ctr.values[0].blob->data, \
_a->value_ctr.values[0].blob->length, \
(void **)discard_const(&(p)->elem)); \
struct drsuapi_DsReplicaObjectIdentifier3 _id3; \
enum ndr_err_code _ndr_err; \
_ndr_err = ndr_pull_struct_blob_all(_a->value_ctr.values[0].blob, \
- mem_ctx, &_id3,\
+ mem_ctx, s->iconv_convenience, &_id3,\
(ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);\
if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
NTSTATUS _nt_status = ndr_map_error2ntstatus(_ndr_err); \
&& _a->value_ctr.values[0].blob->length == 16) { \
enum ndr_err_code _ndr_err; \
_ndr_err = ndr_pull_struct_blob_all(_a->value_ctr.values[0].blob, \
- mem_ctx, &(p)->elem, \
+ mem_ctx, s->iconv_convenience, &(p)->elem, \
(ndr_pull_flags_fn_t)ndr_pull_GUID); \
if (!NDR_ERR_CODE_IS_SUCCESS(_ndr_err)) { \
NTSTATUS _nt_status = ndr_map_error2ntstatus(_ndr_err); \
return NULL;
}
+/**
+ Return a list of linked attributes, in lDAPDisplayName format.
+
+ This may be used to determine if a modification would require
+ backlinks to be updated, for example
+*/
+
WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
{
const char **attr_list = NULL;
return WERR_OK;
}
+static char **merge_attr_list(TALLOC_CTX *mem_ctx,
+ char **attrs, const char **new_attrs)
+{
+ char **ret_attrs;
+ int i;
+ size_t new_len, orig_len = str_list_length((const char **)attrs);
+ if (!new_attrs) {
+ return attrs;
+ }
+
+ ret_attrs = talloc_realloc(mem_ctx,
+ attrs, char *, orig_len + str_list_length(new_attrs) + 1);
+ if (ret_attrs) {
+ for (i=0; i < str_list_length(new_attrs); i++) {
+ ret_attrs[orig_len + i] = new_attrs[i];
+ }
+ new_len = orig_len + str_list_length(new_attrs);
+
+ ret_attrs[new_len] = NULL;
+
+ }
+
+ return ret_attrs;
+}
+
+char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, struct dsdb_schema *schema,
+ const char **class_list,
+ enum dsdb_attr_list_query query)
+{
+ int i;
+ const struct dsdb_class *class;
+
+ char **attr_list = NULL;
+ char **recursive_list;
+
+ for (i=0; class_list && class_list[i]; i++) {
+ class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
+
+ switch (query) {
+ case DSDB_SCHEMA_ALL_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+ break;
+
+ case DSDB_SCHEMA_ALL_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+ break;
+
+ case DSDB_SCHEMA_SYS_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+ break;
+
+ case DSDB_SCHEMA_SYS_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+ break;
+
+ case DSDB_SCHEMA_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+ break;
+
+ case DSDB_SCHEMA_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+ break;
+ }
+
+ recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
+ class->systemAuxiliaryClass,
+ query);
+
+ attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+
+ recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
+ class->auxiliaryClass,
+ query);
+
+ attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+
+ }
+ return attr_list;
+}
+
+char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, struct dsdb_schema *schema,
+ const char **class_list,
+ enum dsdb_attr_list_query query)
+{
+ char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
+ size_t new_len = str_list_length((const char **)attr_list);
+
+ /* Remove duplicates */
+ if (new_len > 1) {
+ int i;
+ qsort(attr_list, new_len,
+ sizeof(*attr_list),
+ (comparison_fn_t)strcasecmp);
+
+ for (i=1 ; i < new_len; i++) {
+ char **val1 = &attr_list[i-1];
+ char **val2 = &attr_list[i];
+ if (ldb_attr_cmp(*val1, *val2) == 0) {
+ memmove(val1, val2, (new_len - i) * sizeof( *attr_list));
+ new_len--;
+ i--;
+ }
+ }
+ }
+ return attr_list;
+}
+/**
+ * Attach the schema to an opaque pointer on the ldb, so ldb modules
+ * can find it
+ */
+
int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
{
int ret;
return LDB_SUCCESS;
}
+/**
+ * Global variable to hold one copy of the schema, used to avoid memory bloat
+ */
static struct dsdb_schema *global_schema;
+/**
+ * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ */
int dsdb_set_global_schema(struct ldb_context *ldb)
{
int ret;
return LDB_SUCCESS;
}
-const struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
+/**
+ * Find the schema object for this ldb
+ */
+
+struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
{
const void *p;
- const struct dsdb_schema *schema;
+ struct dsdb_schema *schema;
/* see if we have a cached copy */
p = ldb_get_opaque(ldb, "dsdb_schema");
return schema;
}
+/**
+ * Make the schema found on this ldb the 'global' schema
+ */
+
void dsdb_make_schema_global(struct ldb_context *ldb)
{
- const void *p;
- const struct dsdb_schema *schema;
-
- /* see if we have a cached copy */
- p = ldb_get_opaque(ldb, "dsdb_schema");
- if (!p) {
- return;
- }
-
- schema = talloc_get_type(p, struct dsdb_schema);
+ struct dsdb_schema *schema = dsdb_get_schema(ldb);
if (!schema) {
return;
}
dsdb_set_global_schema(ldb);
}
+
+/**
+ * Rather than read a schema from the LDB itself, read it from an ldif
+ * file. This allows schema to be loaded and used while adding the
+ * schema itself to the directory.
+ */
+
WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
{
struct ldb_ldif *ldif;
goto nomem;
}
- schema = talloc_zero(mem_ctx, struct dsdb_schema);
- if (!schema) {
+ schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
+
+ schema->fsmo.we_are_master = true;
+ schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
+ if (!schema->fsmo.master_dn) {
goto nomem;
}
if (!msg) {
goto nomem;
}
+ talloc_steal(mem_ctx, msg);
+ talloc_free(ldif);
prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
if (!prefix_val) {
goto nomem;
}
+ talloc_steal(mem_ctx, msg);
+ talloc_free(ldif);
+
is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");