summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_tdb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-02-13 12:27:57 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:48 -0500
commit5a88d5211ba0f6b1d09cdd92489b34d0e603716b (patch)
treec344f9bb56c5e22e9f32ca0bc5f4f82a932cce05 /source4/lib/ldb/ldb_tdb
parente40da81aa4c279240c5ae3f1810fb9cedc15765d (diff)
downloadsamba-5a88d5211ba0f6b1d09cdd92489b34d0e603716b.tar.gz
samba-5a88d5211ba0f6b1d09cdd92489b34d0e603716b.tar.bz2
samba-5a88d5211ba0f6b1d09cdd92489b34d0e603716b.zip
r5374: - changed the dn key code in the ldb tdb backend to correctly honor
the case sensitive/insensitive flags on sections of a dn. So if a dn is made up of 4 attributes, and 2 of those are case insensitive and 2 are case sensitive, then all the attribute names are uppercases, but only the values of the case insensitive attributes are uppercased when forming the tdb key. - added code to canonicalise the dn, removing leading and trailing spaces from attribute names and values - when the @ATTRIBUTES record changes, fix the dn keys of any records that should now have new dn keys due to changes in the case sensitivity of the record I really did this to allow me to make the WINS database properly case insensitive, but it is also the correct general fix for ldb, as it matches the LDAP specification (and w2k LDAP server behaviour) (This used to be commit 0f034dc5636d182a1d9207ad662b3fc8df7ca3e4)
Diffstat (limited to 'source4/lib/ldb/ldb_tdb')
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c10
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c81
2 files changed, 89 insertions, 2 deletions
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) {