summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/ldb/include/ldb.h9
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c10
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c81
-rw-r--r--source4/lib/ldb/tests/test-attribs.ldif2
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