s4:dsdb Don't cast an ldb_val into a const char * for schema lookups
authorAndrew Bartlett <abartlet@samba.org>
Tue, 4 Aug 2009 22:53:11 +0000 (08:53 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 4 Aug 2009 22:56:06 +0000 (08:56 +1000)
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
source4/dsdb/samdb/ldb_modules/objectclass.c
source4/dsdb/samdb/ldb_modules/schema_fsmo.c
source4/dsdb/schema/schema_convert_to_ol.c
source4/dsdb/schema/schema_query.c

index 5bed28b00c77e07dae5a964c9cbb58b7eb6a33b7..15db491171f3e3045e6987be966ad054ac0965d9 100644 (file)
@@ -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;
index 7883bccfe70e934f0df1c16c50f142cc13633912..4f013709b22234747190dcc046483f753c3f6e1b 100644 (file)
@@ -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;
                }
 
index 1b8f786c3542eb8378da899f5e47e6fe65f3f3c8..290232bdb99f0a0da01896f82306afba7fced284 100644 (file)
@@ -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;
        }
index ebcb7ade59e3f73cb23ae253a14fead094c0d3f7..c0ab5c2af85f1afb5afaa598970f2fc969acbc27 100644 (file)
@@ -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 */ 
index f894ef5b1e55464a63a7c9e55d3beb2603ee0e26..0e5efa90040b04ad4ad0a157ebf6431dc0d5c74d 100644 (file)
        } } 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);
+}