From: Andrew Tridgell Date: Fri, 22 Aug 2008 07:36:56 +0000 (+1000) Subject: fixed a problem with length limited ldap values X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=cc43037f19056ed24d7fffa54456d597c63ad105;p=kamenim%2Fsamba.git fixed a problem with length limited ldap values 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) --- diff --git a/source4/lib/charset/charset.h b/source4/lib/charset/charset.h index baa7df532b..c49745cd7f 100644 --- a/source4/lib/charset/charset.h +++ b/source4/lib/charset/charset.h @@ -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); diff --git a/source4/lib/charset/util_unistr.c b/source4/lib/charset/util_unistr.c index 19a4f3236c..09ec7b0471 100644 --- a/source4/lib/charset/util_unistr.c +++ b/source4/lib/charset/util_unistr.c @@ -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. **/ diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 8ed2763d4d..fb57e2dadc 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -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 */ diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index b7b4a60122..69ee2b6964 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -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); } /* diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 5dbf99e5bf..937029f52c 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -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 diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 62a6e35999..e1026ab781 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -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); diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c index 6d141478ad..169ff02da1 100644 --- a/source4/lib/ldb/tools/ldbtest.c +++ b/source4/lib/ldb/tools/ldbtest.c @@ -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; diff --git a/source4/lib/ldb_wrap.h b/source4/lib/ldb_wrap.h index e626b6ef8a..f2982302ab 100644 --- a/source4/lib/ldb_wrap.h +++ b/source4/lib/ldb_wrap.h @@ -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, diff --git a/source4/lib/util/util_ldb.c b/source4/lib/util/util_ldb.c index 0a7433696e..fab729c036 100644 --- a/source4/lib/util/util_ldb.c +++ b/source4/lib/util/util_ldb.c @@ -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); } diff --git a/source4/lib/util/util_ldb.h b/source4/lib/util/util_ldb.h index 030ba7ebee..43f98ae1a9 100644 --- a/source4/lib/util/util_ldb.h +++ b/source4/lib/util/util_ldb.h @@ -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__ */