auth_bind with "()" in username not working
Hi all,
I have an AD testsetup with auth_bind setting
auth_bind_userdn = "spdev\\%Ln"
I created a testuser "claasc (test)" which works fine in all ldapfilters but not for the auth_bind.
the log shows everything correct just "invalid credentials"
mail.debug: Jun 9 14:12:31 dovecot: auth: Debug: auth client connected
(pid=12202) mail.debug: Jun 9 14:12:31 dovecot: auth: Debug: client
in: AUTH 1 PLAIN service=imap
secured session=T6knVtc0wQB/AAAB lip=127.0.0.1
rip=127.0.0.1 lport=143 rport=39873 mail.debug: Jun 9
14:12:31 dovecot: auth: Debug: client passdb out: CONT 1
mail.debug: Jun 9 14:12:31 dovecot: auth: Debug: client in:
CONT<hidden> mail.debug: Jun 9 14:12:31 dovecot: auth: Debug:
passwd-file(claasc (test),127.0.0.1,
So I guess its just a bind problem.
strace output from auth process of imap login:
write(26, "0-\2\1\4`(\2\1\3\4\25spdev\\claasc \\(test\\)\200\fHubertHans99", 47) = 47
the additional \\ in front of the brackets look strange to me and might be the reason.
tested Version is 2.2.18
Greetz Matze
Hi again,
did some more tseting on this.
I think the problem is the ldap userlookup, where "("s are evil and have to be quoted, but these quotes should be removed for the bind request.
I get my usernames from ldap with a filter like this
user_filter = (sAMAccountName=%Ln)
so I think in between this to steps is the problem.
For testing I hard coded the username for auth_bind and compared strace output from the auth process
auth_bind_userdn = "spdev\\claasc (test)"
this works fine. strace output from imap login
write(26, "0+\2\1\2`&\2\1\3\4\23spdev\\claasc (test)\200\fHubertHans99", 45)
compared to
auth_bind_userdn = "spdev\\%Ln"
which gives
write(26, "0-\2\1\2`(\2\1\3\4\25spdev\\claasc \\(test\\)\200\fHubertHans99", 47)
and wrong credentials
nobody else encountering similar problems? maybe the "()" are the only chars making problems at this point
Greetz Matze
Hi guys, I had a look in the sources about this problem. the problem seems to be the ldap_escape function that is called from ldap_verify_plain_auth_bind_userdn(..) I dont really know if this escaping is needed at this point, but with this change it works for me. No other problems discovered so far. could somebody, who is deeper in the sources give me a hint if this will make some troubles? Patch for 2.2.16: diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c index c1c2544..10bfe20 100644 --- a/src/auth/passdb-ldap.c +++ b/src/auth/passdb-ldap.c @@ -367,7 +367,7 @@ ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request, brequest->request.type = LDAP_REQUEST_TYPE_BIND; - vars = auth_request_get_var_expand_table(auth_request, ldap_escape); + vars = auth_request_get_var_expand_table(auth_request, NULL); dn = t_str_new(512); var_expand(dn, conn->set.auth_bind_userdn, vars);
Hi once again, replying to myself
I think I tracked down the problem with a local openldap server.
IMO the point is, you are using a ldap search escaping for a DN Request
which needs another kind of escaping.
the '(' worked well with my NULL-Patch because '(' is a char that needs
escaping for a search filter but not for DN.
I experienced some more problems with users containing a '+', '<' for
example. so I googled a bit and found this one.
http://www.openldap.org/lists/openldap-software/200407/msg00722.html
So you might be missing (or I didnt find it) a special DN escaping
function. I added one in the following patch and all the special chars
seems to work find in the bind AND search requests.
diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c
index 1476fa9..e9218ca 100644
--- a/src/auth/db-ldap.c
+++ b/src/auth/db-ldap.c
@@ -1423,6 +1422,35 @@ db_ldap_value_get_var_expand_table(struct
auth_request *auth_request, return table;
}
+
+#define IS_LDAPDN_ESCAPED_CHAR(c) \
+ ((c) == '"' || (c) == '+' || (c) == ',' || (c) == '\\' || (c)
== '<' || (c) == '>' || (c) == ';') +
+const char *ldapdn_escape(const char *str,
+ const struct auth_request *auth_request
ATTR_UNUSED) +{
+ const char *p;
+ string_t *ret;
+
+ for (p = str; *p != '\0'; p++) {
+ if (IS_LDAPDN_ESCAPED_CHAR(*p))
+ break;
+ }
+
+ 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_LDAPDN_ESCAPED_CHAR(*p))
+ str_append_c(ret, '\\');
+ str_append_c(ret, *p);
+ }
+ return str_c(ret);
+}
+
#define IS_LDAP_ESCAPED_CHAR(c) \
((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c
index c1c2544..5629d85 100644
--- a/src/auth/passdb-ldap.c
+++ b/src/auth/passdb-ldap.c
@@ -367,7 +374,7 @@ ldap_verify_plain_auth_bind_userdn(struct
auth_request *auth_request,
brequest->request.type = LDAP_REQUEST_TYPE_BIND;
- vars = auth_request_get_var_expand_table(auth_request,
ldap_escape);
+ vars = auth_request_get_var_expand_table(auth_request,
ldapdn_escape);
dn = t_str_new(512);
var_expand(dn, conn->set.auth_bind_userdn, vars);
an ldif file for testing.
add them with
# slapadd -l filename
# cat user.ldif
dn: dc=uma,dc=local
dc: uma
objectClass: dcObject
objectClass: domain
structuralObjectClass: domain
entryUUID: 5cdda309-7ad5-4b03-b981-784c1b7ec27e
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231019Z
entryCSN: 20160729231019.057480Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231019Z
dn: ou=users,dc=uma,dc=local
ou: users
objectClass: organizationalUnit
structuralObjectClass: organizationalUnit
entryUUID: cc56753d-09aa-404a-8446-5d0bf75531a3
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231019Z
entryCSN: 20160729231019.147739Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231019Z
dn: uid=s\+schmidt,ou=users,dc=uma,dc=local
givenName: Stefan
uid: s+schmidt
sn: Schmidt
mail:: cy5zY2htaWR0QHR0dC1wb2ludC5sb2NhbA0=
cn: Stefan Schmidt
objectClass: person
objectClass: inetOrgPerson
userPassword:: aW5zZWN1cmU=
structuralObjectClass: inetOrgPerson
entryUUID: fffad6fe-d083-4ab9-b6c2-da82067d510b
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231039Z
entryCSN: 20160729231039.234641Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231039Z
dn: uid=m\\mueller,ou=users,dc=uma,dc=local
givenName: Melanie
uid: m\mueller
sn: Mueller
mail:: bS5tdWVsbGVyQHR0dC1wb2ludC5sb2NhbA0=
cn: Melanie Mueller
objectClass: person
objectClass: inetOrgPerson
userPassword:: aW5zZWN1cmU=
structuralObjectClass: inetOrgPerson
entryUUID: 6e1a3a14-dd75-4766-a308-44a8437a0139
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231039Z
entryCSN: 20160729231039.308360Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231039Z
dn: uid=k(lammer,ou=users,dc=uma,dc=local
givenName: karl
uid: k(lammer
sn: klammer
mail:: a0BzcGRldi5sb2NhbA0=
cn: karl klammer
objectClass: person
objectClass: inetOrgPerson
userPassword:: aW5zZWN1cmU=
structuralObjectClass: inetOrgPerson
entryUUID: b5a26caf-62b1-4cf5-985c-3167424d90c7
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231039Z
entryCSN: 20160729231039.315462Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231039Z
dn: uid=g\>ross,ou=users,dc=uma,dc=local
givenName: v
uid: g>ross
sn: n
mail:: Z0BzcGRldi5sb2NhbA0=
cn: v n
objectClass: person
objectClass: inetOrgPerson
userPassword:: aW5zZWN1cmU=
structuralObjectClass: inetOrgPerson
entryUUID: fb7ad7cc-a028-444c-8109-cfe9dd182b0b
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231039Z
entryCSN: 20160729231039.364040Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231039Z
dn: uid=mmeier,ou=users,dc=uma,dc=local
givenName: Manfred
uid: mmeier
sn: Meier
mail:: bS5tZWllckB0dHQtcG9pbnQubG9jYWwN
cn: Manfred Meier
objectClass: person
objectClass: inetOrgPerson
userPassword:: aW5zZWN1cmU=
structuralObjectClass: inetOrgPerson
entryUUID: 16ef0511-25ed-4001-a1bd-1ad72abbfc02
creatorsName: cn=admin,dc=uma,dc=local
createTimestamp: 20160729231039Z
entryCSN: 20160729231039.369003Z#000000#000#000000
modifiersName: cn=admin,dc=uma,dc=local
modifyTimestamp: 20160729231039Z
Greetz
On Tue, 26 Jul 2016 13:07:24 +0200
Matthias Lay
Hi guys,
I had a look in the sources about this problem.
the problem seems to be the ldap_escape function that is called from
ldap_verify_plain_auth_bind_userdn(..)
I dont really know if this escaping is needed at this point, but with this change it works for me. No other problems discovered so far.
could somebody, who is deeper in the sources give me a hint if this will make some troubles?
Patch for 2.2.16:
diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c index c1c2544..10bfe20 100644 --- a/src/auth/passdb-ldap.c +++ b/src/auth/passdb-ldap.c @@ -367,7 +367,7 @@ ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request, brequest->request.type = LDAP_REQUEST_TYPE_BIND;
- vars = auth_request_get_var_expand_table(auth_request, ldap_escape); + vars = auth_request_get_var_expand_table(auth_request, NULL); dn = t_str_new(512); var_expand(dn, conn->set.auth_bind_userdn, vars);
sorry forgot
password for all test users is "insecure"
and you´ll need the function in the header too
diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h
index 8a51081..82ed1b3 100644
--- a/src/auth/db-ldap.h
+++ b/src/auth/db-ldap.h
@@ -197,6 +197,8 @@ void db_ldap_enable_input(struct ldap_connection
*conn, bool enable);
const char *ldap_escape(const char *str,
const struct auth_request *auth_request);
+const char *ldapdn_escape(const char *str,
+ const struct auth_request *auth_request);
const char *ldap_get_error(struct ldap_connection *conn);
struct db_ldap_result_iterate_context *
On Tue, 2 Aug 2016 14:32:48 +0200
Matthias Lay
Hi once again, replying to myself
I think I tracked down the problem with a local openldap server.
IMO the point is, you are using a ldap search escaping for a DN Request which needs another kind of escaping. the '(' worked well with my NULL-Patch because '(' is a char that needs escaping for a search filter but not for DN.
I experienced some more problems with users containing a '+', '<' for example. so I googled a bit and found this one.
http://www.openldap.org/lists/openldap-software/200407/msg00722.html
So you might be missing (or I didnt find it) a special DN escaping function. I added one in the following patch and all the special chars seems to work find in the bind AND search requests.
diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c index 1476fa9..e9218ca 100644 --- a/src/auth/db-ldap.c +++ b/src/auth/db-ldap.c @@ -1423,6 +1422,35 @@ db_ldap_value_get_var_expand_table(struct auth_request *auth_request, return table; }
+ +#define IS_LDAPDN_ESCAPED_CHAR(c) \ + ((c) == '"' || (c) == '+' || (c) == ',' || (c) == '\\' || (c) == '<' || (c) == '>' || (c) == ';') + +const char *ldapdn_escape(const char *str, + const struct auth_request *auth_request ATTR_UNUSED) +{ + const char *p; + string_t *ret; + + for (p = str; *p != '\0'; p++) { + if (IS_LDAPDN_ESCAPED_CHAR(*p)) + break; + } + + 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_LDAPDN_ESCAPED_CHAR(*p)) + str_append_c(ret, '\\'); + str_append_c(ret, *p); + } + return str_c(ret); +} + #define IS_LDAP_ESCAPED_CHAR(c) \ ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c index c1c2544..5629d85 100644 --- a/src/auth/passdb-ldap.c +++ b/src/auth/passdb-ldap.c @@ -367,7 +374,7 @@ ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request, brequest->request.type = LDAP_REQUEST_TYPE_BIND;
- vars = auth_request_get_var_expand_table(auth_request, ldap_escape); + vars = auth_request_get_var_expand_table(auth_request, ldapdn_escape); dn = t_str_new(512); var_expand(dn, conn->set.auth_bind_userdn, vars);
an ldif file for testing. add them with # slapadd -l filename
# cat user.ldif dn: dc=uma,dc=local dc: uma objectClass: dcObject objectClass: domain structuralObjectClass: domain entryUUID: 5cdda309-7ad5-4b03-b981-784c1b7ec27e creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231019Z entryCSN: 20160729231019.057480Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231019Z
dn: ou=users,dc=uma,dc=local ou: users objectClass: organizationalUnit structuralObjectClass: organizationalUnit entryUUID: cc56753d-09aa-404a-8446-5d0bf75531a3 creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231019Z entryCSN: 20160729231019.147739Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231019Z
dn: uid=s\+schmidt,ou=users,dc=uma,dc=local givenName: Stefan uid: s+schmidt sn: Schmidt mail:: cy5zY2htaWR0QHR0dC1wb2ludC5sb2NhbA0= cn: Stefan Schmidt objectClass: person objectClass: inetOrgPerson userPassword:: aW5zZWN1cmU= structuralObjectClass: inetOrgPerson entryUUID: fffad6fe-d083-4ab9-b6c2-da82067d510b creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231039Z entryCSN: 20160729231039.234641Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231039Z
dn: uid=m\\mueller,ou=users,dc=uma,dc=local givenName: Melanie uid: m\mueller sn: Mueller mail:: bS5tdWVsbGVyQHR0dC1wb2ludC5sb2NhbA0= cn: Melanie Mueller objectClass: person objectClass: inetOrgPerson userPassword:: aW5zZWN1cmU= structuralObjectClass: inetOrgPerson entryUUID: 6e1a3a14-dd75-4766-a308-44a8437a0139 creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231039Z entryCSN: 20160729231039.308360Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231039Z
dn: uid=k(lammer,ou=users,dc=uma,dc=local givenName: karl uid: k(lammer sn: klammer mail:: a0BzcGRldi5sb2NhbA0= cn: karl klammer objectClass: person objectClass: inetOrgPerson userPassword:: aW5zZWN1cmU= structuralObjectClass: inetOrgPerson entryUUID: b5a26caf-62b1-4cf5-985c-3167424d90c7 creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231039Z entryCSN: 20160729231039.315462Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231039Z
dn: uid=g\>ross,ou=users,dc=uma,dc=local givenName: v uid: g>ross sn: n mail:: Z0BzcGRldi5sb2NhbA0= cn: v n objectClass: person objectClass: inetOrgPerson userPassword:: aW5zZWN1cmU= structuralObjectClass: inetOrgPerson entryUUID: fb7ad7cc-a028-444c-8109-cfe9dd182b0b creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231039Z entryCSN: 20160729231039.364040Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231039Z
dn: uid=mmeier,ou=users,dc=uma,dc=local givenName: Manfred uid: mmeier sn: Meier mail:: bS5tZWllckB0dHQtcG9pbnQubG9jYWwN cn: Manfred Meier objectClass: person objectClass: inetOrgPerson userPassword:: aW5zZWN1cmU= structuralObjectClass: inetOrgPerson entryUUID: 16ef0511-25ed-4001-a1bd-1ad72abbfc02 creatorsName: cn=admin,dc=uma,dc=local createTimestamp: 20160729231039Z entryCSN: 20160729231039.369003Z#000000#000#000000 modifiersName: cn=admin,dc=uma,dc=local modifyTimestamp: 20160729231039Z
Greetz
On Tue, 26 Jul 2016 13:07:24 +0200 Matthias Lay
wrote: Hi guys,
I had a look in the sources about this problem.
the problem seems to be the ldap_escape function that is called from
ldap_verify_plain_auth_bind_userdn(..)
I dont really know if this escaping is needed at this point, but with this change it works for me. No other problems discovered so far.
could somebody, who is deeper in the sources give me a hint if this will make some troubles?
Patch for 2.2.16:
diff --git a/src/auth/passdb-ldap.c b/src/auth/passdb-ldap.c index c1c2544..10bfe20 100644 --- a/src/auth/passdb-ldap.c +++ b/src/auth/passdb-ldap.c @@ -367,7 +367,7 @@ ldap_verify_plain_auth_bind_userdn(struct auth_request *auth_request, brequest->request.type = LDAP_REQUEST_TYPE_BIND;
- vars = auth_request_get_var_expand_table(auth_request, ldap_escape); + vars = auth_request_get_var_expand_table(auth_request, NULL); dn = t_str_new(512); var_expand(dn, conn->set.auth_bind_userdn, vars);
-- Mit freundlichem Gruß / Best regards, Matthias Lay Head of UMA development Securepoint GmbH Salzstrasse 1 D-21335 Lüneburg https://www.securepoint.de Tel.: +49(0)413124010 Fax: +49(0)4131240118 Geschäftsführer: Lutz Hausmann, Claudia Hausmann Amtsgericht Lüneburg HRB 1776 USt.-ID-Nr.: DE 188 528 597
participants (1)
-
Matthias Lay