From 9b52f07e5da5a9011e291b20a1eb8c98686f5cf9 Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Thu, 20 Jul 2017 08:49:25 +0300 Subject: [PATCH] dict-ldap: Escape LDAP search filter properly This is syntaxical escaping to make ldap servers accept queries with escapable characters, instead of erroring out. It is possible that the filter could have been modified in unexpected ways if the input comes from untrusted sources. --- src/plugins/dict-ldap/dict-ldap.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/plugins/dict-ldap/dict-ldap.c b/src/plugins/dict-ldap/dict-ldap.c index 005e8fc251..0d6cbc543d 100644 --- a/src/plugins/dict-ldap/dict-ldap.c +++ b/src/plugins/dict-ldap/dict-ldap.c @@ -14,6 +14,8 @@ #include "dict-private.h" #include "dict-ldap-settings.h" +static const char *LDAP_ESCAPE_CHARS = "*,\\#+<>;\"()= "; + struct ldap_dict; struct dict_ldap_op { @@ -163,6 +165,27 @@ int dict_ldap_connect(struct ldap_dict *dict, const char **error_r) return ldap_client_init(&set, &dict->client, error_r); } +#define IS_LDAP_ESCAPED_CHAR(c) \ + ((((unsigned char)(c)) & 0x80) != 0 || strchr(LDAP_ESCAPE_CHARS, (c)) != NULL) + +static const char *ldap_escape(const char *str) +{ + string_t *ret = NULL; + + for (const char *p = str; *p != '\0'; p++) { + if (IS_LDAP_ESCAPED_CHAR(*p)) { + if (ret == NULL) { + ret = t_str_new((size_t) (p - str) + 64); + str_append_n(ret, str, (size_t) (p - str)); + } + str_printfa(ret, "\\%02X", (unsigned char)*p); + } else if (ret != NULL) + str_append_c(ret, *p); + } + + return ret == NULL ? str : str_c(ret); +} + static void ldap_dict_build_query(struct ldap_dict *dict, const struct dict_ldap_map *map, ARRAY_TYPE(const_string) *values, bool priv, @@ -174,7 +197,7 @@ ldap_dict_build_query(struct ldap_dict *dict, const struct dict_ldap_map *map, t_array_init(&exp, 8); entry.key = '\0'; - entry.value = dict->username; + entry.value = ldap_escape(dict->username); entry.long_key = "username"; array_append(&exp, &entry, 1); @@ -189,7 +212,7 @@ ldap_dict_build_query(struct ldap_dict *dict, const struct dict_ldap_map *map, const char *const *valuep = array_idx(values, i); const char *const *long_keyp = array_idx(&(map->ldap_attributes), i); - entry.value = *valuep; + entry.value = ldap_escape(*valuep); entry.long_key = *long_keyp; array_append(&exp, &entry, 1); } -- 2.47.3