CheckPassword
=============

Checkpassword is an authentication interface originally implemented by qmail
[http://www.qmail.org/]. Checkpassword combines both the <password database>
[PasswordDatabase.txt] and <user database> [UserDatabase.txt] lookups into a
single checkpassword lookup, which makes the standard implementation unsuitable
for a standalone userdb. With Dovecot extensions it's also possible to use
checkpassword as a userdb.

Typically you'll use <prefetch> [UserDatabase.Prefetch.txt] as the userdb, but
it's not required that you use the checkpassword script's userdb capabilities.
You can still use for example <static userdb> [UserDatabase.Static.txt] if
you're using only a single UID and GID, and your home directory fits into a
template.

Deliver
-------

If your checkpassword script doesn't support Dovecot extensions, you can't use
it as a user database. This means that if you wish to use <LDA.txt>, you can't
use the '-d' parameter to do userdb lookups. There are two ways to solve this:

 1. Use another userdb which does the lookup for deliver, for example <SQL>
    [AuthDatabase.SQL.txt] or <static> [UserDatabase.Static.txt]. Add this
    userdb after the prefetch userdb.
 2. Use a script to look up the user's home directory and run deliver without
    '-d' parameter. For example:

---%<-------------------------------------------------------------------------
#!/bin/sh

# <<Lookup user's home directory here.>>

# If users have different UIDs/GIDs, make sure to also change this process's
UID and GID.
# If you want to override any settings, use dovecot-lda's -o parameter
# (e.g. dovecot-lda -o mail_location=maildir:~/Maildir).

export HOME
exec /usr/local/libexec/dovecot/dovecot-lda
---%<-------------------------------------------------------------------------

Checkpassword Interface
-----------------------

The interface is specified in http://cr.yp.to/checkpwd/interface.html. However
here's a quick tutorial for writing a script:

 * Read '<username> NUL <password> NUL' from fd 3.
 * Verify the username and password.
    * If the authentication fails, exit with code 1. This makes Dovecot give
      "Authentication failed" error to user.
    * If you encounter an internal error, exit with code 111. This makes
      Dovecot give "Temporary authentication failure" error to user.
 * If the authentication succeeds, you'll need to:
    * Set user's home directory to '$HOME' environment. This isn't required,
      <but highly encouraged> [VirtualUsers.txt].
    * Set '$USER' environment variable. If the user name was changed (eg. if
      you lowercased "Username" to "username"), you can tell about it to
      Dovecot by setting '$USER' to the changed user name.
    * Change the process's effective UID and GID to the user's <UNIX UID and
      GID> [UserIds.txt].
       * Alternatively you could set 'userdb_uid' and 'userdb_gid' environments
         and add them to 'EXTRA' environment (see below for Dovecot
         extensions).
    * Your program received a path to 'checkpassword-reply' binary as the first
      parameter. Execute it.

Qmail-LDAP
----------

Note that auth_imap that comes with qmail-ldap is not compatible with this
interface. You can get a patch that adds auth_dovecot functionality to
qmail-ldap here
[http://japc.uncovering.org/dovecot/qmail-ldap-1.03-20060201-dovecot.patch]. Or
you can use auth_pop instead, but you may need to pass /aliasempty/ to let
auth_pop find the Maildir, so it is recommended to write a
/var/qmail/bin/auth_dovecot wrapper (don't forget to chmod +x it) around
auth_pop.

---%<-------------------------------------------------------------------------
#!/bin/sh
QMAIL="/var/qmail"
if [ -e $QMAIL/control/defaultdelivery ]; then
    ALIASEMPTY=`head -n 1 $QMAIL/control/defaultdelivery 2> /dev/null`
else
    ALIASEMPTY=`head -n 1 $QMAIL/control/aliasempty 2> /dev/null`
fi
ALIASEMPTY=${ALIASEMPTY:-"./Maildir/"}
exec $QMAIL/bin/auth_pop "$@" $ALIASEMPTY
---%<-------------------------------------------------------------------------

you can also use this wrapper to pass LOGLEVEL environmental variable to
auth_pop.

Dovecot Extensions
------------------

If you wish to return <extra fields> [PasswordDatabase.ExtraFields.txt] for
Dovecot, set them in environment variables and then list them in EXTRA
environment variable. The <userdb extra fields> [UserDatabase.ExtraFields.txt]
can be returned by prefixing them with 'userdb_'. For example:

---%<-------------------------------------------------------------------------
userdb_quota_rule=*:storage=10000
userdb_mail=mbox:$HOME/mboxes
EXTRA=userdb_quota_rule userdb_mail
---%<-------------------------------------------------------------------------

Dovecot also sets some environment variables that the script may use:

 * 'SERVICE': contains eg. imap, pop3 or smtp
 * 'TCPLOCALIP' and 'TCPREMOTEIP': Client socket's IP addresses if available
 * 'MASTER_USER': If master login is attempted. This means that the password
   contains the master user's password and the normal username contains the
   user who master wants to log in as.

Checkpassword as userdb
-----------------------

Dovecot calls the script with 'AUTHORIZED=1' environment set when performing a
userdb lookup. The script must acknowledge this by changing the environment to
'AUTHORIZED=2', otherwise the lookup fails. Other than that, the script works
the same way as a passdb checkpassword script.

Example
-------

The standard way:

---%<-------------------------------------------------------------------------
passdb {
  driver = checkpassword
  args = /usr/bin/checkpassword
}
userdb {
  driver = prefetch
}
# If you want to use deliver -d and your users are in SQL:
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
---%<-------------------------------------------------------------------------

Using checkpassword only to verify the password:

---%<-------------------------------------------------------------------------
passdb {
  driver = checkpassword
  args = /usr/bin/checkpassword
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/home/%u
}
---%<-------------------------------------------------------------------------

(This file was created from the wiki on 2012-01-06 04:42)
