From 43aa546ecc3f05845793b1a7354685d50a77c170 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 5 Aug 2009 08:53:11 +1000 Subject: s4:dsdb Don't cast an ldb_val into a const char * for schema lookups This removes a number of cases where we did a cast into a const char * of an ldb_val. While convention is to alway have an extra \0 at data[length] in the ldb_val, this is not required, and does not occour at least on build farm host 'svart'. Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/kludge_acl.c | 18 +--- source4/dsdb/samdb/ldb_modules/objectclass.c | 5 +- source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 3 +- source4/dsdb/schema/schema_convert_to_ol.c | 12 ++- source4/dsdb/schema/schema_query.c | 143 +++++++++++++++++++++------ 5 files changed, 129 insertions(+), 52 deletions(-) (limited to 'source4/dsdb') diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c index 5bed28b00c..15db491171 100644 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -93,7 +93,7 @@ static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_mess struct ldb_message_element *allowedAttributes; const struct dsdb_schema *schema = dsdb_get_schema(ldb); TALLOC_CTX *mem_ctx; - const char **objectclass_list, **attr_list; + const char **attr_list; int i, ret; /* If we don't have a schema yet, we can't do anything... */ @@ -118,19 +118,7 @@ static int kludge_acl_allowedAttributes(struct ldb_context *ldb, struct ldb_mess we alter the element array in ldb_msg_add_empty() */ oc_el = ldb_msg_find_element(msg, "objectClass"); - objectclass_list = talloc_array(mem_ctx, const char *, oc_el->num_values + 1); - if (!objectclass_list) { - ldb_oom(ldb); - talloc_free(mem_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - - for (i=0; oc_el && i < oc_el->num_values; i++) { - objectclass_list[i] = (const char *)oc_el->values[i].data; - } - objectclass_list[i] = NULL; - - attr_list = dsdb_full_attribute_list(mem_ctx, schema, objectclass_list, DSDB_SCHEMA_ALL); + attr_list = dsdb_full_attribute_list(mem_ctx, schema, oc_el, DSDB_SCHEMA_ALL); if (!attr_list) { ldb_asprintf_errstring(ldb, "kludge_acl: Failed to get list of attributes create %s attribute", attrName); talloc_free(mem_ctx); @@ -172,7 +160,7 @@ static int kludge_acl_childClasses(struct ldb_context *ldb, struct ldb_message * oc_el = ldb_msg_find_element(msg, "objectClass"); for (i=0; oc_el && i < oc_el->num_values; i++) { - sclass = dsdb_class_by_lDAPDisplayName(schema, (const char *)oc_el->values[i].data); + sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { /* We don't know this class? what is going on? */ continue; diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 7883bccfe7..4f013709b2 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -134,9 +134,10 @@ static int objectclass_sort(struct ldb_module *module, ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; } - current->objectclass = dsdb_class_by_lDAPDisplayName(schema, (const char *)objectclass_element->values[i].data); + current->objectclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &objectclass_element->values[i]); if (!current->objectclass) { - ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in schema", (const char *)objectclass_element->values[i].data); + ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema", + (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data); return LDB_ERR_OBJECT_CLASS_VIOLATION; } diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 1b8f786c35..290232bdb9 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -417,9 +417,8 @@ static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_messag } first_component_val = ldb_dn_get_component_val(dn, 0); - class_name = (const char *)first_component_val->data; - schema_class = dsdb_class_by_cn(schema, class_name); + schema_class = dsdb_class_by_cn_ldb_val(schema, first_component_val); if (schema_class == NULL) { return LDB_SUCCESS; } diff --git a/source4/dsdb/schema/schema_convert_to_ol.c b/source4/dsdb/schema/schema_convert_to_ol.c index ebcb7ade59..c0ab5c2af8 100644 --- a/source4/dsdb/schema/schema_convert_to_ol.c +++ b/source4/dsdb/schema/schema_convert_to_ol.c @@ -56,9 +56,11 @@ static char *print_schema_recursive(char *append_to_string, struct dsdb_schema * const char **must; const char **may; char *schema_entry = NULL; - const char *objectclass_name_as_list[] = { - objectclass->lDAPDisplayName, - NULL + struct ldb_val objectclass_name_as_ldb_val = data_blob_string_const(objectclass->lDAPDisplayName); + struct ldb_message_element objectclass_name_as_el = { + .name = "objectClass", + .num_values = 1, + .values = &objectclass_name_as_ldb_val }; int j; int attr_idx; @@ -89,7 +91,7 @@ static char *print_schema_recursive(char *append_to_string, struct dsdb_schema * } } - may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); + may = dsdb_full_attribute_list(mem_ctx, schema, &objectclass_name_as_el, DSDB_SCHEMA_ALL_MAY); for (j=0; may && may[j]; j++) { /* We might have been asked to remap this name, due to a conflict */ @@ -101,7 +103,7 @@ static char *print_schema_recursive(char *append_to_string, struct dsdb_schema * } } - must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); + must = dsdb_full_attribute_list(mem_ctx, schema, &objectclass_name_as_el, DSDB_SCHEMA_ALL_MUST); for (j=0; must && must[j]; j++) { /* We might have been asked to remap this name, due to a conflict */ diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c index f894ef5b1e..0e5efa9004 100644 --- a/source4/dsdb/schema/schema_query.c +++ b/source4/dsdb/schema/schema_query.c @@ -51,11 +51,24 @@ } } while (0) +static const 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); + static int uint32_cmp(uint32_t c1, uint32_t c2) { return c1 - c2; } +static int strcasecmp_with_ldb_val(const struct ldb_val *target, const char *str) +{ + int ret = strncasecmp((const char *)target->data, str, target->length); + if (ret == 0) { + return (target->length - strlen(str)); + } + return ret; +} const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema, uint32_t id) @@ -143,6 +156,16 @@ const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema return c; } +const struct dsdb_class *dsdb_class_by_lDAPDisplayName_ldb_val(const struct dsdb_schema *schema, + struct ldb_val *name) +{ + struct dsdb_class *c; + if (!name) return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_lDAPDisplayName, + schema->num_classes, lDAPDisplayName, name, strcasecmp_with_ldb_val, c); + return c; +} + const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema, const char *cn) { @@ -153,6 +176,16 @@ const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema, return c; } +const struct dsdb_class *dsdb_class_by_cn_ldb_val(const struct dsdb_schema *schema, + struct ldb_val *cn) +{ + struct dsdb_class *c; + if (!cn) return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_cn, + schema->num_classes, cn, cn, strcasecmp_with_ldb_val, c); + return c; +} + const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, uint32_t id) { @@ -268,48 +301,86 @@ const char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *s return attr_list; } +static const char **attribute_list_from_class(TALLOC_CTX *mem_ctx, + const struct dsdb_schema *schema, + const struct dsdb_class *sclass, + enum dsdb_attr_list_query query) +{ + const char **this_class_list; + const char **system_recursive_list; + const char **recursive_list; + const char **attr_list; + + this_class_list = dsdb_attribute_list(mem_ctx, sclass, query); + + recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, + sclass->systemAuxiliaryClass, + query); + + system_recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, + sclass->auxiliaryClass, + query); + + attr_list = this_class_list; + attr_list = merge_attr_list(mem_ctx, attr_list, recursive_list); + attr_list = merge_attr_list(mem_ctx, attr_list, system_recursive_list); + return attr_list; +} + +/* Return a full attribute list for a given class list (as a ldb_message_element) + + Via attribute_list_from_class() this calls itself when recursing on auxiliary classes + */ static const 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) + const struct dsdb_schema *schema, + const char **class_list, + enum dsdb_attr_list_query query) { int i; - const struct dsdb_class *sclass; - const char **attr_list = NULL; - const char **this_class_list; - const char **recursive_list; for (i=0; class_list && class_list[i]; i++) { - sclass = dsdb_class_by_lDAPDisplayName(schema, class_list[i]); - - this_class_list = dsdb_attribute_list(mem_ctx, sclass, query); - attr_list = merge_attr_list(mem_ctx, attr_list, this_class_list); + const char **sclass_list + = attribute_list_from_class(mem_ctx, schema, + dsdb_class_by_lDAPDisplayName(schema, class_list[i]), + query); - recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, - sclass->systemAuxiliaryClass, - query); - - attr_list = merge_attr_list(mem_ctx, attr_list, recursive_list); - - recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema, - sclass->auxiliaryClass, - query); - - attr_list = merge_attr_list(mem_ctx, attr_list, recursive_list); + attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list); + } + return attr_list; +} + +/* Return a full attribute list for a given class list (as a ldb_message_element) + + Using the ldb_message_element ensures we do length-limited + comparisons, rather than casting the possibly-unterminated string + + Via attribute_list_from_class() this calls + dsdb_full_attribute_list_internal() when recursing on auxiliary classes + */ +static const char **dsdb_full_attribute_list_internal_el(TALLOC_CTX *mem_ctx, + const struct dsdb_schema *schema, + const struct ldb_message_element *el, + enum dsdb_attr_list_query query) +{ + int i; + const char **attr_list = NULL; + + for (i=0; i < el->num_values; i++) { + const char **sclass_list + = attribute_list_from_class(mem_ctx, schema, + dsdb_class_by_lDAPDisplayName_ldb_val(schema, &el->values[i]), + query); + attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list); } return attr_list; } -const char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, - const struct dsdb_schema *schema, - const char **class_list, - enum dsdb_attr_list_query query) +/* Helper function to remove duplicates from the attribute list to be returned */ +static const char **dedup_attr_list(const char **attr_list) { - const char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query); size_t new_len = str_list_length(attr_list); - /* Remove duplicates */ if (new_len > 1) { int i; @@ -329,3 +400,19 @@ const char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, } return attr_list; } + +/* Return a full attribute list for a given class list (as a ldb_message_element) + + Using the ldb_message_element ensures we do length-limited + comparisons, rather than casting the possibly-unterminated string + + The result contains only unique values + */ +const char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx, + const struct dsdb_schema *schema, + const struct ldb_message_element *class_list, + enum dsdb_attr_list_query query) +{ + const char **attr_list = dsdb_full_attribute_list_internal_el(mem_ctx, schema, class_list, query); + return dedup_attr_list(attr_list); +} -- cgit