--- qmail-smtpd.c.orig  1998-06-15
+++ qmail-smtpd.c       2000-11-26
25a26
> #include "dns.h"
30a32,40
> /* SpaceNet - maex */
> char strnum[FMT_ULONG];
> char sserrbuf[512];
> substdio sserr = SUBSTDIO_FDBUF(write,2,sserrbuf,sizeof(sserrbuf));
> void logerr(s) char *s; { if(substdio_puts(&sserr,s) == -1) _exit(1); }
> void logerrf(s) char *s; { if(substdio_puts(&sserr,s) == -1) _exit(1); if(substdio_flush(&sserr) == -1) _exit(1); }
> void logerrpid() { strnum[fmt_ulong(strnum,getpid())] = 0; logerr("pid "); logerr(strnum); logerr(" from "); }
> 
> 
51,53c61,80
< 
< void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
< void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
---
> void err_smf() { out("451 DNS temporary failure (#4.3.0)\r\n"); }
> void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
> void err_hmf(arg1,arg2) char *arg1,*arg2; {
>   logerr("qmail-smtpd: "); logerrpid(); logerr(arg1); logerr(" Non-existing DNS_MX: ");
>   logerr("MAIL "); logerr(arg2); logerrf("\n");  
>   out("552 sorry, your envelope sender domain must exist (#5.7.1)\r\n"); }
> void err_nogateway(arg1,arg2,arg3) char *arg1,*arg2,*arg3; {
>   logerr("qmail-smtpd: "); logerrpid(); logerr(arg1); logerr(" Invalid RELAY client: "); 
>   logerr("MAIL from: <"); logerr(arg2); logerr (">, RCPT "); logerr(arg3); logerrf("\n");  
>   out("553 sorry, that domain isn't allowed to be relayed thru this MTA (#5.7.1)\r\n"); }
> void err_bmf(arg1,arg2,arg3) char *arg1,*arg2,*arg3; {
>   logerr("qmail-smtpd: "); logerrpid(); logerr(arg1); logerr(" Invalid SENDER address: "); 
>   logerr("MAIL from: <"); logerr(arg2); logerr (">, RCPT "); logerr(arg3); logerrf("\n");  
>   out("554 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); 
>   flush(); _exit(1); }
> void err_rcp(arg1,arg2,arg3) char *arg1,*arg2,*arg3; { 
>   logerr("qmail-smtpd: "); logerrpid(); logerr(arg1); logerr(" Invalid RECIPIENT address: "); 
>   logerr("MAIL from: <"); logerr(arg2); logerr (">, RCPT "); logerr(arg3); logerrf("\n");  
>   out("555 sorry, your envelope recipient is in my badrcptto list (#5.7.1)\r\n"); 
>   flush(); _exit(1); }
83a111,113
> char *relayok;
> char *nodnscheck;
> char *msgsize;
99a130,165
> /* Wildmat Variables */
> int bmpok = 0;
> stralloc bmp = {0};
> struct constmap mapbmp;
> /* Wildmat Patch  END */
> 
> /* RECIPIENT Check Variables */
> int rcpok = 0;
> stralloc rcp = {0};
> struct constmap maprcp;
> int brpok = 0;
> stralloc brp = {0};
> struct constmap mapbrp;
> 
> /* RELAYCLIENT Check Variables */
> int relayclientsok = 0;
> stralloc relayclients = {0};
> struct constmap maprelayclients;
> int relaydomainsok = 0;
> stralloc relaydomains = {0};
> struct constmap maprelaydomains;
> 
> /* RELAYMAILFROM Check Variables */
> int rmfok = 0;
> stralloc rmf = {0};
> struct constmap maprmf;
> 
> /* TARPIT Check Variables */
> int tarpitcount = 0;
> int tarpitdelay = 5;
> 
> /* NODNSCHECK Check Variables */
> int nodnschecksok = 0;
> stralloc nodnschecks = {0};
> struct constmap mapnodnschecks;
> 
103a170,171
>   unsigned int i;
>   unsigned len;
112a181,191
> /* TARPIT Patch - include Control Files */
>  
>   if (control_readint(&tarpitcount,"control/tarpitcount") == -1) die_control();
>   if (tarpitcount < 0) tarpitcount = 0;
>   x = env_get("TARPITCOUNT");
>   if (x) { scan_ulong(x,&u); tarpitcount = u; };
>   if (control_readint(&tarpitdelay,"control/tarpitdelay") == -1) die_control();
>   if (tarpitdelay < 0) tarpitdelay = 0;
>   x = env_get("TARPITDELAY");
>   if (x) { scan_ulong(x,&u); tarpitdelay = u; };
> 
118a198,206
> 
> /* RELAYMAILFROM Patch - include Control File */
> 
>   rmfok = control_readfile(&rmf,"control/relaymailfrom",0);
>   if (rmfok == -1) die_control();
>   if (rmfok)
>     if (!constmap_init(&maprmf,rmf.s,rmf.len,0)) die_nomem();
> 
> /* Wildmat Patch - include Control file */ 
119a208,224
>   bmpok = control_readfile(&bmp,"control/badmailpatterns",0);
>   if (bmpok == -1) die_control();
>   if (bmpok)
>     if (!constmap_init(&mapbmp,bmp.s,bmp.len,0)) die_nomem();
>  
> /* RECIPIENT Patch - include Control file */
> 
>   rcpok = control_readfile(&rcp,"control/badrcptto",0);
>   if (rcpok == -1) die_control();
>   if (rcpok)
>     if (!constmap_init(&maprcp,rcp.s,rcp.len,0)) die_nomem();
>   
>   brpok = control_readfile(&brp,"control/badrcptpatterns",0);
>   if (brpok == -1) die_control();
>   if (brpok)
>     if (!constmap_init(&mapbrp,brp.s,brp.len,0)) die_nomem();
> 
133c238,283
<   relayclient = env_get("RELAYCLIENT");
---
>   relayok = relayclient = env_get("RELAYCLIENT");
> 
> /* DNSCHECK Patch - include Control file */
> 
>   nodnscheck = env_get("NODNSCHECK");
> 
>   if (! nodnscheck) 
>     {
>       /* Look up "MAIL from:" addresses to skip for DNS check in control/nodnscheck. */
>       nodnschecksok = control_readfile(&nodnschecks,"control/nodnscheck",0);
>       if (nodnschecksok == -1) die_control();
>       if (nodnschecksok)
> 	  if (!constmap_init (&mapnodnschecks, nodnschecks.s, nodnschecks.len, 0)) die_nomem();
>     }
> 
>   if (! relayclient)
>     {
>       /* Attempt to look up the IP number in control/relayclients. */
>       relayclientsok = control_readfile(&relayclients,"control/relayclients",0);
>       if (relayclientsok == -1) die_control();
>       if (relayclientsok) {
>         if (!constmap_init (&maprelayclients, relayclients.s, relayclients.len, 1)) die_nomem();
> 
>         for (i = len = str_len (remoteip); i > 0; i --)
> 	  if ((i == len) || (remoteip[i - 1] == '.')) {
> 	    if ((relayclient = constmap (&maprelayclients, remoteip, i)))
>       	      break;
> 	  }
>        }
>     }
> 
>   if (! relayclient)
>     {
>       /* Attempt to look up the host name in control/relaydomains. */
>       relaydomainsok = control_readfile(&relaydomains,"control/relaydomains",0);
>       if (relaydomainsok == -1) die_control();
>       if (relaydomainsok) {
>         if (!constmap_init (&maprelaydomains, relaydomains.s, relaydomains.len, 1)) die_nomem();
> 
>       	for (i = 0, len = str_len (remotehost); i <= len; i ++)
>       	  if ((i == 0) || (i == len) || (remotehost[i] == '.'))
>       	    if ((relayclient = constmap (&maprelaydomains, remotehost + i, len - i)))
>       	      break;
>       }
>     }
> 
199a350,385
> /* SIZELIMIT Function by Chris Harris */
> 
> int sizelimit(arg)
>  char *arg;
>  {
>    int i;
>    long r;
>    unsigned long sizebytes = 0; 
>  
>    i = str_chr(arg,'<');
>    if (arg[i])
>      arg += i + 1;
>    else {
>      arg += str_chr(arg,':');
>      if (*arg == ':') ++arg;
>      while (*arg == ' ') ++arg;
>    }
>  
>    arg += str_chr(arg,' ');
>    if (*arg == ' ') while (*arg == ' ') ++arg;
>    else return 1;
>  
>    i = str_chr(arg,'=');
>    arg[i] = 0;
>    if (case_equals(arg,"SIZE")) {
>      arg += i;
>      while (*++arg && *arg > 47 && *arg < 58) {
>        sizebytes *= 10;
>        sizebytes += *arg - 48;
>      }
>      r = databytes - sizebytes;
>      if (r < 0) return 0;
>    }
>    return 1;
>  }
> 
201a388
>   int i;
203c390,394
<   if (!bmfok) return 0;
---
>   int k = 0;
>   char subvalue;
>   case_lowerb(addr.s,addr.len); /* convert into lower case */
> 
>   if (bmfok) {
207a399,483
>   }
> 
> /* Include control file control/badmailpatterns and evaluate with Wildmat check */
>      
>   if (bmpok) {
>   i = 0;
>   for (j = 0;j < bmp.len;++j)
>    if (!bmp.s[j]) {
>     subvalue = bmp.s[i] != '!';
>     if (!subvalue) i++;
>     if ((k != subvalue) && wildmat(addr.s, bmp.s + i)) k = subvalue;
>     i = j + 1;
>     }
>    return k;
>   }
>   return 0;
> }
> 
> int rmfcheck()
> {
>   int j;
>   if (!rmfok) return 0;
>   if (constmap(&maprmf,addr.s,addr.len - 1)) return 1;
>   j = byte_rchr(addr.s,addr.len,'@');
>   if (j < addr.len)
>     if (constmap(&maprmf,addr.s + j,addr.len - j - 1)) return 1;
>   return 0;
> }
> 
> int rcpcheck()
> {
>   int i;
>   int j;
>   int k = 0;
>   char subvalue;
>   case_lowerb(addr.s,addr.len); /* convert into lower case */
> 
> /* Include control file control/badrcptto */
> 
>   if (rcpok) {
>   if (constmap(&maprcp,addr.s,addr.len - 1)) return 1;
> 
>   j = byte_rchr(addr.s,addr.len,'@');
>   if (j < addr.len)
>     if (constmap(&maprcp,addr.s + j,addr.len - j - 1)) return 1;
>   }
> 
> /* Include control file control/badrcptpatterns and evaluate with Wildmat check */
> 
>   if (brpok) {
>   i = 0;
>   for (j = 0;j < brp.len;++j)
>    if (!brp.s[j]) {
>     subvalue = brp.s[i] != '!';
>     if (!subvalue) i++;
>     if ((k != subvalue) && wildmat(addr.s, brp.s + i)) k = subvalue;
>     i = j + 1;
>     }
>    return k;
>   }
>   return 0;
> }
> 
> int dnscheck()
> {
>   stralloc sa = {0};
>   ipalloc ia = {0};
>   unsigned int random;
>   int j;
> 
>   if (nodnschecksok) {
>   if (constmap(&mapnodnschecks,addr.s,addr.len - 1)) return 0;
>   j = byte_rchr(addr.s,addr.len,'@');
>   if (j < addr.len)
>     if (constmap(&mapnodnschecks,addr.s + j,addr.len - j - 1)) return 0;
>   }
> 
>   random = now() + (getpid() << 16);
>   j = byte_rchr(addr.s,addr.len,'@') + 1;
>   if (j < addr.len) {
>     stralloc_copys(&sa, addr.s + j);
>     dns_init(0);
>     j = dns_mxip(&ia,&sa,random);
>     if (j < 0) return j;
>   }
221a498
> int flagrcpt; /* recipient filter   */
223a501,502
> int rcptcount;
> char size_buf[FMT_ULONG]; /* needed for SIZE CMD */  
227,228c506,512
<   smtp_greet("250 "); out("\r\n");
<   seenmail = 0; dohelo(arg);
---
>     smtp_greet("250 "); out("\r\n");
>     seenmail = 0; dohelo(arg);
> }
> void smtp_size()
> {
>    size_buf[fmt_ulong(size_buf,(unsigned long) databytes)] = 0;
>    out("250 SIZE "); out(size_buf); out("\r\n");
232c516,517
<   smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
---
>   smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
>   smtp_size();
242a528,529
> /* Return error if incoming SMTP msg exceeds DATABYTES */
>   if (databytes && !sizelimit(arg)) { err_size(); return; }
243a531,538
>   relayok = relayclient;
>   if (!relayok) if (rmfcheck()) relayclient = ""; else relayclient = 0; /* this code is not beautiful */
>   if (!nodnscheck) {
>     switch(dnscheck()) {
>       case DNS_HARD: err_hmf(remoteip,arg); return;
>       case DNS_SOFT: err_smf(); return;
>       case DNS_MEM: die_nomem(); }
>   }
247a543
>   rcptcount = 0;
250c546,547
< void smtp_rcpt(arg) char *arg; {
---
> void smtp_rcpt(arg) char *arg; 
> {
253c550,551
<   if (flagbarf) { err_bmf(); return; }
---
>   flagrcpt = rcpcheck();
>   if (flagbarf) { err_bmf(remoteip,mailfrom.s,arg); return; }
260c558
<     if (!addrallowed()) { err_nogateway(); return; }
---
>     if (!addrallowed()) { err_nogateway(remoteip,mailfrom.s,arg); return; } 
263a562,563
>   if (flagrcpt) { err_rcp(remoteip,mailfrom.s,arg); return; } /* RECIPIENT BAD* check */
>   if (tarpitcount && ++rcptcount >= tarpitcount) while (sleep(tarpitdelay)); /* TARPIT Delay */
302a603
>   int seencr;   
307,308c608,609
<   pos = 0; flagmaybex = flagmaybey = flagmaybez = 1;
<   for (;;) {
---
>   pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; seencr = 0; /* qmail-smtpd-newline patch */
>    for (;;) {
309a611,619
>     if (ch == '\n')
>      {
>       if (seencr == 0)
>        {
>         substdio_seek(ssin,-1);
>         ch = '\r';
>        }
>      }
>     if (ch == '\r') seencr = 1; else seencr = 0;
391c701
<   if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
---
>   if (databytes) if (!bytestooverflow) { err_size(); return; } 
