diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 9 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_index.c | 10 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 81 | ||||
-rw-r--r-- | source4/lib/ldb/tests/test-attribs.ldif | 2 |
4 files changed, 96 insertions, 6 deletions
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index c6f96f6dea..09b4cbf84a 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -140,6 +140,11 @@ struct ldb_debug_ops { #define LDB_FLG_RDONLY 1 +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(a,b) +#endif + + /* connect to a database. The URL can either be one of the following forms ldb://path @@ -302,10 +307,6 @@ struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v); -#ifndef PRINTF_ATTRIBUTE -#define PRINTF_ATTRIBUTE(a,b) -#endif - /* this allows the user to set a debug function for error reporting */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index c7dc9f1345..1cf1b5c531 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -935,6 +935,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * struct ldb_module *module = state; struct ldb_message *msg; int ret; + TDB_DATA key2; if (strncmp(key.dptr, "DN=@", 4) == 0 || strncmp(key.dptr, "DN=", 3) != 0) { @@ -952,6 +953,15 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void * return -1; } + /* check if the DN key has changed, perhaps due to the + case insensitivity of an element changing */ + key2 = ltdb_key(module, msg->dn); + if (strcmp(key2.dptr, key.dptr) != 0) { + tdb_delete(tdb, key); + tdb_store(tdb, key2, data, 0); + } + talloc_free(key2.dptr); + if (!msg->dn) { msg->dn = key.dptr+3; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index b1de96986d..07a9fa8866 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -42,6 +42,82 @@ #define LDBLOCK "INT_LDBLOCK" + +/* + casefold a dn. We need to uppercase the attribute names, and the + attribute values of case insensitive attributes. We also need to remove + extraneous spaces between elements +*/ +static char *ltdb_dn_fold(struct ldb_module *module, const char *dn) +{ + const char *dn_orig = dn; + struct ldb_context *ldb = module->ldb; + TALLOC_CTX *tmp_ctx = talloc_new(ldb); + char *ret; + size_t len; + + ret = talloc_strdup(tmp_ctx, ""); + if (ret == NULL) goto failed; + + while ((len = strcspn(dn, ",")) > 0) { + char *p = strchr(dn, '='); + char *attr, *value; + int flags; + + if (p == NULL || (p-dn) > len) goto failed; + + attr = talloc_strndup(tmp_ctx, dn, p-dn); + if (attr == NULL) goto failed; + + /* trim spaces from the attribute name */ + while (' ' == *attr) attr++; + while (' ' == attr[strlen(attr)-1]) { + attr[strlen(attr)-1] = 0; + } + if (*attr == 0) goto failed; + + value = talloc_strndup(tmp_ctx, p+1, len-(p+1-dn)); + if (value == NULL) goto failed; + + /* trim spaces from the value */ + while (' ' == *value) value++; + while (' ' == value[strlen(value)-1]) { + value[strlen(value)-1] = 0; + } + if (*value == 0) goto failed; + + flags = ltdb_attribute_flags(module, attr); + + attr = ldb_casefold(ldb, attr); + if (attr == NULL) goto failed; + talloc_steal(tmp_ctx, attr); + + if (flags & LTDB_FLAG_CASE_INSENSITIVE) { + value = ldb_casefold(ldb, value); + if (value == NULL) goto failed; + talloc_steal(tmp_ctx, value); + } + + if (dn[len] == ',') { + ret = talloc_asprintf_append(ret, "%s=%s,", attr, value); + } else { + ret = talloc_asprintf_append(ret, "%s=%s", attr, value); + } + if (ret == NULL) goto failed; + + dn += len; + if (*dn == ',') dn++; + } + + talloc_steal(ldb, ret); + talloc_free(tmp_ctx); + return ret; + +failed: + talloc_free(tmp_ctx); + return ldb_casefold(ldb, dn_orig); +} + /* form a TDB_DATA for a record key caller frees @@ -65,7 +141,8 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) there are 3 cases dealt with in this code: - 1) if the dn doesn't start with @INDEX: then uppercase whole dn + 1) if the dn doesn't start with @INDEX: then uppercase the attribute + names and the attributes values of case insensitive attributes 2) if the dn starts with @INDEX:attr and 'attr' is a case insensitive attribute then uppercase whole dn 3) if the dn starts with @INDEX:attr and 'attr' is a case sensitive @@ -95,7 +172,7 @@ struct TDB_DATA ltdb_key(struct ldb_module *module, const char *dn) } talloc_free(attr_name); } else { - dn_folded = ldb_casefold(ldb, dn); + dn_folded = ltdb_dn_fold(module, dn); } if (!dn_folded) { diff --git a/source4/lib/ldb/tests/test-attribs.ldif b/source4/lib/ldb/tests/test-attribs.ldif index bfa51b05fa..4bfb1ebd65 100644 --- a/source4/lib/ldb/tests/test-attribs.ldif +++ b/source4/lib/ldb/tests/test-attribs.ldif @@ -1,5 +1,7 @@ dn: @ATTRIBUTES uid: CASE_INSENSITIVE WILDCARD +cn: CASE_INSENSITIVE +ou: CASE_INSENSITIVE dn: CASE_INSENSITIVE dn: @SUBCLASSES |