I’ve finally figured out how to do this. The Dovecot documentation is absolutely horrible which is sad because it should be encouraged to always salt your password hashes yet they make it very difficult to figure out.
Dovecot is a IMAP and POP3 plugin for Postfix. Postfix doesn’t do authentication on its own so it’s often found that SASL authentication gets passed to Dovecot for both IMAP mail checking and creating dynamic relay lists.
Goal
We want to get Dovecot authentication to use salted SHA password hashes. The password hashes are stored in a mysql database and were created using ruby, python, or php.
You should never be saving user passwords. It’s better to only store the hash of a user’s passwords. But don’t stop there, add some complexity to the hash. By salting the password hash it significantly complicates the cracking process. It’s also best practices to have a unique salt for every password hash.
Format of the hash
The Dovecot documentation says the password hash must be in the following format when presented to Dovecot for comparing. (It can be in base64 or hex.)
{SSHA256.hex}4a847fefc4f9ab450f16783c5025d64313942a1ceb2599707cdb65940ba901e513fa442f
This is a string with the following in it:
{SSHA256}
This is the beginning of the string which tells Dovecot what kind of hash this is. In this case ‘SSH256’ means Salted SHA 256 bit.4a847fefc4f9ab450f16783c5025d64313942a1ceb2599707cdb65940ba901e5
is the salted hash. Dovecot knows only that portion is the salted hash because a SHA256 hash will be 32 bytes long.13fa442f
is the salt. Dovecot knows this is the salt because it assumes everything after the hash will be the salt because we indicated “SSHA” which is a salted SHA hash.
You can actually verify this against Dovecot with the following command line:
|
The command above asks the Dovecot authentication compare program to check the hash given against the password “pass”. The result is verified which means this password matches the hash.
Create the hash
The are many ways to create the hash. You can use php, python, ruby, bash, or even mysql itself to hash the password. In the cases below we are creating a base64 hash.
Ruby
Using ruby or ruby on rails we can create the hash this way:
|
You can test this code using the rails console.
Python
Using python or any of the python web frameworks like django we can create the hash this way:
|
You can test this code from the python console. Thanks to this gist for helping me out with this.
PHP
This stackoverflow question goes over how to create the hash in PHP. I have not tested this one though.
Test the hash using Dovecot
Suppose the following:
Our salt is: 2fec1ee0940e7c436ef2037e89e4c06ca20b281a90dbb2d6cbd3534aa4ce7e19
Our password is: test
This would result in the following salted hash:
|
And when concatenating the salt to the end and converting to base64 we’d get this:
|
We can test this string using the doveadm pw
command from the linux command line (provided Dovecot is installed):
|
The -t
indicates we are going to give the hash and the -p
indicates which password to use for hashing. The hash we give indicates this is a Salted SHA512 and is long enough to indicate the salted hash with the salt appended to the end of the string. So doveadm will take the first 64 bytes of the hash off and the rest of the bytes are the salt. It will then hash the word “test” with SHA512 using the salt provided and then test that against the hash provided. The result is verified which means the hashes match.
Configure Dovecot
Suppose the username and hashed password is stored in the mysql table “users”. Let’s now configure Dovecot to get that information for it’s authentication.
First make sure Dovecot is handling the authentication by configuring Postfix. Add the lines to /etc/postfix/main.conf
:
|
Edit the /etc/dovecot/conf.d/10-auth.conf
file and make sure the following are in it:
|
Edit the /etc/dovecot/conf.d/auth-sql.conf.ext
file and put the following in it:
|
Edit the /etc/dovecot/dovecot-sql.conf.ext
file and put the following in it:
|
You’ll have to adjust the connect
and password_query
parameters to be what your database requires for the properly mysql authentication and lookups. Take note here that Dovecot expects this command to return a user
and password
column in the result. So if your mysql columns don’t say that, use the as
mysql command to fix that. Also note that we are adding {SSHA512}
to the front of the password
because this is what Dovecot wants.
Once that is done restart Dovecot by doing sudo services dovecot restart
.
Verify/Troubleshoot
At this point you should be able to authenticate to Dovecot with your password which is stored using a salted hash algorithm.
If this isn’t working for you then check /var/log/mail.log
to see if there are any errors. Turn on additional debugging by editing the file /etc/dovecot/conf.d/10-logging.conf
and add/uncomment this line:
auth_debug_passwords = yes
Now when you check mail.log you may see the following:
|
This will show you the hash that’s being checked and the hashing type Dovecot is trying. You can test this manually by using the doveadm pw
command covered above in the Test section of this page.
My biggest problem was creating a salted hash the correct way. Verify that the hash you’re creating works against doveadm pw
before adding the Dovecot configuration.
Comments