LDAP virtual user username being rewritten:
Hi all,
I’m working on migrating a dovecot instance that formerly had its only user (me) stored in a SQL database to a new instance that uses LDAP so I don’t have to maintain a handful of different passwords. However, I’m ending up getting sent to an incorrect mailbox because the %d part of the username I enter is getting stripped somewhere along the lines. Dovecot debug logs show this happening here:
May 21 18:36:53 auth: Debug: client in: AUTH 1 PLAIN service=imap secured session=itEO5InfPJusEgKD lip=172.18.2.131 rip=172.18.2.131 lport=143 rport=39740 resp=<hidden> May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): Performing passdb lookup May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): pass search: base=ou=People,dc=coyhile,dc=com scope=subtree filter=(&(objectClass=posixAccount)(uid=hile)) fields=uid,userPassword May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): result: uid=hile userPassword=<hidden>; uid,userPassword unused May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): username changed hile@coyhile.com -> hile May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Finished passdb lookup May 21 18:36:53 auth: Debug: auth(hile,172.18.2.131,<itEO5InfPJusEgKD>): Auth request finished May 21 18:36:53 auth: Debug: client passdb out: OK 1 user=hile original_user=hile@coyhile.com May 21 18:36:53 auth: Debug: master in: REQUEST 473956353 9409 1 2c1f94ded4de2c343425c90eeee8d094 session_pid=9412 request_auth_token May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Performing userdb lookup May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): user search: base=ou=People,dc=coyhile,dc=com scope=subtree filter=(&(objectClass=posixAccount)(uid=hile)) fields=homeDirectory,uidNumber,gidNumber May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): result: homeDirectory=/home/hile uidNumber=10000 gidNumber=10000; homeDirectory,uidNumber,gidNumber unused May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Finished userdb lookup May 21 18:36:53 auth: Debug: master userdb out: USER 473956353 hile home=/data/mail/vmail//hile uid=998 gid=998 auth_token=3a262da408d33ce2c51ecb1ddd943203fdbb17a3 auth_user=hile@coyhile.com
Note the “username changed” line above. Clearly I’ve misconfigured something, butI am unsure what. My configuration is as follows:
root@basement-imap01:/var/log# doveconf -n # 2.3.7.2 (3c910f64b): /etc/dovecot/dovecot.conf # Pigeonhole version 0.5.7.2 () # OS: Linux 5.4.0-110-generic x86_64 Ubuntu 20.04.4 LTS # Hostname: basement-imap01.coyhile.com auth_debug = yes debug_log_path = /var/log/dovecot-debug.log doveadm_password = # hidden, use -P to show it mail_location = maildir:~/Maildir mail_privileged_group = mail namespace inbox { inbox = yes location = mailbox Drafts { special_use = \Drafts } mailbox Junk { special_use = \Junk } mailbox Sent { special_use = \Sent } mailbox "Sent Messages" { special_use = \Sent } mailbox Trash { special_use = \Trash } prefix = } passdb { args = /etc/dovecot/dovecot-ldap.conf.ext driver = ldap } protocols = " imap lmtp" service aggregator { fifo_listener replication-notify-fifo { mode = 0666 user = vmail } unix_listener replication-notify { mode = 0666 user = vmail } } service doveadm { inet_listener { port = 12345 } user = vmail } service replicator { unix_listener replicator-doveadm { mode = 0666 } } ssl_cert =
with the dovecot-ldap.conf.ext as follows:
root@basement-imap01:/etc/dovecot# cat dovecot-ldap.conf.ext # This file is commonly accessed via passdb {} or userdb {} section in # conf.d/auth-ldap.conf.ext
# This file is opened as root, so it should be owned by root and mode 0600. # # http://wiki2.dovecot.org/AuthDatabase/LDAP # # NOTE: If you're not using authentication binds, you'll need to give # dovecot-auth read access to userPassword field in the LDAP server. # With OpenLDAP this is done by modifying /etc/ldap/slapd.conf. There should # already be something like this:
# access to attribute=userPassword
# by dn="
# Space separated list of LDAP hosts to use. host:port is allowed too. #hosts = hosts = ldap.coyhile.com
# LDAP URIs to use. You can use this instead of hosts list. Note that this # setting isn't supported by all LDAP libraries. #uris =
# Distinguished Name - the username used to login to the LDAP server. # Leave it commented out to bind anonymously (useful with auth_bind=yes). #dn = dn = uid=dovecotquery,ou=people,dc=coyhile,dc=com
# Password for LDAP server, if dn is specified. #dnpass = dnpass = [REDACTED]
# Use SASL binding instead of the simple binding. Note that this changes # ldap_version automatically to be 3 if it's lower. #sasl_bind = no # SASL mechanism name to use. #sasl_mech = # SASL realm to use. #sasl_realm = # SASL authorization ID, ie. the dnpass is for this "master user", but the # dn is still the logged in user. Normally you want to keep this empty. #sasl_authz_id =
# Use TLS to connect to the LDAP server. #tls = no # TLS options, currently supported only with OpenLDAP: #tls_ca_cert_file = #tls_ca_cert_dir = #tls_cipher_suite = # TLS cert/key is used only if LDAP server requires a client certificate. #tls_cert_file = #tls_key_file = # Valid values: never, hard, demand, allow, try #tls_require_cert =
# Use the given ldaprc path. #ldaprc_path =
# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. # -1 = everything. You may need to recompile OpenLDAP with debugging enabled # to get enough output. #debug_level = 0
# Use authentication binding for verifying password's validity. This works by # logging into LDAP server using the username and password given by client. # The pass_filter is used to find the DN for the user. Note that the pass_attrs # is still used, only the password field is ignored in it. Before doing any # search, the binding is switched back to the default DN. #auth_bind = no
# If authentication binding is used, you can save one LDAP request per login # if users' DN can be specified with a common template. The template can use # the standard %variables (see user_filter). Note that you can't # use any pass_attrs if you use this setting. # # If you use this setting, it's a good idea to use a different # dovecot-ldap.conf.ext for userdb (it can even be a symlink, just as long as # the filename is different in userdb's args). That way one connection is used # only for LDAP binds and another connection is used for user lookups. # Otherwise the binding is changed to the default DN before each user lookup. # # For example: # auth_bind_userdn = cn=%u,ou=people,o=org # #auth_bind_userdn =
# LDAP protocol version to use. Likely 2 or 3. #ldap_version = 3
# LDAP base. %variables can be used here. # For example: dc=mail, dc=example, dc=org base = ou=People,dc=coyhile,dc=com
# Dereference: never, searching, finding, always #deref = never
# Search scope: base, onelevel, subtree #scope = subtree scope = subtree
# User attributes are given in LDAP-name=dovecot-internal-name list. The # internal names are: # uid - System UID # gid - System GID # home - Home directory # mail - Mail location # # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/UserDatabase/ExtraFields #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
# Filter for user lookup. Some variables can be used (see # http://wiki2.dovecot.org/Variables for full list): # %u - username # %n - user part in user@domain, same as %u if there's no domain # %d - domain part in user@domain, empty if user there's no domain #user_filter = (&(objectClass=posixAccount)(uid=%u)) user_filter = (&(objectClass=posixAccount)(uid=%u))
# Password checking attributes: # user: Virtual user name (user@domain), if you wish to change the # user-given username to something else # password: Password, may optionally start with {type}, eg. {crypt} # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/PasswordDatabase/ExtraFields #pass_attrs = uid=user,userPassword=password
# If you wish to avoid two LDAP lookups (passdb + userdb), you can use
# userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll
# also have to include user_attrs in pass_attrs field prefixed with "userdb_"
# string. For example:
#pass_attrs = uid=user,userPassword=password,
# homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid
# Filter for password lookups #pass_filter = (&(objectClass=posixAccount)(uid=%u)) pass_filter = (&(objectClass=posixAccount)(uid=%n))
# Attributes and filter to get a list of all users #iterate_attrs = uid=user iterate_attrs = maildrop=user iterate_filter = (objectClass=posixAccount)
# Default password scheme. "{scheme}" before password overrides this. # List of supported schemes is in: http://wiki2.dovecot.org/Authentication #default_pass_scheme = CRYPT
# By default all LDAP lookups are performed by the auth master process. # If blocking=yes, auth worker processes are used to perform the lookups. # Each auth worker process creates its own LDAP connection so this can # increase parallelism. With blocking=no the auth master process can # keep 8 requests pipelined for the LDAP connection, while with blocking=yes # each connection has a maximum of 1 request running. For small systems the # blocking=no is sufficient and uses less resources. #blocking = no root@basement-imap01:/etc/dovecot#
-- Coy Hile coy.hile@coyhile.com
Replying to myself…
Empirically, changing the following two lines in the LDAP configuration seems to have worked:
user_filter = (&(objectClass=posixAccount)(uid=%n))
and
pass_filter = (&(objectClass=posixAccount)(uid=%n))
My question remains, though, why was the original username getting rewritten by default?
-c
On May 21, 2022, at 3:18 PM, Coy Hile coy.hile@coyhile.com wrote:
Hi all,
I’m working on migrating a dovecot instance that formerly had its only user (me) stored in a SQL database to a new instance that uses LDAP so I don’t have to maintain a handful of different passwords. However, I’m ending up getting sent to an incorrect mailbox because the %d part of the username I enter is getting stripped somewhere along the lines. Dovecot debug logs show this happening here:
May 21 18:36:53 auth: Debug: client in: AUTH 1 PLAIN service=imap secured session=itEO5InfPJusEgKD lip=172.18.2.131 rip=172.18.2.131 lport=143 rport=39740 resp=<hidden> May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): Performing passdb lookup May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): pass search: base=ou=People,dc=coyhile,dc=com scope=subtree filter=(&(objectClass=posixAccount)(uid=hile)) fields=uid,userPassword May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): result: uid=hile userPassword=<hidden>; uid,userPassword unused May 21 18:36:53 auth: Debug: ldap(hile@coyhile.com,172.18.2.131,<itEO5InfPJusEgKD>): username changed hile@coyhile.com -> hile May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Finished passdb lookup May 21 18:36:53 auth: Debug: auth(hile,172.18.2.131,<itEO5InfPJusEgKD>): Auth request finished May 21 18:36:53 auth: Debug: client passdb out: OK 1 user=hile original_user=hile@coyhile.com May 21 18:36:53 auth: Debug: master in: REQUEST 473956353 9409 1 2c1f94ded4de2c343425c90eeee8d094 session_pid=9412 request_auth_token May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Performing userdb lookup May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): user search: base=ou=People,dc=coyhile,dc=com scope=subtree filter=(&(objectClass=posixAccount)(uid=hile)) fields=homeDirectory,uidNumber,gidNumber May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): result: homeDirectory=/home/hile uidNumber=10000 gidNumber=10000; homeDirectory,uidNumber,gidNumber unused May 21 18:36:53 auth: Debug: ldap(hile,172.18.2.131,<itEO5InfPJusEgKD>): Finished userdb lookup May 21 18:36:53 auth: Debug: master userdb out: USER 473956353 hile home=/data/mail/vmail//hile uid=998 gid=998 auth_token=3a262da408d33ce2c51ecb1ddd943203fdbb17a3 auth_user=hile@coyhile.com
Note the “username changed” line above. Clearly I’ve misconfigured something, butI am unsure what. My configuration is as follows:
root@basement-imap01:/var/log# doveconf -n # 2.3.7.2 (3c910f64b): /etc/dovecot/dovecot.conf # Pigeonhole version 0.5.7.2 () # OS: Linux 5.4.0-110-generic x86_64 Ubuntu 20.04.4 LTS # Hostname: basement-imap01.coyhile.com auth_debug = yes debug_log_path = /var/log/dovecot-debug.log doveadm_password = # hidden, use -P to show it mail_location = maildir:~/Maildir mail_privileged_group = mail namespace inbox { inbox = yes location = mailbox Drafts { special_use = \Drafts } mailbox Junk { special_use = \Junk } mailbox Sent { special_use = \Sent } mailbox "Sent Messages" { special_use = \Sent } mailbox Trash { special_use = \Trash } prefix = } passdb { args = /etc/dovecot/dovecot-ldap.conf.ext driver = ldap } protocols = " imap lmtp" service aggregator { fifo_listener replication-notify-fifo { mode = 0666 user = vmail } unix_listener replication-notify { mode = 0666 user = vmail } } service doveadm { inet_listener { port = 12345 } user = vmail } service replicator { unix_listener replicator-doveadm { mode = 0666 } } ssl_cert =
with the dovecot-ldap.conf.ext as follows:
root@basement-imap01:/etc/dovecot# cat dovecot-ldap.conf.ext # This file is commonly accessed via passdb {} or userdb {} section in # conf.d/auth-ldap.conf.ext
# This file is opened as root, so it should be owned by root and mode 0600. # # http://wiki2.dovecot.org/AuthDatabase/LDAP # # NOTE: If you're not using authentication binds, you'll need to give # dovecot-auth read access to userPassword field in the LDAP server. # With OpenLDAP this is done by modifying /etc/ldap/slapd.conf. There should # already be something like this:
# access to attribute=userPassword # by dn="
" read # add this # by anonymous auth # by self write # by * none # Space separated list of LDAP hosts to use. host:port is allowed too. #hosts = hosts = ldap.coyhile.com
# LDAP URIs to use. You can use this instead of hosts list. Note that this # setting isn't supported by all LDAP libraries. #uris =
# Distinguished Name - the username used to login to the LDAP server. # Leave it commented out to bind anonymously (useful with auth_bind=yes). #dn = dn = uid=dovecotquery,ou=people,dc=coyhile,dc=com
# Password for LDAP server, if dn is specified. #dnpass = dnpass = [REDACTED]
# Use SASL binding instead of the simple binding. Note that this changes # ldap_version automatically to be 3 if it's lower. #sasl_bind = no # SASL mechanism name to use. #sasl_mech = # SASL realm to use. #sasl_realm = # SASL authorization ID, ie. the dnpass is for this "master user", but the # dn is still the logged in user. Normally you want to keep this empty. #sasl_authz_id =
# Use TLS to connect to the LDAP server. #tls = no # TLS options, currently supported only with OpenLDAP: #tls_ca_cert_file = #tls_ca_cert_dir = #tls_cipher_suite = # TLS cert/key is used only if LDAP server requires a client certificate. #tls_cert_file = #tls_key_file = # Valid values: never, hard, demand, allow, try #tls_require_cert =
# Use the given ldaprc path. #ldaprc_path =
# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. # -1 = everything. You may need to recompile OpenLDAP with debugging enabled # to get enough output. #debug_level = 0
# Use authentication binding for verifying password's validity. This works by # logging into LDAP server using the username and password given by client. # The pass_filter is used to find the DN for the user. Note that the pass_attrs # is still used, only the password field is ignored in it. Before doing any # search, the binding is switched back to the default DN. #auth_bind = no
# If authentication binding is used, you can save one LDAP request per login # if users' DN can be specified with a common template. The template can use # the standard %variables (see user_filter). Note that you can't # use any pass_attrs if you use this setting. # # If you use this setting, it's a good idea to use a different # dovecot-ldap.conf.ext for userdb (it can even be a symlink, just as long as # the filename is different in userdb's args). That way one connection is used # only for LDAP binds and another connection is used for user lookups. # Otherwise the binding is changed to the default DN before each user lookup. # # For example: # auth_bind_userdn = cn=%u,ou=people,o=org # #auth_bind_userdn =
# LDAP protocol version to use. Likely 2 or 3. #ldap_version = 3
# LDAP base. %variables can be used here. # For example: dc=mail, dc=example, dc=org base = ou=People,dc=coyhile,dc=com
# Dereference: never, searching, finding, always #deref = never
# Search scope: base, onelevel, subtree #scope = subtree scope = subtree
# User attributes are given in LDAP-name=dovecot-internal-name list. The # internal names are: # uid - System UID # gid - System GID # home - Home directory # mail - Mail location # # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/UserDatabase/ExtraFields #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
# Filter for user lookup. Some variables can be used (see # http://wiki2.dovecot.org/Variables for full list): # %u - username # %n - user part in user@domain, same as %u if there's no domain # %d - domain part in user@domain, empty if user there's no domain #user_filter = (&(objectClass=posixAccount)(uid=%u)) user_filter = (&(objectClass=posixAccount)(uid=%u))
# Password checking attributes: # user: Virtual user name (user@domain), if you wish to change the # user-given username to something else # password: Password, may optionally start with {type}, eg. {crypt} # There are also other special fields which can be returned, see # http://wiki2.dovecot.org/PasswordDatabase/ExtraFields #pass_attrs = uid=user,userPassword=password
# If you wish to avoid two LDAP lookups (passdb + userdb), you can use # userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll # also have to include user_attrs in pass_attrs field prefixed with "userdb_" # string. For example: #pass_attrs = uid=user,userPassword=password,
# homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid# Filter for password lookups #pass_filter = (&(objectClass=posixAccount)(uid=%u)) pass_filter = (&(objectClass=posixAccount)(uid=%n))
# Attributes and filter to get a list of all users #iterate_attrs = uid=user iterate_attrs = maildrop=user iterate_filter = (objectClass=posixAccount)
# Default password scheme. "{scheme}" before password overrides this. # List of supported schemes is in: http://wiki2.dovecot.org/Authentication #default_pass_scheme = CRYPT
# By default all LDAP lookups are performed by the auth master process. # If blocking=yes, auth worker processes are used to perform the lookups. # Each auth worker process creates its own LDAP connection so this can # increase parallelism. With blocking=no the auth master process can # keep 8 requests pipelined for the LDAP connection, while with blocking=yes # each connection has a maximum of 1 request running. For small systems the # blocking=no is sufficient and uses less resources. #blocking = no root@basement-imap01:/etc/dovecot#
-- Coy Hile coy.hile@coyhile.com
-- Coy Hile coy.hile@coyhile.com
participants (1)
-
Coy Hile