qmail-smtpd-chkusr

This version of chkusr has been substituted by chkuser 2.0, that you find at this page.


Description
These patches are designed to work with qmail-smtpd (version 1.03) and vpopmail (versions below declared) and accept a message if the recipient is either:

  • a valid user
  • an alias/forward/autoresponder
  • an ezmlm mailing list (anything starting with a mailing list name and following general ezmlm addressing rules)

The patch has been thinked to be the most secure, fast, readable and least intrusive than possible (so no additional logging or other operations not necessary to recipient existence checking).

Why this patch
The original qmail-smtpd accepts by default all messages, checking later for the existence of the recipient. So, if the message has wrong recipient this generates more additional work and more traffic, and if also the sender (reply-to) is not existing the message is bounced back to the postmaster of the recipient.

I wrote this patch in order to check the existence of an e-mail user directly in the acceptance phase of a message and reject immediately all messages not directed to existing users, avoiding additional traffic, work and messages bounced back to me (!).

Versions

Patch version

Vpopmail version

Download patch

Commented patch

1.0

5.3.25 & following

Both versions 1.0 ("Regular" and "Easy-way") work fine with vpopmail >= 5.3.25, but see the note for vpopmail 5.3.25 for a simple change in code

1.0

5.3.6

Easy-Way-1.0

This patch is a semplified version of the regular version, and it's provided only for convenience. See co-existence considerations.
This patch is the one optionally integrated in Matt Simerson's megatoaster and Bill Shupp's megapatch.

1.0

5.3.6

regular patch-1.0

Commented-1.0

0.2

4.9.x

patch-0.2

Commented-0.2

 

Installation
qmail-smtpd-chkusr is working on my system since february 2001 (with latest version installed on 26 february 2002), and I'm (until now) satisfied with functionality, performance and security.


Apply patch and make qmail

Make a backup copy of original qmail-smtpd.c source and working qmail-smtpd (by default in /var/qmail/bin).
After having applied the patch you've selected, modify the path for some #include statements (see commented or normal patches) within the new qmail-smtpd.c.
Modify your qmail Makefile and include vpopmail and crypt libraries (also include mysql or whenever other libraries you're using for authentication within vpopmail - i.e. ldap, sybase, PostgreSQL, etc.)
Make make and rebuild qmake-smtpd, and rename it qmail-smtpd-chkusr, in order to know later which version you're using.

Note on vpopmail 5.3.25 & following
Starting from version 5.3.25, vpopmail has dismissed the function vget_real_domain().
The function making the work of vget_real_domain() is already existing within chkusr, so the lines related vget_real_domain() may be commented out, without losing any functionality.
Just delete or comment out these lines in red:

/* Check if domain is a real domain */
if (!stralloc_0 (&domain)) die_nomem();
vget_real_domain(domain.s, domain.a);
domain.len = strlen (domain.s);
if (domain.len > (domain.a - 1)) die_nomem();
/* Let's get domain's real path */

Installation of qmail-smtpd-chkusr

Regular version

"Easy Way" version

"regular" qmail-smtpd-chkusr must be installed (by default in /var/qmail/bin) with setuid (user qmaild) and setgid (group nofiles), and executed by tcpserver with -u vpopmail-user and -g vchkpw-group parameters.
qmail-smtpd-chkusr starts running with the original qmail-smtpd uid and gid, switching to needed uid and gid only for vpopmail checks on user existence, turning back to the starting uid and gid.

You have to set SUID (set-user-ID-on-execution) and SGID (set-group-ID-on-execution) bits on qmail-smtpd-chkusr:
chown qmaild qmail-smtpd-chkusr
chgrp nofiles qmail-smtpd-chkusr
chmod 6555 qmail-smtpd-chkusr

and the result you see should be like (different size and date, of course):
-r-sr-sr-x 1 qmaild nofiles 57056 Feb 14 18:18 qmail-smtpd-chkusr


Integrate qmail-smtpd-chkusr in your start files:
As example, a real start command for qmail-smtpd-chkusr may be

#!/bin/sh -e
#
# Using splogger to send the log through syslog.

exec env - PATH="/var/qmail/bin:/usr/local/bin" \
tcpserver -t 5 -v -p -x <your.tcp.smtp.cdb> \
-u <vpopmail-user> -g <vchkpw-group> -l <your-host.domain> 0 smtp \
qmail-smtpd-chkusr splogger smtpd &

where
<vpopmail-user> = vpopmail uid
<vchkpw-group> = vchkpw gid
<your-host.domain> = your host.domain (!)
<your.tcp.smtp.cdb> = your tcp.permission.to.relay cdb

NOTE: if you are using more system users for your domains, the execution uid (which I indicated as vpopmail) should be set to root.

"Easy way" qmail-smtpd-chkusr must be installed normally (-r-xr-xr-x) and executed by tcpserver with -u vpopmail-user and -g vchkpw-group parameters.


Integrate qmail-smtpd-chkusr in your start files:
As example, a real start command for qmail-smtpd-chkusr may be

#!/bin/sh -e
#
# Using splogger to send the log through syslog.

exec env - PATH="/var/qmail/bin:/usr/local/bin" \
tcpserver -t 5 -v -p -x <your.tcp.smtp.cdb> \
-u <vpopmail-user> -g <vchkpw-group> -l <your-host.domain> 0 smtp \
qmail-smtpd-chkusr splogger smtpd &

where
<vpopmail-user> = vpopmail uid
<vchkpw-group> = vchkpw gid
<your-host.domain> = your host.domain (!)
<your.tcp.smtp.cdb> = your tcp.permission.to.relay cdb

NOTE: if you are using more system users for your domains, the execution user (which I indicated as vpopmail) should be set to root.



Starting of qmail-smtpd-chkusr
Kill the old tcpserver with qmail-smtpd and start the new one with qmail-smtpd-chkusr.
If all works nicely for you, put the new start command in the system startup commands (substituting the old one with qmail-smtpd).

Co-existence with tls patch
If you use tls patch, you must use the "Easy Way" version of chkusr.

The unique existing problem is related to the security model of the installation, that must be changed following other requirements of openssl (I have the impression openssl doesn't like too much read a certificate owning to someone that's not the effective uid/gid).
TLS needs to be the owner of the digital certs used, so you must be sure of that and certs must belong to vpopmail.vchkpw (and you must chmod 640 them also).

Following all these considerations, the code in Easy-Way-1.0.patch has been semplified, and all the code relative to uid/gid manipulation has been removed.

Co-existence with auth patch
If you use auth patch (up to version 0.31), you may experience this error:
421 unable to read controls

This is due to a bug in auth patch.
Auth patch closes (abnormally) a file descriptor used internally by qmail-smtpd to read morercpthosts.cdb, so:
if you have morercpthosts, and use auth patch, each call made to routine addrallowed(), if done after auth code has been called, will return that error.

In order to avoid this error, you must apply a correction to auth, as pointed out in
http://tomclegg.net/qmail/, and following page http://tomclegg.net/qmail/qmail-smtpd-auth-close3.patch

TMDA
TMDA needs the straight check of user existence to be widened, allowing any address like "realrecipient-extension@domain.com" to be considered valid.
This is an extension of the patch, that allows this behaviour.

 user_passwd = vauth_getpw (user.s, domain.s);
+ if (user_passwd == NULL) {
+ count = 0; + while ((count < (user.len -1)) && (user_passwd == NULL)) {
+ count += byte_chr(&user.s[count], user.len - count,'-');
+ if (count < user.len) {
+ if (!stralloc_copyb (&alias_name, user.s, count)) die_nomem();
+ if (!stralloc_0 (&alias_name)) die_nomem();
+ user_passwd = vauth_getpw (alias_name.s, domain.s);
+ ++count;
+ }
+ }
+ }
if (user_passwd != NULL) {
This code makes a recursive search, starting from left, and looking for each '-' character, until a valid user is found or string is ended.
Be aware to change the '-' constant to whatever you need for your TMDA system.

Change Log
V 1.0 (1 mar 2002):

vpopmail 5.3.3: Updated to vpopmail 5.3.3.

 

domain bounce checking: Checking on recipient existence is made only if bouncing is enabled for recipient domain.

 

valias support: added support for valias.

 

domains path: changed domain path computing (now derived from vpopmail functions and not computed in the fixed ../domains/DOMAINNAME way.

 

ezmlm mailing list: more tailored checking for ezmlm mailing list (only, previous check was more generic).

 

code reviewed and strengthened: code has been reviewed, mostly rewritten and made more robust, more modular on checkings.


V 0.2 (9 may 2001):

Modified emission of error code:

 from: 
void err_realrcpt() { out("553 sorry, no mailbox here by that name (#5.7.1 - usrchk)\r\n"); }
to:
void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); } 
Thanks to Larry M. Smith.

 

Checking of BOUNCE_MAIL flag: added checking of user's BOUNCE_MAIL flag.

 


Credits
I have to thanks Ward Vandewege, whose badrcpttp patch (see http://patch.be/qmail/badrcptto.html for reference) helped me to understand how qmail-smtpd work and where to modify the code.
Of course thanks to Dan Bernstein and Ken Jones (Inter7)!