All,
I'm working in a multi-platform environment where user accounts are already held in Active Directory. I'm been trying to setup dovecot to perform user authentication against Active Directory using ldap.
My Environment is:
Platform OpenBSD 3.9 Dovecot Version 1.0.rc7 Active Directory Windows 2003
The approach I've taken (being the only one I was able to make work) is to use login_ldap to perform bind authentication against Active Directory/LDAP and authenticate dovecot using bsdauth. As far as I can tell the dovecot ldap authentication module requires access to the encrypted password field to which Active Directory does not permit access.
Simulated LDAP login fails and when debug is enabled writes the following to /var/log/maillog
==== /var/log/maillog ================ Oct 15 20:12:27 server dovecot: auth(default): client in: AUTH 1 PLAIN service=IMAP secured lip=127.0.0.1 rip=127.0.0.1 resp=***********************== Oct 15 20:12:27 server dovecot: auth(default): bsdauth(mcrokerx,127.0.0.1): invalid password field Oct 15 20:12:28 server dovecot: auth(default): client out: FAIL 1 user=mcrokerx Oct 15 20:12:38 server dovecot: imap-login: Aborted login: user=<mcrokerx>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, secured
It appears that the cause of these log messages are the following lines of code in src/auth/passdb-bsdauth.c
==== src/auth/passdb-bsdauth.c ======== 29 if (!IS_VALID_PASSWD(pw->pw_passwd)) { 30 auth_request_log_info(request, "bsdauth", 31 "invalid password field"); 32 callback(PASSDB_RESULT_USER_DISABLED, request); 33 return; 34 }
These lines seem to require that the pw structure contains the encrypted password in pw->pw_passwd. Where login_ldap is used against Active Directory the encrypted password is not available to bsdauth and instead pw->pw_passwd contains '*'. If auth_userokay is called independently it is however able to authenticate the user correctly, as such I wonder if the IS_VALID_PASSWD check is actually necessary.
It could be that my entire approach is wrong in which case I'm happy to be put right; however it seems that lines 29-34 need modification to correctly support this behaviour of bsdauth. This is beyond my limited ability in c but temporarily removing these lines of code from passdb-bsdauth.c has enabled me to authenticate dovecot against login_ldap (and thereby against Active Directory).
My config files are:
==== /etc/dovecot.conf ================ base_dir = /var/dovecot/ ssl_cert_file = /etc/ssl/certs/server.crt ssl_key_file = /etc/ssl/private/server.key disable_plaintext_auth = no login_dir = /var/dovecot/login login_user = _dovecot mmap_no_write = yes protocol imap { imap_client_workarounds = delay-newmail outlook-idle netscape-eoh tb-extra-mailbox-sep } protocol pop3 { pop3_uidl_format = %08Xu%08Xv pop3_client_workarounds = outlook-no-nuls oe-ns-eoh } auth default { mechanisms = plain passdb bsdauth { } userdb passwd-file { args = /etc/passwd } user = root } plugin { }
==== /etc/login.conf (exert) ==========
staff:
:auth=-ldap:
:x-ldap-server=10.0.0.23:
:x-ldap-port=389:
:x-ldap-noreferrals:
:x-ldap-uscope=subtree:
:x-ldap-basedn=dc=my,dc=domain,dc=co,dc=uk:
:x-ldap-binddn=cn=UnixUser,cn=Users,dc=my,dc=domain,dc=co,dc=uk:
:x-ldap-bindpw=mypassword:
:x-ldap-filter=(&(objectClass=user)(mail=%u)):
:datasize-cur=512M:
:datasize-max=infinity:
:maxproc-max=256:
:maxproc-cur=128:
:requirehome@:
:tc=default:
Note: for login_ldap to work it is necessary that the user information (minus password) is replicated on the localhost. I've done this using a relatively inelegant script which for completeness is below. I guess adding some error checking would be a good idea.
==== ldapsync.ksh =====================
#!/bin/ksh
ldapsearch -h 10.0.0.23
-D cn=UnixUser,cn=Users,dc=my,dc=domain,dc=co,dc=uk
-b cn=Users,dc=my,dc=domain,dc=co,dc=uk
-w mypassword
-v
-x "(objectClass=user)" |
while read key value ; do
if [ "$key" == name: ]; then
ldap_name="$value"
fi
# User Mail field as Unix name - remove @my.domain.co.uk if necessary
if [ "$key" == mail: ]; then
ldap_mail=$( echo "$value" | sed 's/@.*//g' )
if ( id 2>/dev/null >/dev/null $ldap_mail ); then
usermod -c "$ldap_name" -s osbin/nologin -g staff -L staff $ldap_mail
else
useradd -d /home/$ldap_mail -c "$ldap_name" -s /sbin/nologin -m
-g staff -L staff $ldap_mail fi ldap_name="" ldap_mail="" fi done
Martin