diff options
Diffstat (limited to 'source4/dsdb/schema/schema_init.c')
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 559 |
1 files changed, 13 insertions, 546 deletions
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 85fdbe9e87..3ed7daee59 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -809,7 +809,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 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"); @@ -828,7 +827,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, *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; } @@ -847,7 +845,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, "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; } @@ -869,7 +866,6 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, "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; } @@ -914,7 +910,6 @@ static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn, "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", name, name); if (ret != LDB_SUCCESS) { - printf("Search failed: %s\n", ldb_errstring(ldb)); return ret; } @@ -940,7 +935,8 @@ static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn, static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, TALLOC_CTX *mem_ctx, - struct ldb_result **objectclasses_res) + struct ldb_result **objectclasses_res, + char **error_string) { TALLOC_CTX *local_ctx = talloc_new(mem_ctx); struct ldb_result *top_res, *ret_res; @@ -949,19 +945,23 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche return LDB_ERR_OPERATIONS_ERROR; } - /* Downlaod 'top' */ + /* Download '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; + *error_string = talloc_asprintf(mem_ctx, + "dsdb_schema: failed to search for top classSchema object: %s", + ldb_errstring(ldb)); + return ret; } talloc_steal(local_ctx, top_res); if (top_res->count != 1) { - return LDB_ERR_OPERATIONS_ERROR; + *error_string = talloc_asprintf(mem_ctx, + "dsdb_schema: failed to find top classSchema object"); + return LDB_ERR_NO_SUCH_OBJECT; } ret_res = talloc_zero(local_ctx, struct ldb_result); @@ -972,8 +972,7 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche 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; + return ret; } *objectclasses_res = talloc_move(mem_ctx, &ret_res); @@ -1051,10 +1050,10 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, /* * load the objectClass definitions */ - ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res); + ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res, &error_string); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, - "Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb)); + "Failed to fetch objectClass schema elements: %s", error_string); talloc_free(tmp_ctx); return ret; } @@ -1410,535 +1409,3 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema, return WERR_OK; } -const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema, - uint32_t id) -{ - struct dsdb_attribute *cur; - - /* - * 0xFFFFFFFF is used as value when no mapping table is available, - * so don't try to match with it - */ - if (id == 0xFFFFFFFF) return NULL; - - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (cur->attributeID_id != id) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema, - const char *oid) -{ - struct dsdb_attribute *cur; - - if (!oid) return NULL; - - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (strcmp(cur->attributeID_oid, oid) != 0) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema, - const char *name) -{ - struct dsdb_attribute *cur; - - if (!name) return NULL; - - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema, - int linkID) -{ - struct dsdb_attribute *cur; - - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (cur->linkID != linkID) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema, - uint32_t id) -{ - struct dsdb_class *cur; - - /* - * 0xFFFFFFFF is used as value when no mapping table is available, - * so don't try to match with it - */ - if (id == 0xFFFFFFFF) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (cur->governsID_id != id) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema, - const char *oid) -{ - struct dsdb_class *cur; - - if (!oid) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcmp(cur->governsID_oid, oid) != 0) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema, - const char *name) -{ - struct dsdb_class *cur; - - if (!name) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue; - - return cur; - } - - return NULL; -} - -const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema, - const char *cn) -{ - struct dsdb_class *cur; - - if (!cn) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcasecmp(cur->cn, cn) != 0) continue; - - return cur; - } - - return NULL; -} - -const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, - uint32_t id) -{ - const struct dsdb_attribute *a; - const struct dsdb_class *c; - - /* TODO: add binary search */ - a = dsdb_attribute_by_attributeID_id(schema, id); - if (a) { - return a->lDAPDisplayName; - } - - c = dsdb_class_by_governsID_id(schema, id); - if (c) { - return c->lDAPDisplayName; - } - - 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; - struct dsdb_attribute *cur; - int i = 0; - for (cur = schema->attributes; cur; cur = cur->next) { - if (cur->linkID == 0) continue; - - attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2); - if (!attr_list) { - return WERR_NOMEM; - } - attr_list[i] = cur->lDAPDisplayName; - i++; - } - attr_list[i] = NULL; - *attr_list_ret = attr_list; - 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, - const 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; - - case DSDB_SCHEMA_ALL: - attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain); - attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain); - attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain); - attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain); - 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, - const 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; - - ret = ldb_set_opaque(ldb, "dsdb_schema", schema); - if (ret != LDB_SUCCESS) { - return ret; - } - - talloc_steal(ldb, schema); - - 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; - if (!global_schema) { - return LDB_SUCCESS; - } - ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema); - if (ret != LDB_SUCCESS) { - return ret; - } - - /* Keep a reference to this schema, just incase the global copy is replaced */ - if (talloc_reference(ldb, global_schema) == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - - return LDB_SUCCESS; -} - -/** - * Find the schema object for this ldb - */ - -struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb) -{ - const void *p; - struct dsdb_schema *schema; - - /* see if we have a cached copy */ - p = ldb_get_opaque(ldb, "dsdb_schema"); - if (!p) { - return NULL; - } - - schema = talloc_get_type(p, struct dsdb_schema); - if (!schema) { - return NULL; - } - - return schema; -} - -/** - * Make the schema found on this ldb the 'global' schema - */ - -void dsdb_make_schema_global(struct ldb_context *ldb) -{ - struct dsdb_schema *schema = dsdb_get_schema(ldb); - if (!schema) { - return; - } - - if (global_schema) { - talloc_unlink(talloc_autofree_context(), schema); - } - - talloc_steal(talloc_autofree_context(), schema); - global_schema = schema; - - 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; - struct ldb_message *msg; - TALLOC_CTX *mem_ctx; - WERROR status; - int ret; - struct dsdb_schema *schema; - const struct ldb_val *prefix_val; - const struct ldb_val *info_val; - struct ldb_val info_val_default; - - mem_ctx = talloc_new(ldb); - if (!mem_ctx) { - goto nomem; - } - - 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; - } - - /* - * load the prefixMap attribute from pf - */ - ldif = ldb_ldif_read_string(ldb, &pf); - if (!ldif) { - status = WERR_INVALID_PARAM; - goto failed; - } - talloc_steal(mem_ctx, ldif); - - msg = ldb_msg_canonicalize(ldb, ldif->msg); - if (!msg) { - goto nomem; - } - talloc_steal(mem_ctx, msg); - talloc_free(ldif); - - prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap"); - if (!prefix_val) { - status = WERR_INVALID_PARAM; - goto failed; - } - - info_val = ldb_msg_find_ldb_val(msg, "schemaInfo"); - if (!info_val) { - info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000"); - if (!info_val_default.data) { - goto nomem; - } - 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)) { - goto failed; - } - - /* - * load the attribute and class definitions outof df - */ - while ((ldif = ldb_ldif_read_string(ldb, &df))) { - bool is_sa; - bool is_sc; - - talloc_steal(mem_ctx, ldif); - - msg = ldb_msg_canonicalize(ldb, ldif->msg); - if (!msg) { - 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"); - - if (is_sa) { - struct dsdb_attribute *sa; - - sa = talloc_zero(schema, struct dsdb_attribute); - if (!sa) { - goto nomem; - } - - status = dsdb_attribute_from_ldb(schema, msg, sa, sa); - if (!W_ERROR_IS_OK(status)) { - goto failed; - } - - DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *); - } else if (is_sc) { - struct dsdb_class *sc; - - sc = talloc_zero(schema, struct dsdb_class); - if (!sc) { - goto nomem; - } - - status = dsdb_class_from_ldb(schema, msg, sc, sc); - if (!W_ERROR_IS_OK(status)) { - goto failed; - } - - DLIST_ADD_END(schema->classes, sc, struct dsdb_class *); - } - } - - ret = dsdb_set_schema(ldb, schema); - if (ret != LDB_SUCCESS) { - status = WERR_FOOBAR; - goto failed; - } - - goto done; - -nomem: - status = WERR_NOMEM; -failed: -done: - talloc_free(mem_ctx); - return status; -} |