This page documents the extra features introduced into qmail with the use of each version of my combined patch. I've written a quick little Javascript menu to allow you to choose the version of the patch whose list of features you wish to see, without my having to maintain a separate web page for each version.
Released | |
File | |
Size | |
MD5 | |
SHA-1 | |
RIPEMD-160 | |
PGP Signature |
Click here for a list of downloadable files.
If you are reading this page because you are looking at, or using, the "qmailrocks" package, you shold be aware that qmailrocks has not been updated in several years. The current "stable" version, 2.2.1, was released (according to the qmailrocks web site) on 2006-04-19, which is over three years ago as I write this. Even the "development" version, 3.0, was only released a week later- and neither version has been touched since then.
Unfortunately, the qmailrocks distribution consists of a single tarball, which contains all of the other packages- qmail itself, a copy of this ancient version of my patch, as well as ancient versions of vpopmail, courier-imap, and so forth. And even though qmailrocks has stopped updating, none of the other packages have- and that includes this combined patch.
Which means that, unless you take the time to hunt down the current versions of the individual packages, read through their documentation well enough to understand what has changed since whatever version qmailrocks is using, and update the qmailrocks scripts to work with the current versions of the underlying packages, you will be setting up a server based on ancient software, configured in an insecure manner, and the first time soemthing goes wrong with that server, you will suddenly discover that qmailrocks' total lack of documentation has not prepared you to deal with the issues which WILL arise.
And if you're smart enough to do that, you may as well not use qmailrocks to begin with.
Do yourself a favour. Take the time to learn how qmail actually works, and then build a server which you understand how to operate. See Life with qmail (LWQ) for a much better set of directions. Most people start learning qmail by following along with the LWQ directions, then going back and adding any other patches they may need for their own servers (the "netqmail" patch that LWQ uses is a very minimal patch.)
If you're curious, the current version of my patch includes every patch which is part of netqmail-1.05. I haven't looked at netqmail-1.06 yet.
Because I'm tired of having people like this guy (scroll to the bottom of that page) blaming ME for qmailrocks' problems. (Of course, the fact that he added this note to his web page, telling people to not use my patch, without so much as talking to me about it first, is a separate issue...)
I will take this notice down when one of these things happens:
Unfortunately, I suspect that means this notice will always be here.
Version 7.10 of the combined patch includes the following individual patches.
Changes in Version 5, released 2004-06-23, and included as part of "qmailrocks".
The qmail-1.03-maxrcpt.patch patch allows you to set a limit on how many recipients are specified for any one email message. RFC 2821 section 4.5.3.1 says that an MTA MUST allow at least 100 recipients for each message, but MAY elect not to allow any more than that. I choose not to, since this is one of the favourite tricks of the spammer.
To set the limit, create a /var/qmail/control/maxrcpt file which contains the maximum number of recipients you wish to allow. If you don't want any limit, you can either delete this file, or use 0 as the value.
With the "6c6" or later version of the combined patch, you can override this value with the MAXRCPT environment variable. Also, a minimum limit of 100 recipients is enforced within the code- if you try to set it to a lower number, it will use 100.
The qmail-1.03-mfcheck.3.patch patch causes qmail-smtpd to reject messages where the domain portion of the envelope sender is not a valid domain. If the domain doesn't exist, or if it exists but doesn't have any MX or A records, it rejects the "MAIL" command using a 553 error. If it has trouble looking up those records, it uses a 451 error instead. When combined with a mechanism to make certain domain names appear to not exist, it can make for an effective way to reduce the amount of spam received by rejecting messages which claim to be from certain domain names.
To use this check, create a /var/qmail/control/mfcheck file which contains "1" (or any non-zero number) to enable the check, or "0" to disable it (the default is disabled.) You can also create an environment variable MFCHECK which contains either "1" or "0", and this number will override the control file.
With the "6c2" or later version of the combined patch, the environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_MFCHECK variable whose value would override the control file and/or the original environment variable whenever a client authenticates.
With the "6c6" or later version of the combined patch, using a value of 2 or higher will cause all non-successful checks to be logged, and using a value of 3 or higher will cause successful checks to be logged as well.
The qmail-1.03-quotas-1.1.patch patch modifies qmail's local delivery logic to consider "over quota" to be a hard error rather than a soft error. Some ISP's have accounts which are only used for dialup access, and never check their mail. This patch prevents messages sent to these users from clogging up the queue for a week before being bounced.
The qmail-date-localtime.patch patch causes qmail to use the local timezone in any headers it generates.
The qmailqueue.patch patch allows qmail-smtpd to call a program other than qmail-inject when it receives a message. This "hook" allows you to do things like virus scanning and RBL checking before the message ever goes into the queue. If this other program returns a value other then zero, the SMTP server treats it as a hard or soft error (depending on the return value) and refuses to accept the message.
The qmail-1.03-jms1-antispam.2.patch patch is a patch which I wrote, to expand upon the capabilities of a modified qmail-scanner-queue.pl script. It adds two new error responses to qmail-smtpd- one causes it to drop a message with a response of "we do not accept SPAM", and the other causes it to drop the message but act like it was accepted. I've seen some mail servers continually try to deliver the same message over and over again, and they won't stop until it's been delivered. This allows a qmail-queue replacement program to "fake out" these servers.
Note that this patch changes how qmail-smtpd interprets the return value "1" from a qmail-queue replacement program. Instead of meaning "temporary failure", it means "ignored as spam". Filters which return 1 will cause a "temporary failure" response in an un-patched qmail-smtpd, which will result in the message delivery being tried over and over until the remote machine gives up on it.
I've also been told that this behaviour (lying to an SMTP client) is somehow a violation of RFC 821. It's certainly not something that the RFC planned for, but I don't see it as a violation. If I know that I don't want to receive a certain email message, and that I will never want to receive a certain email message, then telling the remote server that I've handled the message is exactly correct, because the message has indeed been correctly handled, in accordance with MY wishes. The fact that my wishes aren't the same as the wishes of the sender of the message is meaningless to me. Spam is spam and I don't want any.
If anybody out there doesn't agree with me, that I should be the one who ultimately decides which messages I do and don't receive on MY machine, then don't run this patch.
2007-09-03 After all this time (I wrote this patch on 2002-05-20) I found a potential bug, which would have caused exit value 115 to be mis-interpreted. The ".2.patch" file above is the "fixed" version, and combined patch version 7 has the "fixed" version in it.
The errno.patch patch changes error.h to work correctly with glibc-2.3, which is used by RedHat 9 and a few other Linux distributions.
The qmail-smtpd-auth patch teaches qmail-smtpd to handle the AUTH command, which allows authorized remote users to use your mail server as a relay. The original patch came from here, but I changed it so that qmail-smtpd would only advertise the AUTH capability if it actually supports it (i.e. only if a checkpassword program is correctly listed on the command line.) This way the same patched qmail-smtpd binary can be used for SSL-enabled servers which support AUTH and for normal non-SSL servers which do not (which is how I run my own servers, AUTH is only available for SSL connections.)
Note that this was the first patch I couldn't make apply cleanly with the others without manual changes to the code. This was the patch that started me on the idea of making a single combined patch file- not so much for distributing to others through my web site, but for carrying around with me for when I build client machines- first on a CD-ROM, and later on a USB memory stick. Of course the USB memory stick now contains a lot more than just a patch file- it has a full set of scripts that I use to take a machine from a fresh install of Centos 4 to a fully functioning server.
NOTE: There have been issues where people who started out using the original AUTH patch were inadvertently making their machines into open relays because the code in the patch doesn't adequately check to make sure that a "checkpassword" program is properly specified on the command line. I have sent my changes to the author of the AUTH patch, but it's been several years now and he hasn't released any new versions yet.
The original AUTH patch had a "feature" where a program running as a QMAILQUEUE replacement could check the TCPREMOTEINFO variable to find the userid which authenticated. However, this variable already contains the identd information from the sender, and some programs may want/need that information as part of their processing. I have modified the code so that the authenticated userid will be stored in a variable called SMTP_AUTH_USER.
When I first did this, my intent was to take out the change to TCPREMOTEINFO so that it would contain the original information stored there by tcpserver, and any QMAILQUEUE programs would use SMTP_AUTH_USER instead. However, I left it in there because the "qmail-queue" program, which handles adding a message to the queue, uses the value of TCPREMOTEINFO when building the "Received:" header that it adds to the message.
I came across this patch which combines STARTTLS support with the SMTP-AUTH patch above. Since Mozilla's email program doesn't correctly handle SSL-encapsulated SMTP, I tried this patch and it makes Mozilla work.
However, it turns out they wrote the combined patch using a version of the SMTP-AUTH patch without my bug fixes, so I had to add them into this version.
I also added another check to the program- it will not advertise the AUTH capability unless the checkpasswd program is specified correctly on the command line (i.e. at least three items after the program name) and EITHER the STARTTLS command has been issued and an SSL session is active, OR the environment variable SSL exists and has a numeric value greater than zero. This prevents users from sending their passwords over the wire in plain text when they forget to turn on the TLS or SSL checkbox in their mail program.
Let me repeat this last bit, because a lot of people seem to not understand it: with my patch set, if a given connection is not secured by SSL or STARTTLS, the AUTH command will not be advertised in the EHLO response, and it will not be accepted if the client sends it anyway. This is for security reasons- allowing people to send AUTH commands over a non-encrypted connection is allowing them to give out their passwords over the Internet- and all a spammer needs is one valid userid and password in order to use your server as a spam relay.
For some reason, qmailrocks-2.2.0 applies another patch on
top of mine which disables this security check, in the guise of trying to
do something else (the so-called "forcetls" patch, which has no effect on
TLS at all.) If you are using qmailrocks-2.2.0, you should be aware that
there is no way for you to protect your users by preventing them from
sending their passwords across the internet in what amounts to plain
text.
Later versions of the combined patch include a way to disable this
security measure, but I do not recommend that anybody use it (and if you
got my patch as part of the qmailrocks-2.2.0 package, be aware that the
qmailrocks script applies another patch after mine which removes this
security check entirely.).
At the same time that I found the STARTTLS patch above, I also found a patch which adds SPF checking to qmail-smtpd. SPF is a system where the owners of domain names can "publish" the list of IP addresses from which their users send mail. If another mail server sees an incoming message claiming to be "From" that domain, but not coming from an IP on their SPF list, that server can reliably reject the message as a forgery.
It is configured using the /var/qmail/control/spfbehavior file, as well as a SPFBEHAVIOR environment variable. The environment variable, if present, will override the file. The value contained in the file or variable should be a number, as follows:
Values higher than 3 are strongly discouraged- most people will probably want to use either 1 or 2 at first. I've been using 3 on my own server for over a year, and I've been very happy with the results.
With the "6c2" or later version of the combined patch, the SPFBEHAVIOR environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_SPFBEHAVIOR variable whose value would override the control file and/or the original environment variable whenever a client authenticates.
You can also use the control files spfrules, spfguess, and spfexp as detailed on the original SPF patch home page.
The version of the SPF patch which has been included here is rather old (it's version "rc2" on the patch's home page), and it has some bugs. Version 6c9 of the combined patch updates this to the latest "rc5" version of the SPF patch.
Changes in Version 5f, released 2005-04-11
qmail-0.0.0.0.patch fixes a difference between how Linux interprets the IP address "0.0.0.0" and how the *BSD systems handle it. According to RFC 1122, the IP address 0.0.0.0 should always be treated as an address for "this host, this network". Part of qmail's loop-detection logic is determining whether or not a given IP address "is" the current machine. This patch "teaches" qmail that 0.0.0.0 is always the local machine.
qmail-1.03.qmail_local.patch fixes a possible bug in qmail-local having to do with how the first line of a .qmail file is interpreted, when it starts with whitespace. This post from the qmail mailing list describes the problem.
sendmail-flagf.patch fixes how the "-f" option to /var/qmail/bin/sendmail is handled, so that it more closely matches how the original "sendmail" program's "-f" option worked.
qmail-1.03-bind-interface.patch lets you control the "source IP" from which outgoing connections appear from a machine with multiple IP addresses. This file on qmail.org (local copy) describes the patch more clearly, as well as the format of the /var/qmail/control/bindroutes file which it uses.
I have since updated this patch- see the newbind.patch information below, under version 7.05.
qmail-1.03-8k-buffer.patch increases the size of the memory buffer that qmail uses when querying the system for a list of all local IP addresses. This mailing list message describes the problem and includes the patch file (which I saved as a stand-alone .patch file for this web site.)
After a discussion with Eric from qmailrocks.org, I have decided to add an extra hook to allow people who may want to allow AUTH without requiring there to be a secure (SSL or TLS) connection first. THIS IS A VERY BAD IDEA in general, but I can't address the security needs of every server in the world. Some people may have servers which only exist inside of a closed network and have no contact with the outside world, some poeple may have clueless supervisors who order them to turn on AUTH without requiring the users to use encryption, and some people may live in a country where encryption is illegal... whatever your reason, if you use this feature and a spammer sniffs one of your users' passwords and starts using your server as a spam relay, it's your own fault.
If you really want to do this, and you understand and accept the dangers involved, you can set an environment variable called ALLOW_INSECURE_AUTH to a number greater than zero. This would normally be done in the "run" script which starts up the qmail-smtpd service.
I have added another manual patch which modifies how the TLS patch works. When qmail-smtpd starts, it looks for a file called /var/qmail/control/servercert.pem. If it does not exist, it will not include STARTTLS in the list of capabilities advertised in response to the EHLO command, and if the client tries to send the AUTH command anyway, it will be refused.
This way, if you don't want to support TLS, you simply don't create the .pem file it needs.
Also with this patch, if you need to build qmail without needing the openssl libraries for some reason (i.e. you don't have them and cannot legally get them in the country where you live) you can remove -DTLS from the conf-cc file after applying the patch. When you run make after this change, the resulting qmail-smtpd will not have any references to the openssl libraries at all (and of course will not be able to handle the STARTTLS command.)
If your machine has several SMTP services, some of which need to support TLS and some of which should not, you can create a envrionment variable DENY_TLS for those services which should NOT support the STARTTLS command. When qmail-smtpd sees this, it will not advertise or accept the STARTTLS command. This can also be used in your tcpserver access control file if there are certain IP addresses for which you do not wish to support TLS.
Note that this value is automatically set to 1 if qmail-smtpd cannot find or read /var/qmail/control/servercert.pem. If you are trying to use FORCE_TLS and get the error message 421 FORCE_TLS and DENY_TLS both found (#4.3.0) when the client connects, you may need to make sure your servercert.pem file exists and is readable. I will admit this isn't the most descriptive error message in the world, and it will be clarified in a future patch. Thanks to Allyn Baskerville on the qmailrocks list for pointing this out.
Changes in Version 6, released 2005-05-04
The validrcptto.cdb patch, based on the original validrcptto patch, which checks each RCPT TO argument against a list of known valid email addresses, and refuses to accept mail for any address which isn't on the list. My modification is that it uses a cdb file instead of a flat text file, which is a MAJOR performance boost for sites with more than a few hundred mailboxes on the server.
And yes, it works correctly without breaking AUTH.
I wrote it so that if the validrcptto.cdb file does not exist, the extra RCPT TO checks are bypassed. This allows you to have the patch on your server before you're actually ready to use it, or even if you don't plan to use it at all.
I have also added a counter to this mechanism... if a given session tries more than a certain number of invalid RCPT TO addresses in a single session, that session will be dropped and the incident logged. I plan on using this on my own server to automatically add these IP addresses to a blacklist.
The limit defaults to ten, and can be changed or disabled by creating an environment variable called VALIDRCPTTO_LIMIT with a numeric value. Setting it to zero will disable the checks, allowing unlimited attempts (otherwise known as "harvesting", a trick used by spammers to build a list of which email addresses do and don't work within your domain).
With the "6c2" or later version of the combined patch, the environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_VALIDRCPTTO_LIMIT variable whose value would override the original environment variable whenever a client authenticates.
This web page describes the stand-alone version of this patch, suitable for adding to djb's original source. It also provides more documentation, including directions for a script called mkvalidrcptto which can be used to build the validrcptto.cdb file.
2005-10-20 I received an email from Patrick (aka "marlowe") which asked for clarification about when the validrcptto.cdb check is done versus when the normal rcpthosts check is done. For people who care about such things, the normal rcpthosts check is done first- if an email arrives where the recipient's domain name is not listed in the rcpthosts or morercpthosts.cdb file, the RCPT TO command will be refused before the validrcptto.cdb file is ever checked.
A self-written patch to add a real FORCE_TLS capability, for those who want a non-SSL server but don't want it to be able to accept mail without STARTTLS happening first. Creating an envrionment variable called FORCE_TLS with a numeric value greater than zero enables this behaviour.
A self-written patch to add a REQUIRE_AUTH capability, if somebody wants to set up a server which will not accept incoming mail unless the user has successfully authenticated. Creating an envrionment variable called REQUIRE_AUTH with a numeric value greater than zero enables this behaviour.
The standard warning about using or allowing AUTH to happen without some kind of encryption applies here... you should not make the AUTH command available on any conenction which is not encrypted, either through TLS or by running an SSL-enabled server on another port.
Note that I haven't provided specific error messages to the client for every possible combination of this with FORCE_TLS, DENY_TLS, and ALLOW_INSECURE_AUTH... basically if the connection is not AUTH'd and the client tries to do a MAIL FROM command, it will tell them "503 AUTH first", even if AUTH is not allowed because the connection is not secured by SSL or TLS. Most of the people who would try are going to be spammers anyway, so I don't really think it makes a whole lot of difference.
Do not use REQUIRE_AUTH for an SMTP service which also needs to accept normal incoming mail. Doing this will prevent any other service from being able to deliver their normal mail to your server.
Changes in Version 6a, released 2005-05-12
The validrcptto.cdb functionality now works with "-default" addresses. This was causing problems with TMDA, a challenge-response mechanism that I use on my server (which some people may not like, but I will state this- it is probably the single most effective spam-blocking tool I have ever used.) The problem was that TMDA would send a challenge, and whenever anybody answered a challenge, their answer was rejected by the validrcptto mechanism. Thanks to "marlowe" on the qmailrocks mailing list for telling me this was happening.
Part of writing the "-default" search stuff was adding debugging code to make sure I was using djb's string functions correctly. They're a bit tricky, but once you figure out what they do, they're actually pretty cool. I ended up leaving some of the debugging stuff in there, figuring some people might want to see it when they run their servers. Setting the environment variable VALIDRCPTTO_LOG=1 will cause these messages to be added to the smtp log. Enjoy.
With the "6c2" or later version of the combined patch, the environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_VALIDRCPTTO_LOG variable whose value would override the original environment variable whenever a client authenticates.
With the "6c8" or later version of the combined patch, the value VALIDRCPTTO_LOG=2 shows even more debugging information. Using 1 shows what it's looking for and what it found, while 2 also shows which specific values it's searching from the cdb file.
Somebody on the qmailrocks mailing list had a question about a patch to NOT include the entire original message when generating a bounce. I looked at it, and the patch is very nice- it only touches one file, it only makes the absolute minimum changes it needs in order to do its job, and it doesn't cut existing lines (which would prevent future patches from applying cleanly.)
However, I don't like the fact that it's always enabled, and has a 50,000 byte limit by default. I tend to feel that unless the administrator does something extra (defines an environment variable, creates a control file, etc.) the qmail system should behave as closely as possible to djb's original design.
Since I was playing with the code again anyway, I went ahead and added
this patch to the mix. However, I made the following change: if the
control/bouncemaxbytes
file does not exist, or if it
contains zero, there will be no limit on the size of a bounced message. This
matches the original behavior of qmail-send (the program within qmail which
actually builds the bounce messages, and which this patch affects). There is
also no default of 50,000 anymore- the default is zero, meaning no trimming
of bounce messages. If you want a limit, whether it's 50,000 or something
else, you will need to create the control file.
Changes in Version 6b, released 2005-05-23
My AUTH_SET patch. Before running the QMAILQUEUE program, the environment is scanned for the following:
If any variables like "AUTH_SET_{name}={value}" are found, it will be removed- and if the connection is AUTH'd, a new variable "{name}={value}" is added to the envronment (or any existing variable with that name will be changed to the new value.)
If any variables like "AUTH_UNSET_{name}={value}" are found, it will be removed- and if the connection is AUTH'd, any variable with the name "{name}" will also be removed (regardless of its value- the value from the AUTH_UNSET_{name} variable is never used.)
These changes are needed in order to allow for patches which require different environment variables to be set depending on whether or not the connection has been successfully AUTH'd.
Note that the environment changes happen when the first DATA command is sent by the client. This means that if you connect to a server, send one message, then AUTH, and then try to send a second message, the changes will not be seen by any QMAILQUEUE programs which handle the second message.
An example of a patch which needs this functionality, and in fact the initial reason for writing this patch, is the domainkeys patch. In order to verify a signature for an incoming message, it requires that a variable DKVERIFY exist, which contains a list of letters telling which domainkeys results should be considered hard or soft errors. However, in order to sign outgoing messages, it requires that DKVERIFY should NOT exist.
This patch allows me to create an AUTH_SET_DKSIGN environment variable, and when the user AUTH's, it adds a DKSIGN variable to the environment, which forces the qmail-dk program to sign the message instead of verifying it. Without this, the only way to make domainkeys work was to enable it for certain IP addresses in the /etc/tcp/smtp.cdb file, which was no good for clients who used AUTH in order to relay.
The domainkeys patch is not a full combined patch like the ones listed here. It is an "add-on" patch which is meant to be installed after installing one of the combined patches here. It is only available for the 6b and later versions, since it requires the dynamic environment variables change features which were added from 6a to 6b.
Changes in Version 6c, released 2005-10-27
Fixes the CRAM bug, where the challenge and response were being sent from qmail-smtpd to vchkpw in the wrong order. As part of fixing the problem I cleaned up the code in the auth_cram() function so that the variable names actually mean what they say (instead of "pass" holding the challenge, "chal" now holds the challenge and "pass" holds the response.)
Made CRAM a run-time option instead of a compile-time option. It is disabled by default, if qmail-smtpd sees an environment variable ALLOW_CRAM=1 it will enable it.
Added code to log the results of each SPF lookup. The logs are enabled if qmail-smtpd sees an SPF_LOG=1 environment variable. The format of the log lines is identical to the header which is added to each message.
With the "6c2" or later version of the combined patch, the environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_SPF_LOG variable whose value would override the original environment variable whenever a client authenticates.
There was a bug in the SPF_LOG patch- this version does not work correctly, and may cause qmail-smtpd to crash. The problem is fixed in version 6c5 of the patch. Thanks to Eduardo Rocha for pointing the problem out to me.
Jason King (from the qmailrocks list) told me about an issue with DNS queries and CNAME records and ancient versions of BIND... this page explains the issue. I had never seen it on my own servers because I always use djbdns. I have added two patches which together take care of the issue.
In searching for some kind of "badhelo" patch. I found a regex (regular expression) patch which includes the "badhelo" functionality I was looking for, plus it adds regex support to the "badmailfrom" mechanism, and adds a "badrcptto" mechanism as well (the original patch called this "badmailto", but I have renamed it so that it matches the actual SMTP command involved.
The idea behind "badhelo" is this- one of the common spammer tricks is to send your own server's name or IP address as the argument to their HELO or EHLO command. Since it doesn't normally make sense for your server to be talking to itself, anybody who claims to be the server itself can safely be assumed to be a spammer (and their connection can be dropped, obviously.) This check can be bypassed for certain IP addresses by defining the NOBADHELO variable, the same way you would set RELAYCLIENT.
Other changes introduced by this patch...
The "badmailfrom" file has changed from the normal qmail implementation. Instead of just holding a set of strings, it holds a set of regular expressions which are used to reject MAIL FROM commands which contain certain patterns.
The "badmailfromnorelay" file, if it exists, has the same effect as the "badmailfrom" file, but it is only checked for clients which don't have relay permission (i.e. RELAYCLIENT is not set and a successful AUTH command has not been done.) This allows you to set up different lists depending on whether the client is trusted or not- the "badmailfrom" file is always checked, while the "badmailfromnorelay" file is only cheked for non-trusted clients.
The "badrcptto" file, if it exists, contains regular expressions which, if found in a RCPT TO command, will cause the command to be rejected. You can use this to always refuse mail to all "sales@..." addresses, for example.
The "badrcpttonorelay" file, if it exsits, has the same effect as the "badrcptto" file, but it is only checked for clients which don't have relay permission (i.e. RELAYCLIENT is not set and a successful AUTH command has not been done.) This allows you to set up different lists depending on whether the client is trusted or not- the "badrcptto" file is always checked, while the "badrcpttonorelay" file is only cheked for non-trusted clients.
Tom Clegg's qmail-remote-auth.patch allows qmail-remote to use AUTH when connecting to certain remote mail servers. The userids and passwords are set in the "smtproutes" file, after the IP[:PORT] value, separated by spaces. For example...
domain1.xyz:1.2.3.4
domain2.xyz:2.3.4.5 user pass
domain3.xyz:3.4.5.6:26 user pass
In the process of tracking down what I thought was a bug, I ended up adding support for the AUTH PLAIN method. With this patch, qmail-remote checks the list of AUTH methods advertised in the EHLO response, and can work with either AUTH PLAIN or AUTH LOGIN (with AUTH PLAIN being used if both are available.) This was made possible by the regex function from above, because using regular expressions makes it so much easier to scan the server's output for authentication methods.
There is a typo in the code which sends the AUTH PLAIN command to the remote server, which causes it to sometimes send garbage characters after the base64-encoded credentials. This problem is fixed in version 6ce. Note that this is a typo in my code, not in Tom Clegg's original patch.
I also found something else which may be a bug or may have been by design, but it doesn't seem right to me so I changed it. When it sends the "MAIL FROM:<...> AUTH=<...>" line (after successfully AUTH'ing to the remote server) it was repeating the sender address in the AUTH= argument, rather than putting the actual AUTH information in this argument. It now puts the userid from the AUTH information into the AUTH= argument. If this is somehow wrong, please explain to me why and I'll change it back.
2006-01-04: I did finally find a real bug, which is why the "6c" and "6c2" versions are no longer available. I made a typo while writing the code for AUTH PLAIN- after sending the AUTH PLAIN command it was looking for the wrong return code, and not recognizing "235" as "login successful." If you need this functionality, the 6c3 version contains the fix. Thanks to Carl Pulley for reporting the bug and helping me to nail it down.
I've also added a security check to prevent qmail-remote from sending authentication credentials across the internet in plain text. By default (with my version of this patch) qmail-remote will only send the AUTH command if the STARTTLS command has already been sent in the same session. If the connection between your server and the remote server is known to be secure (i.e. through an encrypted VPN, or within a closed network) or if you care so little for security that you don't mind sending your userid and password across the internet in what amounts to plain text, you can bypass this security check by adding a "-" to the beginning of the userid in your smtproutes file (the "-" will be removed if present.)
This patch fixes a problem with how qmail handles deliveries to domains which have multiple MX records. Normally qmail tries to connect to the various MX servers, but the first server it successfully connects to ends up being the only one it ever tries.
I've modified the patch so that both 4xx and 5xx messages result in the next MX record being tried.
Dr. Erwin Hoffman's qmail-smtpd.c. size.diff adds support for the SIZE extension as detailed in RFC 1870. The limit is set with the "databytes" control file, or the DATABYTES environment variable (if it exists.) A value of 0 means "no limit".
With the "6c2" or later version of the combined patch, the environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_DATABYTES variable whose value would override the control file and/or the original environment variable whenever a client authenticates.
André Oppermann's ext_todo patch breaks the "todo" portion of qmail-send (the part which examines each new message and decides whether it's a local or a remote delivery) into a separate program called "qmail-todo". This prevents the so-called "silly qmail syndrome", which is where qmail-send becomes so busy classifying new messages that it doesn't do any deliveries at all.
Thanks to "Bert-Jan" for suggesting the patch, and letting me know that it integrated fairly smoothly into everything else (only one hunk failed against the 6c-test2 patch, which surprised me- this is a fairly large patch and changes qmail-send at a very basic level.) Thanks also to Yousef Raffah for pointing out that the link was broken (it pointed to the front page of the web site which has the patch, but apparently the site doesn't have a page explaining the patch or even a link to download the patch itself.)
Changes in Version 6c2, released 2005-12-26
The following environment variables are re-read and their effects re-evaluated within qmail-smtpd after a successful AUTH command.
This means, for example, that if the initial environment contains the environment variables DATABYTES=5242800 and AUTH_SET_DATABYTES=0, that most clients will have a 5MB limit on their messages, but clients who send a successful AUTH command will have no limit.
Changes in Version 6c3, released 2006-01-03
This version corrects a bug in my patching of qmail-remote which was causing the response to AUTH PLAIN was being interpreted incorrectly.
The bug was in code that I added, which taught qmail-remote how to use the AUTH PLAIN command. The bug is not present in Tom Clegg's qmail-remote-auth.patch.
Thanks to Carl Pulley for pointing out the problem and helping me test the updated version.
Changes in Version 6c4, released 2006-01-17
Adds support for one of Russell Nelson's early relay rejection patches. It checks each recipient address for multiple @ characters, or for any % or ! characters before the @ character, and if it sees any such addresses it will refuse the RCPT command.
This check is only done if the RELAYREJ environment variable exists, and contains a non-zero value. This environment variable is re-checked when the user does a successful AUTH command, which means you can use an AUTH_SET_RELAYREJ=0 environment variable to disable this check for authenticated clients (if you use this check at all.)
The only reason you would want to even do this check is because some automated relay testers are broken. They try to use addresses containing these characters in an attempt to trigger old bugs in sendmail. qmail normally accepts such email addresses because, according to RFC 2821 section 4.1.2, these characters ARE VALID in the "local part" of an email address (the portion to the left of the @ character.)
In fact, there are a few "gateway" systems which accept incoming mail from SMTP and forward it to other systems (such as uucp) where the % and ! characters are NEEDED in order for mail to be routed correctly. This check will prevent these systems from working.
I do not recommend that anybody use this feature. However, I have added it to the combined patch because some people seem to get a warm fuzzy feeling from knowing that it's being done... and honestly, because I got tired of hearing people ask about it. It's here if you really really need it... but my advice is to not use it.
Updated the qmail-smtpd man page so that it includes the RELAYREJ environment variable, as well as the MFCHECK environment variable (which I had forgotten to list before) and the re-checking features introduced in the 6c2 patch.
Changes in Version 6c5, released 2006-03-08
Some people are improperly treating "SPF pass" as a strong
non-spam flag when evaluating the "spam level" of a message. Spammers
ARE taking advantage of this by placing +all
in the
SPF records of the domains that they purchase for the purposes of
sending spam. What this does is tells the receiving server that ANY IP
ADDRESS is allowed to send messages claiming to be "From:" that
domain.
Obviously this is not a good thing, for two reasons. First, spammers are bypassing the filtering that SPF should be offering. Second, people are placing a lot more trust in SPF than they should. An "SPF failure" result can be used to place a lower trust value on a particular message, but as long as spammers are able to purchase their own domain names and create their own SPF records, an "SPF pass" result should not be used to place any higher trust value on a message.
I have added an option to treat a +all
term found
within an SPF record as an immediate SPF failure. This can be enabled by
creating an SPF_BLOCK_PLUS_ALL
environment variable
with a value other than "0". Note that this variable is checked at the
time the SPF check itself is done, which means if you want to add, change,
or delete this variable using the AUTH_SET variables, you can.
Updated the qmail-smtpd man page so that it includes the SPF_BLOCK_PLUS_ALL environment variable.
Fixed a bug which was causing SPF_LOG to crash (note to self: it helps to actually DO the SPF check before trying to log the results.) Thanks to Eduardo Rocha for telling me about the problem.
In the rush to get the SPF_BLOCK_PLUS_ALL stuff released, I also seem to have released the AUTH_CDB code. I hadn't planned to release it yet, because I haven't had time to fully document it, or to make a stand-alone version of the patch which can be used without having to use my combined patch. Here are the basics:
The AUTH_CDB
enviornment variable needs to
contain the filename of a cdb file. The keys should be email addresses,
converted to lowercase. The values should be ENCRYPTED passwords. The
encryption can be any type which is supported by your system's
crypt()
function (i.e. anything which vpopmail supports-
which is generally the old unix crypt or the newer MD5 hashes.)
The service-qmail-smtpd-run
script already has the code to support this variable. It will only
include it if you have AUTH=1
. If you set both
AUTH_CDB
and CHECKPW
, AUTH_CDB
will take precedence and CHECKPW
will be ignored.
There is a script called mkauth
which scans your system's configuration and builds a list of email
addresses and passwords, similar to the mkvalidrcptto script. The output of
this script can be converted to a cdb file using the same
cdbmake-12
mechanism that mkvalidrcptto
uses.
However, since the encrypted passwords are sensitive information (they
could theoretically be "cracked" using a dictionary attack or a rainbow
table) these files should not be world-readable. Be careful with the
ownership and permissions of these files- if your scripting saves a copy
of the text output of mkauth
, the text file should only be
readable to root, and the .cdb file needs to be readable to the userid
as which qmail-smtpd
runs.
Changes in Version 6c6, released 2006-11-02
Added support for different SMTP greetings for different services.
This is done using the SMTPGREETING
environment
variable, whose contents will override the contents of the
control/smtpgreeting
file.
Added the remote IP address to the AUTH result log message. Also added the AUTH result log message when AUTH_CDB is not being used.
Added a way for the STARTTLS processing to use a certificate other
than control/servercert.pem
. This is done by creating a
TLS_SERVER_CERT
environment variable with the filename
of the PEM-enocded certificate. This would allow different SMTP services to
easily use different SSL certificates while feeding into the same queue.
Thanks to Bob Walter for the suggestion.
Updated the validrcptto.cdb
patch to allow for certain addresses to specifically be rejected, even
if the rest of the domain is being accepted with a more general entry (such
as @domain
.) Thanks to Robert Hanson for the suggestion.
Added the remote IP address to validrcptto.cdb-related log entries, changed the format of all existing validrcptto.cdb-related log entries to use a common format with the remote IP address.
Also updated the validrcptto.cdb patch so that it uses the "dash"
character compiled into qmail (using the conf-break
file when
compiling qmail) or specified in the /var/qmail/users/cdb
file
when searching for matches for "-default" aliases (as opposed to blindly
assuming that the "dash" character will always be "-", as it does
now.)
Added the MAXRCPT
environment variable to override the
maxrcpt
control file. Added code to enforce RFC 2821 section
4.5.3.1, which specifies that you must allow a minimum of 100
recipients on any given message. For "no limit" you should use
MAXRCPT=0
.
Also, while testing the patch, I found a bug in how the original patch was implemented, which would allow a knowledgable attacker to bypass the limit and specify as many recipients as they wanted. This patch fixes that issue.
Added logging for messages rejected due to MFCHECK doing its job. If the MFCHECK value is 1, the check will be done but not logged- as has been the case all along. If the MFCHECK value is 2 or higher, the results of each failed check will be logged. If the MFCHECK value is 3 or higher, successful checks will also be logged. The value can be overridden with a successful AUTH command using AUTH_SET_MFCHECK. Thanks to Carl de Kock for the suggestion.
For those who are about to ask, MFCHECK bypassed
means that the client sent a MAIL FROM:<>
command with
no envelope sender, therefore there is nothing to check. Usually this means
that the message is a bounce notification.
And before you ask about refusing these messages, you should be aware that THIS IS VALID according to RFC 2821 section 4.1.1.2. If you were to try and block these, you would be refusing to accept any legitimate bounce messages, which is NOT something you normally want to do (unless you are a spammer.)
Changes in Version 6c7, released 2006-11-04
Fixed a bug in the code which handled the SMTPGREETING variable. Thanks to Brad Jacobs for making me find the bug.
Changes in Version 6c8, released 2006-11-26
Fixed a bug in the validrcptto.cdb code, it now properly
uses the "break" value defined in the conf-break
file
instead of only using the "-" character. Thanks to "marlowe" for pointing
out the fact that it wasn't working, which made me track down the
bug.
Added VALIDRCPTTO_LOG=2
, which not only shows the
RCPT TO argument and what was found to match it, but also shows what
email addresses are being searched for in the file.
Changes in Version 6c9, released 2006-12-04
Fixed a bug in the AUTH patch where qmail-remote would send a STARTTLS command even if there was no clientcert.pem file available.
Updated the SPF patch
from version rc2 to version rc5. This fixes several bugs,
notably one where if a domain (like "paypal.com") has a large SPF
record, qmail-smtpd
would segfault (i.e. die with "status
11") on some platforms. Thanks to Mark DeGroot for allowing me to use
his server to track down the problem (because it wasn't happening on
my server.)
IF YOUR SERVER IS DOING SPF CHECKS ON THE INCOMING MAIL, DO NOT USE ANY VERSION OF THE COMBINED PATCH EARLIER THAN 6c9.
Changes in Version 6ca, released 2006-12-15
The code that I added to qmail-remote in the 6c9 patch does not compile correctly on some platforms. I've changed how I do the test (i.e. I'm actually opening the file rather than just calling access() on it) and now it seems to work on a much wider range of systems.
Found and fixed a bug which was causing AUTH log messages to be sent to the client instead of to the logs. It turned out to be a problem with the original AUTH+TLS patch. When I asked about this on djb's qmail list, Dr. Erwin Hoffmann referred me to his AUTH patches, where I learned that not only was the bug fixed long ago, but several other problems were fixed as well.
This patch incorporates all of his fixes, so the AUTH code in my combined patch is equivalent to his qmail-authentication-0.6.4 patch (which is current as of 2006-12-15, when I'm writing this.)
Changes in Version 6cb, released 2006-12-24
Added Dr. Erwin Hoffman's GREETDELAY patch, which adds an artificial
delay before qmail-smtpd
sends its initial banner. He found
that by adding a 30-second delay, half of the spammers who connected to
his server were giving up.
This is configured by creating an environment variable called
GREETDELAY
whose value is the number of seconds you want
to delay. If the variable does not exist, there is no extra delay.
I heard from a friend about another patch out there which caused
qmail-smtpd
to forcibly disconnect clients which tried to
send commands before qmail-smtpd sent its initial banner. I couldn't
find the patch he was talking about, but seeing Dr. Hoffman's GREETDELAY
patch reminded me about this, so I added this logic as well.
The idea is that many spammers try to send their commands to the SMTP servers as quickly as possible, and therefore don't wait for the server to send its initial banner, even though this violates RFC 821. Dropping clients who "jump the gun" like this will block some spammers who would otherwise get through.
To use this, create and export an environment variable called DROP_PRE_GREET with a non-zero value.
Note that this check involves adding a one-second delay before the initial greeting is sent. If you use this and GREETDELAY at the same time, the delay from GREETDELAY is used instead. It also means that if you set GREETDELAY="0" and DROP_PRE_GREET="1" at the same time, there WILL still be a one-second delay, so that the DROP_PRE_GREET code has some kind of delay against which to compare. If you have a specific IP for whom you are absolutely sure you want no delay and no dropping of the connection at all, make sure that BOTH of these variables are set to "0".
I have also added log messages whenever a client disconnects or sends data before the greeting is sent.
The person who gave me the idea is Phil Barnett, the
president of LEAP, the Linux user
group here in Orlando and a good friend. He had a client with a
sendmail-based server which was hemmorhaging SPAM, and ended up
installing a program on the server called MailScanner, which is a
framework for calling other scanning programs from within the MTA's SMTP
server process, very similar to how a qmail server would use qmail-scanner or simscan.
Phil also did a presentation at a LEAP meeting where he walked through
setting it up on a machine, then SSH'd into a live server where it was
running and showed what it ends up looking like. His notes from the
presentation are online if you want to see them. (The OpenOffice.org file is updated,
but the HTML version is not.
And of course there were questions about doing the same thing with
qmail, which made the meeting even more fun for me...
Changed Dr. Erwin Hoffman's base64.c
to work around what
appears to be a bug in some versions of gcc
. This was causing
the error message 501 malformed auth input
in response
to otherwise valid AUTH PLAIN
commands.
Changes in Version 6cc, released 2007-03-11
Added the client's IP address to log messages generated by the GREETDELAY and DROP_PRE_GREET mechanisms.
Fixed some typos in the README.qregex
and
qmail-control.9
files, which were inherited as part of the
"qregex" patch. Thanks to Zeeshan Muhammad for pointing them out.
Fixed the man page for qmail-smtpd
to include a few
items which have been added to the patch since 6c4 but not included in
the man page.
Fixed a problem with the original CRAM patch. Until now, there was no way to permit AUTH CRAM without also advertising AUTH LOGIN and AUTH PLAIN. I separated the AUTH logic so that the ALLOW_INSECURE_AUTH and ALLOW_CRAM variables are no longer dependent upon each other at all. Also made some internal code changes which should make the code easier to understand and maintain in the future. Thanks to Tyler Larson for pointing out the problem.
Fixed a problem where qmail-remote was not able to find the control/clientcert.pem file if it wasn't started from the /var/qmail directory (which is how qmail-send starts it.) Thanks to Ravinandan Naik for pointing out the problem.
I've since been asked to clarify what the problem was- apparently there are people on the qmailrocks forums who don't feel like joining the mailing list and finding out about these things as they happen.
Basically, when I wrote the patch in version 6c9 which made qmail-remote check the existence and permissions of the control/clientcert.pem file, I was half asleep and made a mistake. I accidentally put that check before the chdir("/var/qmail") call... so if qmail-remote was run by something other than qmail-rspawn and /var/qmail was not the current directory, it looked for a file called control/clientcert.pem within the current directory instead of within the /var/qmail directory.
This version puts the access() call after the chmod() call, where it belongs, so that when it tries to check for the existence and permissions of the control/clientcert.pem file, it will actually find it if it exists.
Changes in Version 6cd, released 2007-03-22
Changed the format of all log messages generated within qmail-smtpd to start with "qmail-smtpd[pid]". This allows the strack script to track these lines along with the tcpserver and rblsmtpd lines.
Changes in Version 6ce, released 2007-06-22
In qmail-remote, fixed and simplified the logic which treats "first charcter of an AUTH userid is '-'" as "okay to send AUTH without encryption".
In qmail-remote, fixed a typo which was making AUTH PLAIN send extra garbage after the base64-encoded credentials. Thanks to David Telfer for finding the bug and suggesting the fix.
Changes in Version 6cf, released 2007-07-13
The original regex patch that I added to the mix back in version 6c has been updated. The change is that if the LOGREGEX environment variable is defined, if qmail-smtpd rejects a command because it matched a regular expression found in the badhelo, badmailfrom, badmailfromnorelay, badrcptto, or badrcpttonorelay control files, the error message it adds to the log will now include the regular expression which was matched. It took some doing, but I managed to get these changes added to the combined patch.
2007-07-24 I received a bug report concerning this
change... apparently it's either comparing the patterns to the wrong lists,
using the wrong messages when logging a match, or both. I haven't had time
to dig into it yet, but I plan to find and fix it within the next day or
two.
2007-07-28 I have checked the code- it turns out that this was not
a real bug, it was a mis-understanding of how the code had been written.
Basically, if the client sends a HELO/EHLO command whose argument matches
a regex in the "badhelo" file, the client doesn't see any error message
until after sending a RCPT command. Strange, but it doesn't really open the
server up to any new security risks, and it does make it possible to log
the spammers' attempted forged senders and recipients.
Thanks to Bill Olson for making me look at this again.
Because of the logging change I made in version 6cd, the new version of the patch above wouldn't quite work because I needed a strerr_warn7() macro, while the macros provided in strerr.h only go as high as 6. I modified strerr_die.c and strerr.h to expand the range of strerr_warnxxx() and strerr_diexxx() macros from 6 arguments to 9. I figured since I was changing it anyway, I might as well leave room for future expansion, so I went all the way to 9 instead of just 7.
This patch is also available as a stand-alone qmail-1.03-strerr9.patch file.
Changes in Version 6cg, released 2007-08-01
Added the qmail-queue-custom-error.patch which is needed in order to use the enable-custom-smtp-reject option with simscan. Also wrote my own page with notes about simscan.
Updated the validrcptto.cdb patch so that instead of using the hard-coded value "control/validrcptto.cdb" as the filename, it uses the value of the VALIDRCPTTO_CDB environment variable as the filename instead. This makes it possible to set up SMTP services which use different .cdb files, or which do no validrcptto checking at all (which you would normally only do for a localhost SMTP service, or an encrypted SMTP service which also uses REQUIRE_AUTH.)
In addition, you can use an AUTH_SET_VALIDRCPTTO_CDB or AUTH_UNSET_VALIDRCPTTO_CDB environment variable whose value will replace the original value when a client successfully authenticates. If you set the value to an empty string, or if you UNSET the variable entirely, qmail-smtpd will close any file which may be already open and continue without doing the validrcptto.cdb checks at all.
IF YOU ARE ALREADY USING AN OLDER VERSION OF THE PATCH, YOU WILL NEED TO ADD THE NEW ENVIRONMENT VARIABLE TO YOUR SMTP SERVICES. If you don't, the validrcptto.cdb file you may already have in place will stop working.
Thanks to Nigel Mundy for helping me think of how to structure this change.
Added a log message when the DATABYTES mechanism prevents a message from being accepted. Thanks to Don Orbin for the suggestion.
Something so simple I'm surprised nobody thought of it before... added basic logging of MAIL FROM and RCPT TO arguments. The QMAILSMTPD_LOG_MAIL and/or QMAILSMTPD_LOG_RCPT variables may be set to a non-zero value to enable logging of each one.
Note that the VALIDRCPTTO_LOG code was already logging the RCPT TO commands, I added a check so that if QMAILSMTPD_LOG_RCPT logging is enabled, VALIDRCPTTO_LOG will not cause the RCPT TO command to be logged twice. If you are using a script which relies on the log entries generated by the VALIDRCPTTO_LOG code, you may need to change it to look for the RCPT TO:<_____> entries generated by this code instead.
These environment variables will be re-read if the client sends a successful AUTH command. This means that you could create AUTH_SET_QMAILSMTPD_LOG_MAIL and/or AUTH_SET_QMAILSMTPD_LOG_RCPT variables whose value would override the original environment variable whenever a client authenticates.
Added the big-concurrency patch. I actually meant to add this one a long time ago, but kept forgetting about it. The "conf-spawn" file in the qmail source, which limits the maximum number of concurrent deliveries that qmail-send will process at once, normally has a range of (1-255) with a default of 120. This patch changes the range to (1-65,000), but unlike the original patch, it doesn't change the default- so even with this patch, if you want more than 120, you will need to edit the conf-spawn file before compiling qmail.
Note that most systems have a "hidden limit" on how many concurrent deilveries can be processed, because most kernels impose a limit on how many file handles may be opened by any single process (typically 1,024.) Each delivery uses two of those handles, and qmail-send itself uses five of them for other purposes. If you set this value higher than the "hidden limit" for your system (typically 509) then qmail will refuse to compile... and if you try to be clever and work around the check (which is in "chkspawn.c") then you run the risk of qmail-send failing under heavy loads- and you don't want that.
If you're really curious and wonder why the original limit was 255, it's because the protocol that qmail-send uses to exchange information with qmail-lspawn and qmail-rspawn originally used a one-byte identifier for each delivery. This patch changes all three programs so that these messages now use two bytes for the delivery identifier.
If you truly feel that you need a higher concurrency than 120, and you're sure that your system will handle more than 255 deliveries at once, now you have the option. Be careful.
Added the QMAILSMTPD_HELP_VERSION environment variable. If this is set to a non-zero value, qmail-smtpd will include the version number of this combined patch in the output of the HELP command.
This environment variable will be re-read if the client sends a successful AUTH command. This means that you could set an AUTH_SET_QMAILSMTPD_HELP_VERSION variable whose value would override the original environment variable whenever a client authenticates, so you can do something like only telling authenticated clients what version of the software you're running.
Thanks to Nigel Mundy for the idea.
Changes in Version 7, released 2007-09-03
Fixed a potential bug with the original qmail-1.03-jms1-antispam.patch from 2002, which would have caused exit value 115 to be interpreted incorrectly.
Changes in Version 7.01, released 2007-09-12
Added Inter7's qmail-tap patch. See the README.tap file in the source code.
Changes in Version 7.02, released 2007-09-12
Added code to the AUTH_CDB patch to allow for specific environment variables to be added or changed when an individual user authenticates.
Changes in Version 7.03, released 2007-09-28
Changes in Version 7.04, released 2007-10-09
If the AUTH_CDB mechanism detects an environment variable called "PASSWORD_EXPIRES" being set to a non-zero value, the password will not work after that time. The value should be expressed in seconds since the epoch, as returned by the time() function. If the password has not expired, the variable is still added to the environment just like any other variable.
Changes in Version 7.05, released 2007-11-09
Fixed a bug which was preventing the TLS_SERVER_CERT variable from working if the default "servercert.pem" file didn't also exist. Thanks to Brent Powers for finding the bug and walking me through the process of understanding it.
Added the ability for qmail-remote to bind() to a specific local IP address when sending outbound mail, based on the domain name of the sender. This replaces the "qmail-1.03-bind-interface.patch" from version 5f.
A replacement for that patch which includes the new functionality is available as newbind.patch, for people who may be using the existing patch and want the new feature but don't want to use the combined patch in full.
This functionality is controlled by a "control/senderip" file whose lines look like this:
domain:1.2.3.4
Any mail sent from an email address in the given domain will be sent "from" the given IP address. If qmail-remote is not able to bind() to that IP (i.e. if the IP isn't assigned to an interface on the machine, for example) then the message will stay in the queue until the problem is corrected (i.e. until a correct IP address is put into the file, or the domain is removed from the file.)
Note that if you have both a "control/senderip" file (to choose the source IP by sender domain name) and a "control/bindroutes" file (to choose the source IP by recipient IP address), the choice based on the domain name will take precendence.
Also note that if you wish to set a "default" source IP, you need to do this in the "control/bindroutes" file. This functionality was already there, I didn't see any reason to change it.
This feature was suggested by, and developed with the support of, GGMR Marketing Consultants.
Changes in Version 7.06, released 2008-05-12 (individual patches)
Updated the version numbers in the qmail-smtpd HELP output and on the qmail-smtpd man page.
Added documentation about the PASSWORD_EXPIRES variable to the qmail-smtpd man page.
Fixed a bug in qmail-smtpd which was preventing per-user environment variables from being added to the environment after a successful AUTH command, when using the AUTH_CDB mechanism. Thanks to Alexandre "dude" Fiori for pointing out the bug.
Added a fix for an old bug found by Georgi Guninski (in qmail itself, not specifically in my patch) which could cause qmail-smtpd to crash if a single header in an incoming message were over 2GB in size.
Added a fix for a bug in qmail-qmtpd found by Georgi Guninski (again, in qmail itself- not specific to my patch) where the "length" portion of a "netstring" was not being checked for digits only.
Note that my fix is not the same as the fix he has on his web site, as I think it makes more sense to return a "protocol error" (exit code 100, a permanent error) than it does to return "out of resources" (exit code 111, a temporary error.)
Changes in Version 7.07, released 2008-06-02 (individual patches)
Added Jay Soffian's RCPTCHECK patch. With this patch, if a RCPTCHECK environment variable exists, its value should be the full pathname of an external program which qmail-smtpd will run after receiving a RCPT command.
Before running the program, qmail-smtpd will store the envelope sender (from the MAIL command) in the SENDER environment variable, and the recipient (from the RCPT command) in the RECIPIENT variable. Any other environment variables which were inherited by qmail-smtpd, including the TCPREMOTEHOST variable (set by tcpserver) and the SMTP_AUTH_USER variable (if the client has sent a successful AUTH command) will be present as well. The script is free to us any or all of these variables in its decision-making process.
The exit code from this program tells qmail-smtpd to accept or refuse the command, or to immediately terminate the client's connection. The possible values are:
100: The recipient is not valid. The client receives a 553 error.
111: Temporary problem verifying the recipient. The client receives a 421 error code and the connection is closed.
120: The program could not execute correctly. The client receives a 421 error code and the connection is closed.
Any other value: The recipient is valid.
The original patch did exactly this; my version has a few extra tweaks added:
The validrcptto.cdb file (if any) will be checked before the RCPTCHECK program (if any) runs. If the validrcptto.cdb mechanism rejects a recipient, the RCPTCHECK program will not be run for that recipient.
When storing the SENDER and RECIPIENT variables, qmail-smtpd will also store a HELO variable which contains whatever name the client used with their most recent HELO command. This is actually one line added to the code, just before the execve() call which runs the RCPTCHECK program:
if (!env_put2("HELO",helohost.s)) die_nomem();
Thanks to Hugo Monteiro (on djb's qmail list) for the suggestion.
Before running the RCPTCHECK program, qmail-smtpd will change the file handles it gives to the program, so that if the program sends anything to its "standard out" channel (which goes back to the client and would "break" the SMTP conversation) that output will be sent to the "standard error" channel (i.e. the log file) instead. This is done with these two lines, which do the same thing that "2>&1" does in a shell script:
close(1);
dup2(2,1);
Note: if you ever need to do this in a program you may be writing, this must be done after the fork() call which creates the child process, but before the execve() call which executes the actual program.
Added documentation about the RCPTCHECK variable and its functionality to the qmail-smtpd man page.
Updated the version numbers in the qmail-smtpd HELP output and on the qmail-smtpd man page.
Changes in Version 7.08, released 2008-12-04 (individual patches)
Updated the MFCHECK code to include Jeremy Kister's "version 4" updates. The idea is that "MAIL FROM:<blah>" (where the purported sender does not contain an "@" character) should not be considered valid. However, "MAIL FROM:<>" must still be considered valid, since all bounce messages use this. Jeremy's version of the patch can be found at http://jeremy.kister.net/code/mfcheck/qmail-1.03-mfcheck.4jk.patch.
Programs run from the RCPTCHECK mechanism can now send a custom error message back to qmail-smtpd by writing it to file descriptor 4. qmail-smtpd will explicitly create a USE_FD4=1 environment variable to tell the RCPTCHECK program that this feature is available. You MUST NOT create this environment variable yourself- qmail-smtpd will do it, if and only if this new functionality is available.
The message MUST start with a valid three-digit SMTP status code (either "550" for a hard failure, or "450" for a soft failure) followed by a space and your message. You MUST NOT send any CR or LF characters at the end of your message.
If you are writing a custom RCPTCHECK handler, you MUST NOT write any data to file descriptor 4 without first checking to ensure that this variable exists and has the value "1". Blindly assuming that file descriptor 4 will always be there is a good way to get yourself into trouble.
Fixed a long-standing issue where recordio would cause STARTTLS connections to die. Turns out the bug fix has been around for years, but I had never seen it. Thanks to Warren Volz for letting me know about it.
Updated the version numbers in the qmail-smtpd HELP output and on the qmail-smtpd man page.
Changes in Version 7.09, released 2010-02-05 (individual patches)
When an SMTP client sends a MAIL FROM command with the AUTH= extension (RFC 2554), the AUTH= argument should be encoded using XTEXT (RFC 1891). The patch I originally used, which made qmail-remote able to authenticate when connecting to other servers, did not do this.
I copied the xtext function from Dr. Erwin Hoffmann's qmail-authentication-069_tgz.bin patch, and made the other adjustments myself (because my combined patch has changed some other things as well- for example, my patch has a single function which tries AUTH LOGIN and then AUTH PLAIN, while his patch has them as separate functions.)
I haven't tested this myself, because I don't have any machines which use AUTH when connecting to remote servers. Hopefully somebody else can test it and let me know if it works correctly now.
Thanks to Tomas Lee for finding the bug, and reporting it on djb's qmail list. Apparently this bug is present in a lot of the other patches out there as well.
There is a typo in my copying of the code from Dr. Hoffmann's patch. Please use version 7.10 below.
Fixed a bug in the code I added to allow RCPTCHECK programs to return custom error messages. Thanks to Boyko Yordanov for finding the bug.
Updated the version numbers in the qmail-smtpd HELP output and on the qmail-smtpd man page.
Changes in Version 7.10, released 2010-02-14 (individual patches)
Fixed a typo in the code I copied from Dr. Hoffmann's patch above. Thanks to Vasco Santos for noticing the typo.
Updated the version numbers in the qmail-smtpd HELP output and on the qmail-smtpd man page.
I've been asked a few times how to actually use these patch files. Here's a quick example. Note that this does NOT need to be done as root, except where noted at the end. I'm also leaving out the process of creating the user and group IDs that qmail needs.