This patch adds a switch (via a control file or environment variable) to qmail to enable a pause before the SMTP greeting to detect violation of the SMTP protocol: If the remote system tries to send SMTP commands prior to the SMTP greeting the connection is terminated. This patch is specifically for netqmail-1.06 with the qmail-errmsg logging patch. Please see http://free.acrconsulting.co.uk/email/other.html for more information. Andrew Richards, November 2008. diff -N -u netqmail-1.06.errmsg-v1.1/qmail-smtpd.8 netqmail-1.06.errmsg-v1.1.with.earlytalker/qmail-smtpd.8 --- netqmail-1.06.errmsg-v1.1/qmail-smtpd.8 1998-06-15 11:53:16.000000000 +0100 +++ netqmail-1.06.errmsg-v1.1.with.earlytalker/qmail-smtpd.8 2008-11-04 11:33:32.000000000 +0000 @@ -77,6 +77,17 @@ is set, it overrides .IR databytes . .TP 5 +.I earlytalkerdroptime +Number of seconds to wait before issuing the welcome prompt. +Default: 0. If any input is received before the welcome prompt the +session is terminated. This can be helpful to trap junk SMTP traffic +(well-behaved MTAs will wait for the welcome prompt before sending). + +If the environment variable +.B EARLYTALKERDROPTIME +is set, it overrides +.IR earlytalkerdroptime . +.TP 5 .I localiphost Replacement host name for local IP addresses. Default: diff -N -u netqmail-1.06.errmsg-v1.1/qmail-smtpd.c netqmail-1.06.errmsg-v1.1.with.earlytalker/qmail-smtpd.c --- netqmail-1.06.errmsg-v1.1/qmail-smtpd.c 2008-11-02 19:13:06.000000000 +0000 +++ netqmail-1.06.errmsg-v1.1.with.earlytalker/qmail-smtpd.c 2008-11-04 14:08:42.000000000 +0000 @@ -179,6 +179,7 @@ int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; +unsigned int earlytalkerdroptime = 0; void setup() { @@ -207,6 +208,9 @@ remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; + if (control_readint(&earlytalkerdroptime,"control/earlytalkerdroptime") == -1) die_control(); + x = env_get("EARLYTALKERDROPTIME"); + if (x) { scan_ulong(x,&u); earlytalkerdroptime = u; } local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; @@ -369,6 +373,28 @@ unsigned int bytestooverflow = 0; unsigned int messagebytes = 0; +void earlytalkercheck(delay) +unsigned int delay; +{ + int r; + r = timeoutread(delay,0,ssinbuf,sizeof ssinbuf); + if (r == -1) if (errno == error_timeout) return; /* Timeout ==> No early talking */ + + /* Explain result of timeoutread and exit */ + enew(); + if (r<0) eout3("Error before greeting (",error_str(errno),")"); + else if (r==0) eout("Disconnect before greeting"); + else /* Earlytalker */ + { + eout("Data sent before greeting"); + out("554 SMTP protocol violation\r\n"); flush(); + } + + eout(": quitting\n"); + eflush(); + _exit(1); +} + void put(ch) char *ch; { @@ -514,6 +540,7 @@ if (chdir(auto_qmail) == -1) die_control(); setup(); if (ipme_init() != 1) die_ipme(); + if (earlytalkerdroptime) earlytalkercheck(earlytalkerdroptime); smtp_greet("220 "); out(" ESMTP\r\n"); if (commands(&ssin,&smtpcommands) == 0) die_read();