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.