fixed a problem with length limited ldap values
authorAndrew Tridgell <tridge@samba.org>
Fri, 22 Aug 2008 07:36:56 +0000 (17:36 +1000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 22 Aug 2008 07:36:56 +0000 (17:36 +1000)
The core ldb code for string matching assumed NULL terminated strings,
whereas the anr module used data_blob_const() to effectively truncate
a ldb_val by changing its length. The ldb code is supposed to be based
around length limited blobs, not NULL terminated strings, so the
correct fix was to change the string comparison functions to be length
limited
(This used to be commit 26c6aa5a80ffaf06fc33f30a6533f8f16ef538bc)

source4/lib/charset/charset.h
source4/lib/charset/util_unistr.c
source4/lib/ldb/common/attrib_handlers.c
source4/lib/ldb/common/ldb_utf8.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/tools/ldbtest.c
source4/lib/ldb_wrap.h
source4/lib/util/util_ldb.c
source4/lib/util/util_ldb.h

index baa7df532b6d78fa1c5db0aa53138f13ba5edf96..c49745cd7f1799a2897483e7bbcb625941ff891b 100644 (file)
@@ -97,6 +97,7 @@ size_t count_chars_w(const char *s, char c);
 void strupper_m(char *s);
 void strlower_m(char *s);
 char *strupper_talloc(TALLOC_CTX *ctx, const char *src);
+char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n);
 char *strlower_talloc(TALLOC_CTX *ctx, const char *src);
 bool strhasupper(const char *string);
 bool strhaslower(const char *string);
index 19a4f3236cfdedcdc5cffe9541d7b9cb427021c8..09ec7b04716d1db271fd906f6cf94ab53e869a3e 100644 (file)
@@ -518,8 +518,9 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
 
 /**
  Convert a string to UPPER case, allocated with talloc
+ source length limited to n bytes
 **/
-_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
 {
        size_t size=0;
        char *dest;
@@ -531,12 +532,12 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
 
        /* this takes advantage of the fact that upper/lower can't
           change the length of a character by more than 1 byte */
-       dest = talloc_array(ctx, char, 2*(strlen(src))+1);
+       dest = talloc_array(ctx, char, 2*(n+1));
        if (dest == NULL) {
                return NULL;
        }
 
-       while (*src) {
+       while (*src && n--) {
                size_t c_size;
                codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
                src += c_size;
@@ -561,6 +562,16 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
        return dest;
 }
 
+/**
+ Convert a string to UPPER case, allocated with talloc
+**/
+_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+{
+       return strupper_talloc_n(ctx, src, src?strlen(src):0);
+}
+
+
+
 /**
  Convert a string to lower case.
 **/
index 8ed2763d4df5112af67f89b43b109f0e3c359cbc..fb57e2dadc084fb74bf06d1dc7a9b1bc5fca42de 100644 (file)
@@ -55,11 +55,12 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
 {
        char *s, *t;
        int l;
+
        if (!in || !out || !(in->data)) {
                return -1;
        }
 
-       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data));
+       out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
        if (out->data == NULL) {
                ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
                return -1;
@@ -153,13 +154,14 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                               const struct ldb_val *v1, const struct ldb_val *v2)
 {
        const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
+       size_t n1 = v1->length, n2 = v2->length;
        const char *u1, *u2;
        char *b1, *b2;
        int ret;
-       while (*s1 == ' ') s1++;
-       while (*s2 == ' ') s2++;
+       while (*s1 == ' ' && n1) { s1++; n1--; };
+       while (*s2 == ' ' && n2) { s2++; n2--; };
        /* TODO: make utf8 safe, possibly with helper function from application */
-       while (*s1 && *s2) {
+       while (*s1 && *s2 && n1 && n2) {
                /* the first 127 (0x7F) chars are ascii and utf8 guarantes they
                 * never appear in multibyte sequences */
                if (((unsigned char)s1[0]) & 0x80) goto utf8str;
@@ -167,10 +169,11 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
                        break;
                if (*s1 == ' ') {
-                       while (s1[0] == s1[1]) s1++;
-                       while (s2[0] == s2[1]) s2++;
+                       while (s1[0] == s1[1] && n1) { s1++; n1--; }
+                       while (s2[0] == s2[1] && n2) { s2++; n2--; }
                }
                s1++; s2++;
+               n1--; n2--;
        }
        if (! (*s1 && *s2)) {
                /* check for trailing spaces only if one of the pointers
@@ -178,15 +181,18 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
                 * can mistakenly match.
                 * ex. "domain users" <-> "domainUpdates"
                 */
-               while (*s1 == ' ') s1++;
-               while (*s2 == ' ') s2++;
+               while (*s1 == ' ') { s1++; n1--; }
+               while (*s2 == ' ') { s2++; n2--; }
+       }
+       if (n1 != n2) {
+               return n1 - n2;
        }
        return (int)(toupper(*s1)) - (int)(toupper(*s2));
 
 utf8str:
        /* no need to recheck from the start, just from the first utf8 char found */
-       b1 = ldb_casefold(ldb, mem_ctx, s1);
-       b2 = ldb_casefold(ldb, mem_ctx, s2);
+       b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
+       b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
 
        if (b1 && b2) {
                /* Both strings converted correctly */
@@ -221,6 +227,7 @@ utf8str:
        return ret;
 }
 
+
 /*
   canonicalise a attribute in DN format
 */
index b7b4a60122f8c5b9d6e1ec7f66cca410457ae8a8..69ee2b6964f81e8a66b634f80965b3cabb823bb0 100644 (file)
@@ -40,8 +40,8 @@
   function to handle utf8 caseless comparisons
  */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *))
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t))
 {
        if (context)
                ldb->utf8_fns.context = context;
@@ -53,10 +53,10 @@ void ldb_set_utf8_fns(struct ldb_context *ldb,
   a simple case folding function
   NOTE: does not handle UTF8
 */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
 {
        int i;
-       char *ret = talloc_strdup(mem_ctx, s);
+       char *ret = talloc_strndup(mem_ctx, s, n);
        if (!s) {
                errno = ENOMEM;
                return NULL;
@@ -72,9 +72,9 @@ void ldb_set_utf8_default(struct ldb_context *ldb)
        ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default);
 }
 
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
 {
-       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
+       return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
 }
 
 /*
index 5dbf99e5bf9aa2aaf88ae34ba9b25089b2b2e1f7..937029f52ce3f53f2ec78274430a9d05416500d0 100644 (file)
@@ -203,7 +203,7 @@ struct ldb_debug_ops {
 */
 struct ldb_utf8_fns {
        void *context;
-       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s);
+       char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 };
 
 /**
@@ -1216,7 +1216,7 @@ void ldb_set_utf8_default(struct ldb_context *ldb);
    \note The default function is not yet UTF8 aware. Provide your own
          set of functions through ldb_set_utf8_fns()
 */
-char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n);
 
 /**
    Check the attribute name is valid according to rfc2251
@@ -1603,8 +1603,8 @@ int ldb_set_debug(struct ldb_context *ldb,
   this allows the user to set custom utf8 function for error reporting
 */
 void ldb_set_utf8_fns(struct ldb_context *ldb,
-                       void *context,
-                       char *(*casefold)(void *, void *, const char *));
+                     void *context,
+                     char *(*casefold)(void *, void *, const char *, size_t n));
 
 /**
    this sets up debug to print messages on stderr
index 62a6e35999d69c3e5382191c02b6570110ab7051..e1026ab781170a412cd12dcc12fddcec2c9da827 100644 (file)
@@ -235,7 +235,7 @@ int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct l
 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);
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n);
 
 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
 
index 6d141478ad4a097d162a0a3deb922047e351251e..169ff02da1ad9dfb75862886e156549ccff81a96 100644 (file)
@@ -93,7 +93,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(ldb, tmp_ctx, name);
+               vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name, strlen(name));
                vals[2][0].length = strlen((char *)vals[2][0].data);
 
                el[3].flags = 0;
index e626b6ef8aa7d0797e59e4117553ed5a0a219365..f2982302abb2ac9794b3d36a5215ba93e3377444 100644 (file)
@@ -29,7 +29,7 @@ struct cli_credentials;
 struct loadparm_context;
 struct event_context;
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
                                     struct event_context *ev,
index 0a7433696e586e84d2a43aa77c6471dd254c5f49..fab729c0367b07985ef8014ff35e7db8268e4399 100644 (file)
@@ -125,9 +125,9 @@ int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string)
        return ret;
 }
 
-char *wrap_casefold(void *context, void *mem_ctx, const char *s)
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
 {
-       return strupper_talloc(mem_ctx, s);
+       return strupper_talloc_n(mem_ctx, s, n);
 }
 
 
index 030ba7ebeef6aa0a4145eb47bbf61d665ba35bc5..43f98ae1a9f2f6f6abaace007b6345b875f191de 100644 (file)
@@ -22,6 +22,6 @@ int gendb_search_dn(struct ldb_context *ldb,
                 struct ldb_message ***res,
                 const char * const *attrs);
 int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string);
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
 
 #endif /* __LIB_UTIL_UTIL_LDB_H__ */