Why this patch
I wanted authenticated SMTP submission without patching
ofmipd(8)
or
qmail-smtpd(8).
Reasons:
- I haven’t been able to run the latest TLS patch because it conflicts with the popular SMTP AUTH patches, the last time someone published a merged patch was 2007, and one of my goals in life is to spend as little time as possible hand-merging patches, especially if they’re security-sensitive.
- I haven’t been able to run the 2007 TLS merged patch because that version doesn’t interoperate with Gmail (and probably other sites).
- Now that I think about it, the popular SMTP AUTH patches never felt truly qmail-ish.
- Thinking about it some more, yikes: SMTP AUTH can be abused to
dictionary-attack the
rootpassword — and if I were running POP3, guessing right would runqmail-pop3dasroot! - With a more qmail-ish design, I could improve security and get new user-controlled features.
How and why acceptutils is different:
Without this patch
POP3 runs as the authenticated user, even if that happens to be root.
SMTP AUTH runs with hardcoded privileges, needs checkpassword marked
setuid-root in order to invoke it strangely, and is implemented by a
patch to ofmipd or qmail-smtpd.
With this patch
POP3 runs as the authenticated user, who will never be root. SMTP AUTH
works the same way, invokes checkpassword as intended, and does not
require any changes to ofmipd or qmail-smtpd.
If someone manages to guess the root password, they won’t know they did: it looks exactly like any other failed login.
Both services run green thanks to these new programs:
reupruns a program repeatedly until it succeeds.authupoffers SMTP or POP3 authentication and callscheckpassword.checknotrootrefuses to run as UID 0.fixsmtpiofilters SMTP I/O and exit status to suitauthup.
Install
- Extract a fresh copy of netqmail into “qmail-acceptutils”.
- Apply this patch (not yet released) there.
- Copy over
conf-*from your main qmail source tree.
Then simply:
# make acceptutils
# cp reup authup checknotroot fixsmtpio /var/qmail/bin
# cp reup.8 authup.8 checknotroot.8 fixsmtpio.8 /var/qmail/man/man8
(You can also try to merge this patch into your main qmail source tree. But since it only adds new programs, why bother?)
Example: authenticated submission service
To accept messages via SMTP AUTH on localhost:26:
#!/bin/sh
exec tcpserver 127.0.0.1 26 \
reup -t 5 \
authup smtp \
checkpassword \
checknotroot \
fixsmtpio \
env RELAYCLIENT="" ofmipd
and put these rules in control/fixsmtpio.
# if client closes the connection, tell authup to be happy
AUTHUP_USER:clienteof::*:0
# if server greets us unhappily, notify authup
AUTHUP_USER:greeting::4*:14
AUTHUP_USER:greeting::5*:15
# if server times out, hide message (authup has its own)
AUTHUP_USER:timeout::*:16:
# always (authenticated or not) replace greeting
:greeting::2*::&fixsmtpio
# always replace greeting in HELO/EHLO
:helo::2*::&fixsmtpio
:ehlo::2*::&fixsmtpio
# always prepend acceptutils link to HELP message
:help::*::&fixsmtpio
# always replace greeting in QUIT
:quit::2*::&fixsmtpio
# don't advertise AUTH or STARTTLS
AUTHUP_USER:ehlo::250?AUTH*::
AUTHUP_USER:ehlo::250?STARTTLS::
# don't allow AUTH or STARTTLS
AUTHUP_USER:auth:NOOP :*::502 unimplemented (#5.5.1)
AUTHUP_USER:starttls:NOOP :*::502 unimplemented (#5.5.1)
Note that stunnel (or similar) is needed to encrypt the service and
make it available over the network.
Note that authenticated submission must be on a separate port (or host) from incoming SMTP. If you’re currently using port 25 for both, consider moving submission to port 587, or wait for a future version of acceptutils.
Example: retire previous SMTP AUTH patch
When you’re satisfied with acceptutils, at leisure, remove your previous
SMTP AUTH patch and chmod -s checkpassword. Once you’re running an
unpatched ofmipd, remove env RELAYCLIENT="".
(Exception: if you’re relying on AUTH support in qmail-remote, don’t
remove your previous patch.)
New user-controlled features
Sender address rewriting
Since authenticated submission runs as you, messages you send can be modified according to your settings.
For example, since checkpassword sets $HOME, you can give ofmipd
your own CDB of rules for rewriting envelope senders and From:
headers.
Here’s an ofmipd-with-user-cdb wrapper to do this:
#!/bin/sh
ofmipd_arg=""
user_cdb="$HOME/.ofmipd/rules.cdb"
[ -f "${user_cdb}" ] && ofmipd_arg="${user_cdb}"
exec ofmipd "${ofmipd_arg}"
Stateful filtering
Since authenticated submission and incoming delivery both run as you, messages you send can influence what happens to messages you receive.
For example, filtering your submitted messages through pymsgauth-filter
inserts a token into the headers and records it in $HOME, where
pymsgauth-confirm can find and match the token in incoming messages.
Here’s how to post to DJB’s mailing lists from any AUTH-capable mail client without ever seeing a qsecretary challenge again:
- Apply the QMAILQUEUE patch (available here for
ofmipd, included with netqmail forqmail-smtpd). - Install qmail-qfilter.
- Install rejectutils.
- Install pymsgauth with the pymsgauth-filter patch.
- Configure
$HOME/.pymsgauth/pymsgauthrcand the relevant.qmailfile. - Add
pymsgauth-filtertocontrol/ofmipfilters. - Set
QMAILQUEUE="qmail-qfilter-ofmipd-queue"andPYMSGAUTH_TOLERATE_UNCONFIGURED=1in your service’s environment.
Security
Please consider carefully the risks and mitigations and decide for yourself whether acceptutils might safely improve your SMTP AUTH submission service.
Possible future directions
Here are some ideas for the future of acceptutils.
Get this patch
When it’s ready, I’ll announce it on the qmail list.
Improve this patch
If you see a simpler way to do it, I’d love to know.
