r13324: From now on check attribute names obey rfc2251
authorSimo Sorce <idra@samba.org>
Sat, 4 Feb 2006 00:38:48 +0000 (00:38 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:51:44 +0000 (13:51 -0500)
Also add a way to provide utf8 compliant functions
by registering them with ldb_set_utf8_fns()

Next comes code to register samba internal utf8 functions.

Simo.
(This used to be commit ac9b8a41ffca8e06c5e849d544d3203a665b8e0d)

source4/lib/ldb/Makefile.in
source4/lib/ldb/common/ldb.c
source4/lib/ldb/common/ldb_dn.c
source4/lib/ldb/common/ldb_ldif.c
source4/lib/ldb/common/ldb_msg.c
source4/lib/ldb/common/ldb_utf8.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source4/lib/ldb/ldb_tdb/ldb_index.c
source4/lib/ldb/tools/ldbtest.c

index 320b9c281ff84eec8b29efd59476085de2777953..43d1674d088a62d87185a6ef2acedbbbf105b5b5 100644 (file)
@@ -188,7 +188,7 @@ endif
 test: $(BINS) test-tdb test-ldap test-sqlite3 test-schema
 
 install: all
-       cp include/ldb.h $(includedir)
+       cp include/ldb.h include/ldb_errors.h $(includedir)
        cp $(LDB_LIB) $(libdir)
        cp $(BINS) $(bindir)
        cp ldb.pc $(libdir)/pkgconfig
index 41b1a3efb72ea1a25b7979d64d5d18d0966571d2..0857c07ad4efdb44709d975c88ac04ee0ba91d19 100644 (file)
@@ -50,6 +50,8 @@ struct ldb_context *ldb_init(void *mem_ctx)
                return NULL;
        }
 
+       ldb_set_utf8_default(ldb);
+
        return ldb;
 }
 
index e0c6f4a103a862d542316ade4c6e747f4229f75d..c2212fd6fe66001233b2bd4432194a02967e5cd2 100644 (file)
@@ -55,23 +55,6 @@ int ldb_dn_check_special(const struct ldb_dn *dn, const char *check)
        return ! strcmp((char *)dn->components[0].value.data, check);
 }
 
-static int ldb_dn_is_valid_attribute_name(const char *name)
-{
-       if (name == NULL) return 0;
-
-       while (*name) {
-               if (! isascii(*name)) {
-                       return 0;
-               }
-               if (! (isalnum((unsigned char)*name) || *name == '-')) {
-                       return 0;
-               }
-               name++;
-       }
-
-       return 1;
-}
-
 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
 {
        const char *p, *s, *src;
@@ -301,7 +284,7 @@ static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw
        if (!dc.name)
                return dc;
 
-       if (! ldb_dn_is_valid_attribute_name(dc.name)) {
+       if (! ldb_valid_attr_name(dc.name)) {
                goto failed;
        }
 
@@ -519,7 +502,8 @@ int ldb_dn_compare_base(struct ldb_context *ldb,
                const struct ldb_attrib_handler *h;
 
                /* compare names (attribute names are guaranteed to be ASCII only) */
-               ret = ldb_caseless_cmp(base->components[n0].name,
+               ret = ldb_caseless_cmp(ldb,
+                                      base->components[n0].name,
                                       dn->components[n1].name);
                if (ret) {
                        return ret;
@@ -598,7 +582,7 @@ struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn
                struct ldb_dn_component dc;
                const struct ldb_attrib_handler *h;
 
-               dc.name = ldb_casefold(cedn, edn->components[i].name);
+               dc.name = ldb_casefold(ldb, cedn, edn->components[i].name);
                LDB_DN_NULL_FAILED(dc.name);
 
                h = ldb_attrib_handler(ldb, dc.name);
@@ -761,7 +745,7 @@ struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
                                                 const struct ldb_dn *base)
 {
        struct ldb_dn *new;
-       if (! ldb_dn_is_valid_attribute_name(attr)) return NULL;
+       if (! ldb_valid_attr_name(attr)) return NULL;
        if (value == NULL || value == '\0') return NULL; 
 
        if (base != NULL) {
index 53dadcc6fe07a9e77580312af65cd62ab9215598..7501e89222f6c74d4d1c8213acfe1227f3c5712b 100644 (file)
@@ -498,40 +498,6 @@ void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
        talloc_free(ldif);
 }
 
-/*
-  add an empty element
-*/
-static int msg_add_empty(struct ldb_context *ldb,
-                        struct ldb_message *msg, const char *name, unsigned flags)
-{
-       struct ldb_message_element *el2, *el;
-
-       el2 = talloc_realloc(msg, msg->elements, 
-                              struct ldb_message_element, msg->num_elements+1);
-       if (!el2) {
-               errno = ENOMEM;
-               return -1;
-       }
-       
-       msg->elements = el2;
-
-       el = &msg->elements[msg->num_elements];
-       
-       el->name = talloc_strdup(msg->elements, name);
-       el->num_values = 0;
-       el->values = NULL;
-       el->flags = flags;
-
-       if (!el->name) {
-               errno = ENOMEM;
-               return -1;
-       }
-
-       msg->num_elements++;
-
-       return 0;
-}
-
 /*
  read from a LDIF source, creating a ldb_message
 */
@@ -630,7 +596,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
                }
 
                if (empty) {
-                       if (msg_add_empty(ldb, msg, (char *)value.data, flags) != 0) {
+                       if (ldb_msg_add_empty(msg, (char *)value.data, flags) != 0) {
                                goto failed;
                        }
                        continue;
index 513a4de1f81a183864c3d91a110fac2d4d054beb..497d2cb0d5591ce365c322d510c68d549c3447ef 100644 (file)
@@ -123,6 +123,10 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
 {
        struct ldb_message_element *els;
 
+       if (! ldb_valid_attr_name(attr_name)) {
+               return -1;
+       }
+
        els = talloc_realloc(msg, msg->elements, 
                             struct ldb_message_element, msg->num_elements+1);
        if (!els) {
@@ -135,6 +139,7 @@ int ldb_msg_add_empty(struct ldb_message *msg, const char *attr_name, int flags)
        els[msg->num_elements].flags = flags;
        els[msg->num_elements].name = talloc_strdup(els, attr_name);
        if (!els[msg->num_elements].name) {
+               errno = ENOMEM;
                return -1;
        }
 
index c2d31d440bb5636dff825a9630abcfe674ee92ca..4735b35af6d6452f60bfb1112c438fa761debda3 100644 (file)
 #include "includes.h"
 #include "ldb/include/includes.h"
 
+
 /*
-  TODO:
-  a simple case folding function - will be replaced by a UTF8 aware function later
+  this allow the user to pass in a caseless comparison
+  function to handle utf8 caseless comparisons
+ */
+void ldb_set_utf8_fns(struct ldb_context *ldb,
+                       void *context,
+                       int (*cmp)(void *, const char *, const char *),
+                       char *(*casefold)(void *, void *, const char *))
+{
+       if (context)
+               ldb->utf8_fns.context = context;
+       if (cmp)
+               ldb->utf8_fns.caseless_cmp = cmp;
+       if (casefold)
+               ldb->utf8_fns.casefold = casefold;
+}
+
+/*
+  a simple case folding function
+  NOTE: does not handle UTF8
 */
-char *ldb_casefold(void *mem_ctx, const char *s)
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
 {
        int i;
        char *ret = talloc_strdup(mem_ctx, s);
@@ -55,20 +73,69 @@ char *ldb_casefold(void *mem_ctx, const char *s)
 
 /*
   a caseless compare, optimised for 7 bit
-  TODO: doesn't yet handle UTF8
+  NOTE: doesn't handle UTF8
 */
-int ldb_caseless_cmp(const char *s1, const char *s2)
+
+int ldb_caseless_cmp_default(void *context, const char *s1, const char *s2)
+{
+       return strcasecmp(s1,s2);
+}
+
+void ldb_set_utf8_default(struct ldb_context *ldb)
+{
+       ldb_set_utf8_fns(ldb, NULL, ldb_caseless_cmp_default, ldb_casefold_default);
+}
+
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
+{
+       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
+}
+
+int ldb_caseless_cmp(struct ldb_context *ldb, const char *s1, const char *s2)
+{
+       return ldb->utf8_fns.caseless_cmp(ldb->utf8_fns.context, s1, s2);
+}
+
+/*
+  check the attribute name is valid according to rfc2251
+  returns 1 if the name is ok
+ */
+
+int ldb_valid_attr_name(const char *s)
 {
-       return strcasecmp(s1, s2);
+       int i;
+
+       if (!s || !s[0])
+               return 0;
+
+       /* handle special ldb_tdb wildcard */
+       if (strcmp(s, "*") == 0) return 1;
+
+       for (i = 0; s[i]; i++) {
+               if (! isascii(s[i])) {
+                       return 0;
+               }
+               if (i == 0) { /* first char must be an alpha (or our special '@' identifier) */
+                       if (! (isalpha(s[i]) || (s[i] == '@'))) {
+                               return 0;
+                       }
+               } else {
+                       if (! (isalnum(s[i]) || (s[i] == '-'))) {
+                               return 0;
+                       }
+               }
+       }
+       return 1;
 }
 
 /*
   compare two attribute names
+  attribute names are restricted by rfc2251 so using strcasecmp here is ok.
   return 0 for match
 */
 int ldb_attr_cmp(const char *attr1, const char *attr2)
 {
-       return ldb_caseless_cmp(attr1, attr2);
+       return strcasecmp(attr1, attr2);
 }
 
 /*
index 9139e6d2f5abe9ec4c590aed8fb85282cd1d659d..a8c2d176b59fc8fb4b3b61003e13ee03a919d0e8 100644 (file)
@@ -208,6 +208,16 @@ struct ldb_debug_ops {
        void *context;
 };
 
+/**
+  The user can optionally supply a custom utf8 functions,
+  to handle comparisons and casefolding.
+*/
+struct ldb_utf8_fns {
+       void *context;
+       int (*caseless_cmp)(void *context, const char *s1, const char *s2);
+       char *(*casefold)(void *context, void *mem_ctx, const char *s);
+};
+
 /**
    Flag value for database connection mode.
 
@@ -718,30 +728,48 @@ int ldb_transaction_cancel(struct ldb_context *ldb);
 */
 const char *ldb_errstring(struct ldb_context *ldb);
 
+/**
+  setup the default utf8 functions
+  FIXME: these functions do not yet handle utf8
+*/
+void ldb_set_utf8_default(struct ldb_context *ldb);
+
 /**
    Casefold a string
 
+   \param ldb the ldb context
    \param mem_ctx the memory context to allocate the result string
    memory from. 
    \param s the string that is to be folded
    \return a copy of the string, converted to upper case
 
-   \todo This function should be UTF8 aware, but currently is not.
+   \note The default function is not yet UTF8 aware. Provide your own
+         set of functions through ldb_set_utf8_fns()
 */
-char *ldb_casefold(void *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s);
 
 /**
    Compare two strings, without regard to case. 
 
+   \param ldb the ldb context
    \param s1 the first string to compare
    \param s2 the second string to compare
 
    \return 0 if the strings are the same, non-zero if there are any
    differences except for case.
 
-   \note This function is not UTF8 aware.
+   \note The default function is not yet UTF8 aware. Provide your own
+         set of functions through ldb_set_utf8_fns()
+*/
+int ldb_caseless_cmp(struct ldb_context *ldb, const char *s1, const char *s2);
+
+/**
+   Check the attribute name is valid according to rfc2251
+   \param s tthe string to check
+
+   \return 1 if the name is ok
 */
-int ldb_caseless_cmp(const char *s1, const char *s2);
+int ldb_valid_attr_name(const char *s);
 
 /*
   ldif manipulation functions
index 6871d8d5525a6fb7072acf1d0959a776128a189e..fffda77ff8fd0a34a54dd493a53f3812f3409eb1 100644 (file)
@@ -90,6 +90,9 @@ struct ldb_context {
        /* debugging operations */
        struct ldb_debug_ops debug_ops;
 
+       /* custom utf8 functions */
+       struct ldb_utf8_fns utf8_fns;
+
        /* backend specific opaque parameters */
        struct ldb_opaque {
                struct ldb_opaque *next;
@@ -191,4 +194,8 @@ int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
 struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid);
 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver);
 int check_critical_controls(struct ldb_control **controls);
+
+/* The following definitions come from lib/ldb/common/ldb_utf8.c */
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
+int ldb_caseless_cmp_default(void *context, const char *s1, const char *s2);
 #endif
index 4c00998fa9357da42dd2a93d351236c20dc6810f..fbbbf037b3d2e7e53575d92bb6d0acb8960ff1e5 100644 (file)
@@ -289,7 +289,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                 * For simple searches, we want to retrieve the list of EIDs that
                 * match the criteria.
                */
-               attr = ldb_casefold(mem_ctx, t->u.equality.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
                if (attr == NULL) return NULL;
                h = ldb_attrib_handler(module->ldb, attr);
 
@@ -353,7 +353,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                        wild_card_string[strlen(wild_card_string) - 1] = '\0';
                }
 
-               attr = ldb_casefold(mem_ctx, t->u.substring.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.substring.attr);
                if (attr == NULL) return NULL;
                h = ldb_attrib_handler(module->ldb, attr);
 
@@ -374,7 +374,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                                        value.data);
 
        case LDB_OP_GREATER:
-               attr = ldb_casefold(mem_ctx, t->u.equality.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
                if (attr == NULL) return NULL;
                h = ldb_attrib_handler(module->ldb, attr);
 
@@ -393,7 +393,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                                        attr);
 
        case LDB_OP_LESS:
-               attr = ldb_casefold(mem_ctx, t->u.equality.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
                if (attr == NULL) return NULL;
                h = ldb_attrib_handler(module->ldb, attr);
 
@@ -416,7 +416,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                        return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry");
                }
 
-               attr = ldb_casefold(mem_ctx, t->u.present.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.present.attr);
                if (attr == NULL) return NULL;
 
                return lsqlite3_tprintf(mem_ctx,
@@ -425,7 +425,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                                        attr);
 
        case LDB_OP_APPROX:
-               attr = ldb_casefold(mem_ctx, t->u.equality.attr);
+               attr = ldb_casefold(module->ldb, mem_ctx, t->u.equality.attr);
                if (attr == NULL) return NULL;
                h = ldb_attrib_handler(module->ldb, attr);
 
@@ -715,26 +715,8 @@ static int lsqlite3_search_callback(void *result, int col_num, char **cols, char
                if (!found) return 0;
        }
 
-       msg->elements = talloc_realloc(msg,
-                                      msg->elements,
-                                      struct ldb_message_element,
-                                      msg->num_elements + 1);
-       if (msg->elements == NULL) return SQLITE_ABORT;
-
-       msg->elements[msg->num_elements].flags = 0;
-       msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, cols[2]);
-       if (msg->elements[msg->num_elements].name == NULL) return SQLITE_ABORT;
-
-       msg->elements[msg->num_elements].num_values = 1;
-       msg->elements[msg->num_elements].values = talloc_array(msg->elements,
-                                                               struct ldb_val, 1);
-       if (msg->elements[msg->num_elements].values == NULL) return SQLITE_ABORT;
-
-       msg->elements[msg->num_elements].values[0].length = strlen(cols[3]);
-       msg->elements[msg->num_elements].values[0].data = talloc_strdup(msg->elements, cols[3]);
-       if (msg->elements[msg->num_elements].values[0].data == NULL) return SQLITE_ABORT;
-
-       msg->num_elements++;
+       if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0)
+               return SQLITE_ABORT;
 
        return SQLITE_OK;
 }
@@ -1076,7 +1058,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
                int j;
 
                /* Get a case-folded copy of the attribute name */
-               attr = ldb_casefold(local_ctx, el->name);
+               attr = ldb_casefold(module->ldb, local_ctx, el->name);
                if (attr == NULL) {
                        ret = LDB_ERR_OTHER;
                        goto failed;
@@ -1175,7 +1157,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
                int j;
 
                /* Get a case-folded copy of the attribute name */
-               attr = ldb_casefold(local_ctx, el->name);
+               attr = ldb_casefold(module->ldb, local_ctx, el->name);
                if (attr == NULL) {
                        ret = LDB_ERR_OTHER;
                        goto failed;
index c74ce62fbf0543ba871d38c28df18b1f864edc0e..fb29a9ddbfc5a04ff3597d9d464ffb8ffbcaa7c4 100644 (file)
@@ -106,7 +106,7 @@ static struct ldb_dn *ldb_dn_key(struct ldb_context *ldb,
        const struct ldb_attrib_handler *h;
        char *attr_folded;
 
-       attr_folded = ldb_casefold(ldb, attr);
+       attr_folded = ldb_casefold(ldb, ldb, attr);
        if (!attr_folded) {
                return NULL;
        }
index f2efd4d22ab0a2ba7360ed47895cd459560f046e..69362d0f20134194fc47aea6f87e5a4ba07d0154 100644 (file)
@@ -94,7 +94,7 @@ static void add_records(struct ldb_context *ldb,
                el[2].name = talloc_strdup(tmp_ctx, "uid");
                el[2].num_values = 1;
                el[2].values = vals[2];
-               vals[2][0].data = (uint8_t *)ldb_casefold(tmp_ctx, name);
+               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
                vals[2][0].length = strlen((char *)vals[2][0].data);
 
                el[3].flags = 0;