[Dovecot] Authenticating dovecot against Active Directory using bsdauth and login_ldap

Martin Croker mcroker.pub at gmail.com
Sun Oct 15 21:48:17 UTC 2006


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


More information about the dovecot mailing list