changeset 22438:1e3702379e9d

auth: Escape LDAP search filter properly This is syntaxical escaping to make ldap servers accept queries with escapable characters, instead of erroring out.
author Aki Tuomi <aki.tuomi@dovecot.fi>
date Thu, 20 Jul 2017 13:24:21 +0300
parents d4b14f33b5b1
children 74c84176bbdc
files src/auth/db-ldap.c
diffstat 1 files changed, 14 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/db-ldap.c	Thu Jul 20 08:49:25 2017 +0300
+++ b/src/auth/db-ldap.c	Thu Jul 20 13:24:21 2017 +0300
@@ -49,6 +49,8 @@
 #  define LDAP_OPT_SUCCESS LDAP_SUCCESS
 #endif
 
+static const char *LDAP_ESCAPE_CHARS = "*,\\#+<>;\"()= ";
+
 struct db_ldap_result {
 	int refcount;
 	LDAPMessage *msg;
@@ -1461,31 +1463,25 @@
 }
 
 #define IS_LDAP_ESCAPED_CHAR(c) \
-	((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
+	((((unsigned char)(c)) & 0x80) != 0 || strchr(LDAP_ESCAPE_CHARS, (c)) != NULL)
 
 const char *ldap_escape(const char *str,
 			const struct auth_request *auth_request ATTR_UNUSED)
 {
-	const char *p;
-	string_t *ret;
+	string_t *ret = NULL;
 
-	for (p = str; *p != '\0'; p++) {
-		if (IS_LDAP_ESCAPED_CHAR(*p))
-			break;
+	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);
 	}
 
-	if (*p == '\0')
-		return str;
-
-	ret = t_str_new((size_t) (p - str) + 64);
-	str_append_n(ret, str, (size_t) (p - str));
-
-	for (; *p != '\0'; p++) {
-		if (IS_LDAP_ESCAPED_CHAR(*p))
-			str_append_c(ret, '\\');
-		str_append_c(ret, *p);
-	}
-	return str_c(ret);
+	return ret == NULL ? str : str_c(ret);
 }
 
 static bool