diff options
Diffstat (limited to 'doc/wiki/AuthDatabase.CheckPassword.txt')
-rw-r--r-- | doc/wiki/AuthDatabase.CheckPassword.txt | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/doc/wiki/AuthDatabase.CheckPassword.txt b/doc/wiki/AuthDatabase.CheckPassword.txt new file mode 100644 index 0000000..c285868 --- /dev/null +++ b/doc/wiki/AuthDatabase.CheckPassword.txt @@ -0,0 +1,234 @@ +CheckPassword +============= + +Since v2.3.0 You can also use Lua to write your custom authentication, see +<AuthDatabase.Lua.txt> + +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. + +Security +-------- + +The standard checkpassword design is incompatible with Dovecot's security +model. If the system has local users and the checkpassword script setuid()s +into a local user, the user is able to ptrace into the communication and change +the authentication results. This is of course undesirable, so v2.2.7+ will just +refuse to run in such environments by default. The possibilities to solve this +are: + + 1. If possible, change the checkpassword to return 'userdb_uid' and + 'userdb_gid' extra fields instead of using 'setuid()' and 'setgid()'. This + also improves the performance. + 2. If you can't change the script, you can make Dovecot's + 'checkpassword-reply' binary setuid or setgid (e.g.'chgrp dovecot + /usr/local/libexec/dovecot/checkpassword-reply; chmod g+s + /usr/local/libexec/dovecot/checkpassword-reply') + 3. If you don't have any untrusted local users and you just don't care about + this check, you can set 'INSECURE_SETUID=1' environment e.g. with a wrapper + checkpassword script. + +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. + * This error is returned both for password mismatch and also if the user + doesn't exist at all. Internally Dovecot maps this as password + mismatch. + * 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. + * Return the user's <UNIX UID and GID> [UserIds.txt] using 'userdb_uid' and + 'userdb_gid' environments and add them to the 'EXTRA' environment (see + below for Dovecot extensions). + * This is recommended over actually changing the UID/GID using + setuid()/setgid() as specified by the standard checkpassword + interface, because it's <incompatible with Dovecot's security model> + [AuthDatabase.CheckPassword.txt]. + * 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. + * 'AUTH_*': All of the <auth variables> [Variables.txt] are available as + 'AUTH_<long name>' extra fields. For example '%{cert}' is in 'AUTH_CERT'. + (v2.0.16+) + +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. If user doesn't exist, use exit +code 3. + +Checkpassword with passdb lookups (v2.1.2+) +------------------------------------------- + +Normally checkpassword answers to questions "is user X's password Y?" This +doesn't work with non-plaintext auth mechanisms, or when Dovecot wants to do a +non-authenticating passdb lookup (e.g. for LMTP proxy). These passdb +credentials lookups can be implemented the same way as a userdb lookup (i.e. +change the 'AUTHORIZED' environment). + + * 'AUTHORIZED=1' is set, just like for userdb lookup + * When doing a non-plaintext authentication: + * 'CREDENTIALS_LOOKUP=1' environment is set + * The password scheme that Dovecot wants is available in 'SCHEME' + environment (e.g.'SCHEME=CRAM-MD5') + * If a password is returned, it must be returned as + 'password={SCHEME}secret'. + * When doing a passdb lookup, e.g. a proxy which doesn't really want the + password, just the passdb extra fields: + * Neither 'CREDENTIALS_LOOKUP' nor 'SCHEME' is set. + * FIXME: Unfortunately it looks like you currently can't easily + differentiate a passdb lookup from userdb lookup! + * If user doesn't exist, use exit code 3. + * If you get an error about checkpassword exiting with code 0, you didn't + execute the 'checkpassword-reply' binary as you should have (which exits + with code 2 on success) + +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 +} +---%<------------------------------------------------------------------------- + +Performance +----------- + +The <CheckPassword.txt> backend is not suited for heavy traffic. Especially if +the script spawned has to launch an entire language interpreter. + +If your user database is only accessible with custom code an alternative might +be using the <Dict AuthDatabase over a UNIX socket> [AuthDatabase.Dict.txt]. + +Specific checkpassword implementations +-------------------------------------- + + * phpBB dovecot checkpassword authentication, written in python: + https://github.com/ser/checkpassword-phpbb + +(This file was created from the wiki on 2019-06-19 12:42) |