spamdyke: Recipient Validation With spamdyke-qrv

# spamdyke

## A drop-in connection-time spam filter for qmail

## Recipient Validation With spamdyke-qrv

It's impossible to overstate the complexity of qmail's recipient validation procedure. It is inexcusably complex, far beyond the point where anyone can be certain qmail's implementation is correct (and secure) in all cases. If you want to get a glimpse at how bad it is, take at look at the flowchart here. You'll see the flowchart is big, but the number of possible configurations is describes enormous: there are just under 165 thousand different paths through it (even more if the loops are followed multiple times). Fully testing spamdyke's `reject-recipient` filter requires checking every one of those paths -- this takes weeks to finish using spamdyke's test scripts. spamdyke-qrv begins its work at step 7 in the flowchart (steps 1, 2, 5 and 6 are assumed to have been performed by spamdyke before spamdyke-qrv was started).

spamdyke-qrv is intended to be run as root by marking the binary "setuid root". This is necessary because spamdyke typically runs as a non-root user and doesn't have access to all of the files needed to validate an address without root access.

spamdyke-qrv returns its results to spamdyke using its exit code:

- `0`: No determination was made -- spamdyke-qrv could not tell if the address is valid or not
- `1`: The address is valid
- `2`: The address is invalid, delivery is not possible. Without spamdyke-qrv, qmail would accept the message, then bounce it.
- `3`: The address is unavailable until some condition is met -- usually a file's or directory's permissions must be changed. Without spamdyke-qrv, qmail accept the message and queue it until the condition is met. When qmail was written, this situation was probably common, since most users logged into their mail servers at the command line and edited files by hand. These days, an "unavailable" condition is most likely due to a misconfiguration that won't be fixed for days (if ever) In that case, qmail will queue the message for a while and eventually bounce it.

In theory, another program could be created to perform recipient validation that accepts the same inputs and returns the same exit codes. This is not recommended, however, because the details of correctly validating an address are simply overwhelming (again, see the flowchart).

If vpopmail is in use, spamdyke-qrv should be compiled with vpopmail support, which will allow it to execute two of vpopmail's programs in the final stages of validating an address. These two programs are:

- `valias`: This program looks up an address to determine if it is an alias for a real mailbox (vpopmail uses its own internal system for aliases instead of creating .qmail files). If a recipient address is actually a vpopmail alias, spamdyke-qrv has no way to look it up and may mistakenly reject the address without `valias`.
- `vuserinfo`: This program returns information about a recipient address; spamdyke-qrv uses it simply to determine if the address exists. Because vpopmail keeps its own list of valid addresses, it is possible for an address to appear valid (e.g. the correct files and directories exist on disk) when it is not.

Before executing either of these programs, spamdyke-qrv will drop its root privileges so they will run as the vpopmail user. However, because this user typically has access to every mailbox on the server, executing extra binaries represents a potential security risk. For this reason, the full path to each program must be given when spamdyke-qrv is compiled -- paths to the vpopmail binaries cannot be supplied on the command line and they will not be found using the `PATH`. To specify the path to the programs, use the `configure` script with the `VALIAS_PATH` and `VUSERINFO_PATH` options:

> `VALIAS_PATH=/path/to/valias VUSERINFO_PATH=/path/to/vuserinfo ./configure --with-vpopmail-support`

spamdyke-qrv will accept several command line arguments if qmail's control files are in a non-standard location. These options should only be used if qmail was customized somehow to store its files elsewhere (very unusual).

- `qmail-assign-cdb`: The full path to qmail's "assign" CDB file (be sure to use the CDB file, not the text file that was used to create it). The default value is: `/var/qmail/users/cdb`
- `qmail-defaultdelivery-file`: The full path to qmail's "defaultdelivery" file. The default value is: `/var/qmail/control/defaultdelivery`
- `qmail-envnoathost-file`: The full path to qmail's "envnoathost" file. The default value is: `/var/qmail/control/envnoathost`
- `qmail-locals-file`: The full path to qmail's "locals" file. The default value is: `/var/qmail/control/locals`
- `qmail-me-file`: The full path to qmail's "me" file. The default value is: `/var/qmail/control/me`
- `qmail-morercpthosts-cdb`: The full path to qmail's "morercpthosts" CDB file (be sure to use the CDB file, not the text file that was used to create it). The default value is: `/var/qmail/control/morercpthosts.cdb`
- `qmail-percenthack-file`: The full path to qmail's "percenthack" file. The default value is: `/var/qmail/control/percenthack`
- `qmail-rcpthosts-file`: The full path to qmail's "rcpthosts" file. The default value is: `/var/qmail/control/rcpthosts`