diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-13 12:27:57 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:48 -0500 |
commit | 5a88d5211ba0f6b1d09cdd92489b34d0e603716b (patch) | |
tree | c344f9bb56c5e22e9f32ca0bc5f4f82a932cce05 /source4/lib/ldb/ldb_tdb | |
parent | e40da81aa4c279240c5ae3f1810fb9cedc15765d (diff) | |
download | samba-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.c | 10 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 81 |
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) { |