From 83d90d6cd6029446f836774d7c68bc13ce9cd360 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 10 Jul 2008 15:52:44 +1000 Subject: Make ad2oLschema even simpler, by moving the heavy work into dsdb. This will allow the kludge_acl and schema code to leverage the same work. (We might even get schema validation soon! :-) Andrew Bartlett (This used to be commit cecd04ce1f8ce2af2fb654b3abc1499092405d60) --- source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 77 +----- source4/dsdb/schema/schema.h | 9 + source4/dsdb/schema/schema_init.c | 306 +++++++++++++++++++++++- source4/utils/ad2oLschema.c | 344 ++++----------------------- 4 files changed, 368 insertions(+), 368 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 6f65c199ba..a397228723 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -37,17 +37,8 @@ static int schema_fsmo_init(struct ldb_module *module) TALLOC_CTX *mem_ctx; struct ldb_dn *schema_dn; struct dsdb_schema *schema; - struct ldb_result *schema_res; - struct ldb_result *a_res; - struct ldb_result *c_res; char *error_string = NULL; int ret; - static const char *schema_attrs[] = { - "prefixMap", - "schemaInfo", - "fSMORoleOwner", - NULL - }; if (dsdb_get_schema(module->ldb)) { return ldb_next_init(module); @@ -67,83 +58,25 @@ static int schema_fsmo_init(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } - /* - * setup the prefix mappings and schema info - */ - ret = ldb_search(module->ldb, schema_dn, - LDB_SCOPE_BASE, - NULL, schema_attrs, - &schema_res); + ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb, + lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), + schema_dn, &schema, &error_string); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { ldb_reset_err_string(module->ldb); ldb_debug(module->ldb, LDB_DEBUG_WARNING, "schema_fsmo_init: no schema head present: (skip schema loading)\n"); talloc_free(mem_ctx); return ldb_next_init(module); - } else if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(module->ldb, - "schema_fsmo_init: failed to search the schema head: %s", - ldb_errstring(module->ldb)); - talloc_free(mem_ctx); - return ret; - } - talloc_steal(mem_ctx, schema_res); - if (schema_res->count == 0) { - ldb_debug(module->ldb, LDB_DEBUG_WARNING, - "schema_fsmo_init: no schema head present: (skip schema loading)\n"); - talloc_free(mem_ctx); - return ldb_next_init(module); - } else if (schema_res->count > 1) { - ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, - "schema_fsmo_init: [%u] schema heads found on a base search", - schema_res->count); - talloc_free(mem_ctx); - return LDB_ERR_CONSTRAINT_VIOLATION; - } - - /* - * load the attribute definitions - */ - ret = ldb_search(module->ldb, schema_dn, - LDB_SCOPE_ONELEVEL, - "(objectClass=attributeSchema)", NULL, - &a_res); - if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(module->ldb, - "schema_fsmo_init: failed to search attributeSchema objects: %s", - ldb_errstring(module->ldb)); - talloc_free(mem_ctx); - return ret; - } - talloc_steal(mem_ctx, a_res); - - /* - * load the objectClass definitions - */ - ret = ldb_search(module->ldb, schema_dn, - LDB_SCOPE_ONELEVEL, - "(objectClass=classSchema)", NULL, - &c_res); - if (ret != LDB_SUCCESS) { - ldb_asprintf_errstring(module->ldb, - "schema_fsmo_init: failed to search classSchema objects: %s", - ldb_errstring(module->ldb)); - talloc_free(mem_ctx); - return ret; } - talloc_steal(mem_ctx, c_res); - ret = dsdb_schema_from_ldb_results(mem_ctx, module->ldb, - lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), - schema_res, a_res, c_res, &schema, &error_string); if (ret != LDB_SUCCESS) { ldb_asprintf_errstring(module->ldb, "schema_fsmo_init: dsdb_schema load failed: %s", error_string); talloc_free(mem_ctx); - return ret; } - + /* dsdb_set_schema() steal schema into the ldb_context */ ret = dsdb_set_schema(module->ldb, schema); if (ret != LDB_SUCCESS) { diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 6fce354f7c..66cc867a19 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -158,6 +158,15 @@ struct dsdb_schema { struct smb_iconv_convenience *iconv_convenience; }; +enum dsdb_attr_list_query { + DSDB_SCHEMA_ALL_MAY, + DSDB_SCHEMA_ALL_MUST, + DSDB_SCHEMA_SYS_MAY, + DSDB_SCHEMA_SYS_MUST, + DSDB_SCHEMA_MAY, + DSDB_SCHEMA_MUST +}; + #include "dsdb/schema/proto.h" #endif /* _DSDB_SCHEMA_H */ diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 826f91b5f0..3a6a8f5553 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -2,8 +2,8 @@ Unix SMB/CIFS mplementation. DSDB schema header - Copyright (C) Stefan Metzmacher 2006 - Copyright (C) Andrew Bartlett 2007 + Copyright (C) Stefan Metzmacher 2006-2007 + Copyright (C) Andrew Bartlett 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 @@ -624,7 +624,7 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 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 attriute definition: %s:%s", + "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); @@ -670,6 +670,191 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, 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; @@ -1167,6 +1352,13 @@ const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, 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; @@ -1187,6 +1379,114 @@ WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *sche 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 diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c index 879b1a7213..51b03b8e8f 100644 --- a/source4/utils/ad2oLschema.c +++ b/source4/utils/ad2oLschema.c @@ -67,114 +67,13 @@ static void usage(void) exit(1); } -static int fetch_attrs_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, - TALLOC_CTX *mem_ctx, - struct ldb_result **attrs_res) -{ - int ret; - - /* Downlaod schema */ - ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, - "objectClass=attributeSchema", - NULL, attrs_res); - if (ret != LDB_SUCCESS) { - printf("Search failed: %s\n", ldb_errstring(ldb)); - return LDB_ERR_OPERATIONS_ERROR; - } - - return ret; -} - -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; -} - -static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, - struct ldb_result **schema_res) +static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx) { const char *rootdse_attrs[] = {"schemaNamingContext", NULL}; struct ldb_dn *schemadn; struct ldb_dn *basedn = ldb_dn_new(mem_ctx, ldb, NULL); struct ldb_result *rootdse_res; + struct ldb_result *schema_res; int ldb_ret; if (!basedn) { @@ -186,126 +85,42 @@ static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ct if (ldb_ret != LDB_SUCCESS) { ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, "(&(objectClass=dMD)(cn=Schema))", - NULL, schema_res); + NULL, &schema_res); if (ldb_ret) { printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb)); return NULL; } - talloc_steal(mem_ctx, *schema_res); + talloc_steal(mem_ctx, schema_res); - if ((*schema_res)->count != 1) { + if (schema_res->count != 1) { + talloc_free(schema_res); printf("Failed to find rootDSE"); return NULL; } - schemadn = talloc_steal(mem_ctx, (*schema_res)->msgs[0]->dn); + schemadn = talloc_steal(mem_ctx, schema_res->msgs[0]->dn); + talloc_free(schema_res); return schemadn; - } - talloc_steal(mem_ctx, rootdse_res); - if (rootdse_res->count != 1) { printf("Failed to find rootDSE"); + talloc_free(rootdse_res); return NULL; } /* Locate schema */ schemadn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, rootdse_res->msgs[0], "schemaNamingContext"); - if (!schemadn) { - return NULL; - } + talloc_free(rootdse_res); - ldb_ret = ldb_search(ldb, schemadn, LDB_SCOPE_BASE, - "(&(objectClass=dMD)(cn=Schema))", - NULL, schema_res); - if (ldb_ret) { - printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb)); + if (!schemadn) { return NULL; } - - talloc_steal(mem_ctx, *schema_res); - if ((*schema_res)->count != 1) { - printf("Failed to find rootDSE"); - return NULL; - } - talloc_free(rootdse_res); return schemadn; } -static bool merge_attr_list(TALLOC_CTX *mem_ctx, - struct ldb_message_element *attrs, struct ldb_message_element *new_attrs) -{ - struct ldb_val *values; - if (!new_attrs) { - return true; - } - - values = talloc_realloc(mem_ctx, - attrs->values, struct ldb_val, attrs->num_values + new_attrs->num_values); - - attrs->values = values; - - memcpy(&attrs->values[attrs->num_values], new_attrs->values, sizeof(*new_attrs->values) * new_attrs->num_values); - attrs->num_values = attrs->num_values + new_attrs->num_values; - - /* Add sort and unique implementation here */ - - return true; -} - -static bool find_aux_classes(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_dn *schema_dn, - struct ldb_message_element *aux_class, struct ldb_message_element *must, - struct ldb_message_element *sys_must, struct ldb_message_element *may, - struct ldb_message_element *sys_may) -{ - int i, ret; - struct ldb_message *msg; - struct ldb_result *res; - - for (i=0; aux_class && i < aux_class->num_values; i++) { - ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, - schema_dn, LDB_SCOPE_SUBTREE, NULL, - "(&(objectClass=classSchema)(lDAPDisplayName=%s))", - aux_class->values[i].data); - if (ret != LDB_SUCCESS) { - return false; - } - - msg = res->msgs[0]; - - if (!merge_attr_list(mem_ctx, must, ldb_msg_find_element(msg, "mustContain"))) { - return false; - } - if (!merge_attr_list(mem_ctx, sys_must, ldb_msg_find_element(msg, "systemMustContain"))) { - return false; - } - if (!merge_attr_list(mem_ctx, may, ldb_msg_find_element(msg, "mayContain"))) { - return false; - } - if (!merge_attr_list(mem_ctx, sys_may, ldb_msg_find_element(msg, "systemMayContain"))) { - return false; - } - - - if (res->count == 0) { - return false; - } - - if (!find_aux_classes(mem_ctx, ldb, schema_dn, - ldb_msg_find_element(msg, "auxiliaryClass"), must, sys_must, may, sys_may)) { - return false; - } - if (!find_aux_classes(mem_ctx, ldb, schema_dn, - ldb_msg_find_element(msg, "systemAuxiliaryClass"), must, sys_must, may, sys_may)) { - return false; - } - } - return true; -} - #define IF_NULL_FAIL_RET(x) do { \ if (!x) { \ @@ -332,13 +147,14 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ char *new_attr; } *attr_map = NULL; int num_attr_maps = 0; - struct ldb_result *schema_res, *attrs_res, *objectclasses_res; + struct dsdb_class *objectclass; + struct dsdb_attribute *attribute; struct ldb_dn *schemadn; struct schema_conv ret; struct dsdb_schema *schema; char *error_string; - int ldb_ret, i; + int ldb_ret; ret.count = 0; ret.skipped = 0; @@ -389,31 +205,16 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } } - schemadn = find_schema_dn(ldb, mem_ctx, &schema_res); + schemadn = find_schema_dn(ldb, mem_ctx); if (!schemadn) { printf("Failed to find schema DN: %s\n", ldb_errstring(ldb)); ret.failures = 1; return ret; } - ldb_ret = fetch_attrs_schema(ldb, schemadn, mem_ctx, &attrs_res); - if (ldb_ret != LDB_SUCCESS) { - printf("Failed to fetch attribute schema: %s\n", ldb_errstring(ldb)); - ret.failures = 1; - return ret; - } - - - ldb_ret = fetch_objectclass_schema(ldb, schemadn, mem_ctx, &objectclasses_res); - if (ldb_ret != LDB_SUCCESS) { - printf("Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb)); - ret.failures = 1; - return ret; - } - - ldb_ret = dsdb_schema_from_ldb_results(mem_ctx, ldb, - lp_iconv_convenience(cmdline_lp_ctx), - schema_res, attrs_res, objectclasses_res, &schema, &error_string); + ldb_ret = dsdb_schema_from_schema_dn(mem_ctx, ldb, + lp_iconv_convenience(cmdline_lp_ctx), + schemadn, &schema, &error_string); if (ldb_ret != LDB_SUCCESS) { printf("Failed to load schema: %s\n", error_string); ret.failures = 1; @@ -428,24 +229,17 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ break; } - for (i=0; i < attrs_res->count; i++) { - struct ldb_message *msg = attrs_res->msgs[i]; + for (attribute=schema->attributes; attribute; attribute = attribute->next) { + const char *name = attribute->lDAPDisplayName; + const char *description = attribute->adminDescription; + const char *oid = attribute->attributeID_oid; + const char *syntax = attribute->attributeSyntax_oid; + bool single_value = attribute->isSingleValued; - const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); - const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); - const char *oid = ldb_msg_find_attr_as_string(msg, "attributeID", NULL); - const char *syntax = ldb_msg_find_attr_as_string(msg, "attributeSyntax", NULL); - bool single_value = ldb_msg_find_attr_as_bool(msg, "isSingleValued", false); const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax); char *schema_entry = NULL; int j; - if (!name) { - printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); - ret.failures++; - continue; - } - /* We have been asked to skip some attributes/objectClasses */ if (attrs_skip && str_list_check_ci(attrs_skip, name)) { ret.skipped++; @@ -487,9 +281,11 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ IF_NULL_FAIL_RET(schema_entry); if (description) { +#if 0 /* If you want to re-enable this, you must first figure out a sane escaping of ' in the description */ schema_entry = talloc_asprintf_append(schema_entry, - " DESC %s\n", description); + " DESC '%s'\n", description); IF_NULL_FAIL_RET(schema_entry); +#endif } if (map) { @@ -539,59 +335,31 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ ret.count++; } - for (i=0; i < objectclasses_res->count; i++) { - struct ldb_message *msg = objectclasses_res->msgs[i]; - const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); - const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); - const char *oid = ldb_msg_find_attr_as_string(msg, "governsID", NULL); - const char *subClassOf = ldb_msg_find_attr_as_string(msg, "subClassOf", NULL); - int objectClassCategory = ldb_msg_find_attr_as_int(msg, "objectClassCategory", 0); - struct ldb_message_element *must = ldb_msg_find_element(msg, "mustContain"); - struct ldb_message_element *sys_must = ldb_msg_find_element(msg, "systemMustContain"); - struct ldb_message_element *may = ldb_msg_find_element(msg, "mayContain"); - struct ldb_message_element *sys_may = ldb_msg_find_element(msg, "systemMayContain"); - struct ldb_message_element *aux_class = ldb_msg_find_element(msg, "auxiliaryClass"); - struct ldb_message_element *sys_aux_class = ldb_msg_find_element(msg, "systemAuxiliaryClass"); + /* This is already sorted to have 'top' and similar classes first */ + for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) { + const char *name = objectclass->lDAPDisplayName; + const char *description = objectclass->adminDescription; + const char *oid = objectclass->governsID_oid; + const char *subClassOf = objectclass->subClassOf; + int objectClassCategory = objectclass->objectClassCategory; + char **must; + char **may; char *schema_entry = NULL; + const char *objectclass_name_as_list[] = { + objectclass->lDAPDisplayName, + NULL + }; int j; - - if (!name) { - printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); - ret.failures++; - continue; - } - + /* We have been asked to skip some attributes/objectClasses */ if (attrs_skip && str_list_check_ci(attrs_skip, name)) { ret.skipped++; continue; } - if (must == NULL) { - must = talloc_zero(mem_ctx, struct ldb_message_element); - } - - if (may == NULL) { - may = talloc_zero(mem_ctx, struct ldb_message_element); - } - - if (sys_must == NULL) { - sys_must = talloc_zero(mem_ctx, struct ldb_message_element); - } - - if (sys_may == NULL) { - sys_may = talloc_zero(mem_ctx, struct ldb_message_element); - } + may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); - if (!find_aux_classes(mem_ctx, ldb, schemadn, aux_class, must, sys_must, may, sys_may)) { - ret.failures++; - continue; - } - - if (!find_aux_classes(mem_ctx, ldb, schemadn, sys_aux_class, must, sys_must, may, sys_may)) { - ret.failures++; - continue; - } + must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); /* We might have been asked to remap this oid, due to a conflict */ for (j=0; oid_map && oid_map[j].old_oid; j++) { @@ -635,7 +403,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ if (description) { schema_entry = talloc_asprintf_append(schema_entry, - " DESC %s\n", description); + " DESC '%s'\n", description); IF_NULL_FAIL_RET(schema_entry); } @@ -666,9 +434,9 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ #define APPEND_ATTRS(attributes) \ do { \ int k; \ - for (k=0; attributes && k < attributes->num_values; k++) { \ + for (k=0; attributes && attributes[k]; k++) { \ int attr_idx; \ - const char *attr_name = (const char *)attributes->values[k].data; \ + const char *attr_name = attributes[k]; \ /* We might have been asked to remap this name, due to a conflict */ \ for (attr_idx=0; attr_name && attr_map && attr_map[attr_idx].old_attr; attr_idx++) { \ if (strcasecmp(attr_name, attr_map[attr_idx].old_attr) == 0) { \ @@ -681,7 +449,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ " %s", \ attr_name); \ IF_NULL_FAIL_RET(schema_entry); \ - if (k != (attributes->num_values - 1)) { \ + if (attributes[k+1]) { \ schema_entry = talloc_asprintf_append(schema_entry, \ " $"); \ IF_NULL_FAIL_RET(schema_entry); \ @@ -694,35 +462,25 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_ } \ } while (0) - if ((must && must->values) || (sys_must && sys_must->values)) { + if (must) { schema_entry = talloc_asprintf_append(schema_entry, " MUST ("); IF_NULL_FAIL_RET(schema_entry); APPEND_ATTRS(must); - if (must && must->values && sys_must && sys_must->values) { - schema_entry = talloc_asprintf_append(schema_entry, \ - " $"); \ - } - APPEND_ATTRS(sys_must); - + schema_entry = talloc_asprintf_append(schema_entry, " )\n"); IF_NULL_FAIL_RET(schema_entry); } - if ((may && may->values) || (sys_may && sys_may->values)) { + if (may) { schema_entry = talloc_asprintf_append(schema_entry, " MAY ("); IF_NULL_FAIL_RET(schema_entry); APPEND_ATTRS(may); - if (may && may->values && sys_may && sys_may->values) { - schema_entry = talloc_asprintf_append(schema_entry, \ - " $"); \ - } - APPEND_ATTRS(sys_may); - + schema_entry = talloc_asprintf_append(schema_entry, " )\n"); IF_NULL_FAIL_RET(schema_entry); -- cgit