The DynDN.eS Blog

About DynDN.eS, eQmail, Gentoo & some other network stuff

User Tools

Site Tools


eQmail: qmail-chkpw

qmail-chkpw is a tool compliant to DJB's checkpassword interface. It is especially for SMTP authentication with eQmail or (net)qmail and can do AUTH PLAIN, AUTH LOGIN and CRAM-MD5 authentication. Based on  cmd5checkpw-0.30  it has the similar functionality. The new part is that passwords for non CRAM-MD5 authentication have to be stored encrypted. Passwords for use with CRAM-MD5 still have to be stored in clear text format - as of the nature of this mechanism.

qmail-chkpw uses $QMAILHOME/users/smtpauth to store pairs of usernames and passwords separated by a colon. Read INSTALL to see how this can be changed. Most common $QMAILHOME is “/var/qmail”.

 Update: Recent documentation and download of the latest release is available at openqmail.org!

Download from GitHub: qmail-chkpw        Browse releases on GitHub

qmail-chkpw will be discussed on the openqmail mailing list (closed!).

History

Initially I made a quick and dirty modification of cmd5checkpw-0.30 sometimes in 2009. Since I used it in different netqmail installations. After publishing eQmail-1.08 I decided to make a clean source package and publish it. Hopefully qmail-chkpw is useful for others. It is one of multiple modifications/extensions I did for eQmail/(net)qmail.

Preface

Additional to the man page I want to give some examples how to use it. All are done with the “bash” shell. The connections to the mail-server will be done telnet-like (e.g. “telnet localhost 25”). Replace localhost and port with your needs. For encrypted connections use the “s_client” command. After connection enter the EHLO command. I assume that you are familiar how to do it this way. Your server should offer some code “250” lines, at least one should show accepted authentication methods, like:

250 AUTH LOGIN PLAIN CRAM-MD5

I use this line in the examples below. Afterwards the authentication commands are entered. The communication is usually base64 encoded.

The password file

Let's start with AUTH PLAIN/LOGIN. I use as username foo and as password testpass. Encrypt the password:

$ qmail-chkpw -e
$    New password:  <put "testpass" here and hit enter>
$ Repeat password:  <repeat "testpass" and hit enter>
$ $6$QkB7Kb3G$pyYT/beGjy1u9BFGX70Py3qZnVfuGWB5zE9C4FKrus9atP.jZzj9meyA1xh1jsBJnES0P/TcapPKu/16/8CxS.

Put the username and the encrypted password into $QMAILHOME/users/smtpauth:

foo:$6$VnC7KG1H$o0au7H4Q49AxlHi9fmKH94kDMWMve7UhiL1tO5x.39Wtr7XGjfwlSU6ZQvnywGWL9NTMRdLo3Run0tHzSO3Pl/

As users have to be unique we use bar for CRAM-MD5 (later on) and put the password in plain text into the file, so we have 2 lines in smtpauth now:

foo:$6$VnC7KG1H$o0au7H4Q49AxlHi9fmKH94kDMWMve7UhiL1tO5x.39Wtr7XGjfwlSU6ZQvnywGWL9NTMRdLo3Run0tHzSO3Pl/
bar:testpass

AUTH PLAIN

To use AUTH PLAIN we need username and password base64 encoded as one string:

$ printf '\0foo\0testpass' | base64
$ AHVzZXIxAHRlc3RwYXNz

Connect to your server (e.g. “telnet localhost 25”) and do authentication:

...
250 AUTH LOGIN PLAIN CRAM-MD5
AUTH PLAIN AHVzZXIxAHRlc3RwYXNz
235 ok, foo, go ahead (#2.0.0)
...

AUTH LOGIN

To use AUTH LOGIN we need username and password als separate base64 encoded strings:

$ printf foo | base64
$ dXNlcjE=
$ printf testpass | base64
$ dGVzdHBhc3M=

Connect to your server like above and enter your credentials. The strings after the 334 code are base64 encoded: “VXNlcm5hbWU6” is “Username:” and “UGFzc3dvcmQ6” is “Password”:

...
250 AUTH LOGIN PLAIN CRAM-MD5
AUTH LOGIN
334 VXNlcm5hbWU6
dXNlcjE=
334 UGFzc3dvcmQ6
dGVzdHBhc3M=
235 ok, foo, go ahead (#2.0.0)
...

The strings “VXNlcm5hbWU6” and “UGFzc3dvcmQ6” are nothing else than “Username:” and “Password:” base64 encoded.

AUTH CRAM-MD5

Testing CRAM-MD5 authentication is a bit more complex. Beware that we have to use bar. First we connect to the mail server via telnet:

$ telnet localhost 25
...
250 AUTH LOGIN PLAIN CRAM-MD5
AUTH CRAM-MD5
334 PDI2NDQyLjE0MzI2MjY5MDRAd3JhY2suYWxkb3guZGU+

The string after 334 is the challenge of the server. By opening another shell this string have to be base64 decoded:

$ printf PDI2NDQyLjE0MzI2MjY5MDRAd3JhY2suYWxkb3guZGU+ | base64 -d
$ <26442.1432626904@localhost>

Based on the decoded challenge we need to create a client response with the password testpass:

$ printf '<26442.1432626904@localhost>' | openssl md5 -hmac testpass
$ d8896141e89cb008a1f339e1ad1683ea

The given hash have to be base64 encoded together with the username (username and password are separated by space):

printf 'bar d8896141e89cb008a1f339e1ad1683ea' | base64
a3AgZDg4OTYxNDFlODljYjAwOGExZjMzOWUxYWQxNjgzZWE=

Now we switch back to our telnet session and put in the response:

...
250 AUTH LOGIN PLAIN CRAM-MD5
AUTH CRAM-MD5
334 PDI2NDQyLjE0MzI2MjY5MDRAd3JhY2suYWxkb3guZGU+
a3AgZDg4OTYxNDFlODljYjAwOGExZjMzOWUxYWQxNjgzZWE=
235 ok, bar, go ahead (#2.0.0)
...

Troubleshooting hints

  • the owner of qmail-chkpw have to be  qmaild  or it have to be made sticky:  chmod +s $QMAILHOME/bin/qmail-chkpw 
  • the password file should have ownership  qmaild:qmail  and should be read-only by  qmaild 
  • the file smtpauth MUST NOT have empty lines

The RSA Header files bugfix

As qmail-chkpw is based on cmd5checkpw-0.30 it uses the RSA MD5 implementation. Unfortunately the definition of 32bit integers on 64bit systems is wrong in the original RSA header files. This is fixed since the first public release qmail-chkpw-0.1 by using the C standard include files.