--- Makefile.orig Mon Apr 23 15:20:25 2001 +++ Makefile Mon Apr 23 15:24:51 2001 @@ -7,6 +7,8 @@ # to use cleartext passwords (a bad idea on production systems) add # -DCLEARTEXTPASSWD to the LDAPFLAGS LDAPFLAGS=-DQLDAP_CLUSTER +RBLTAGON=-DRBLTAG + # Perhaps you have different ldap libraries, change them here LDAPLIBS=-L/usr/local/lib -lldap -llber @@ -1578,11 +1580,12 @@ load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \ date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \ getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \ -str.a fs.a auto_qmail.o +str.a fs.a auto_qmail.o dns.o ipalloc.o ./load qmail-qmtpd rcpthosts.o control.o constmap.o \ received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ datetime.a open.a getln.a sig.a case.a env.a stralloc.a \ - alloc.a substdio.a error.a str.a fs.a auto_qmail.o + alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ + dns.o ipalloc.o ip.o `cat dns.lib` qmail-qmtpd.0: \ qmail-qmtpd.8 @@ -1592,7 +1595,7 @@ compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \ substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \ auto_qmail.h readwrite.h control.h received.h - ./compile qmail-qmtpd.c + ./compile ${RBLTAGON} qmail-qmtpd.c qmail-qread: \ load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \ @@ -1790,7 +1793,7 @@ error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h - ./compile ${TLSON} ${TLSINCLUDES} qmail-smtpd.c + ./compile ${RBLTAGON} ${TLSON} ${TLSINCLUDES} qmail-smtpd.c qmail-start: \ load qmail-start.o prot.o fd.a auto_uids.o --- qmail-showctl.c.orig Mon Apr 23 15:27:51 2001 +++ qmail-showctl.c Mon Apr 23 15:28:31 2001 @@ -300,6 +300,7 @@ do_lst("badrcptto","Any RCPT TO is allowed.",""," not accepted in RCPT TO"); do_lst("relaymailfrom","Relaymailfrom not enabled.","Envelope senders allowed to relay: ","."); do_lst("rbllist","No RBL listed.","RBL to check: ","."); + do_lst("rbltags","No RBL listed.","RBL to check: ","."); substdio_puts(subfdout,"\n"); --- qmail-smtpd.c.orig Mon Apr 23 15:29:23 2001 +++ qmail-smtpd.c Mon Apr 23 11:47:09 2001 @@ -186,6 +186,9 @@ char *relayok; char *denymail; char *rblenabled; +#ifdef RBLTAG + char *rbltagenabled; +#endif int spamflag = 0; stralloc helohost = {0}; @@ -207,6 +210,10 @@ struct constmap maprmf; int rblok = 0; stralloc rbl = {0}; +#ifdef RBLTAG +int rbltagok = 0; +stralloc rbltag = {0}; +#endif int tarpitcount = 0; int tarpitdelay = 5; int maxrcptcount = 0; @@ -263,7 +270,14 @@ if (rblok == -1) die_control(); if (rblok) rblenabled = env_get("RBL"); - + +#ifdef RBLTAG + rbltagok = control_readfile(&rbltag,"control/rbltags",0); + if (rbltagok == -1) die_control(); + if (rbltagok) + rbltagenabled = "1"; +#endif + if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); if (x) { scan_ulong(x,&u); databytes = u; } @@ -388,6 +402,9 @@ /* RBL */ stralloc ip_reverse; +#ifdef RBLTAG +stralloc tagrblid; +#endif void rbl_init() { @@ -470,6 +487,41 @@ return r; } +#ifdef RBLTAG +int rblcheck_tag() +{ + int r; + char *p; + rbl_init(); + + p = &rbltag.s[0]; + while(p < &rbltag.s[0]+rbltag.len) + { + logpid(2); logstring(2,"RBL check with '"); logstring(2,p); logstring(2,"':"); + r = rbl_lookup(p); + switch(r) { + case 2: + logstring(2,"temporary DNS error"); + break; + case 1: + logstring(2,"found match"); + if ( 0 != tagrblid.len ) if (!stralloc_cats(&tagrblid," ")) die_nomem(); + if (!stralloc_cats(&tagrblid,p)) die_nomem(); + break; + default: + logstring(2, "no match"); + break; + } + /* continue */ + logflush(); + p = p+strlen(p); + p++; + } + if ( 0 != tagrblid.len ) tagrblid.s[tagrblid.len]='\0'; + return r; +} +#endif + /* RBL */ int sizelimit(arg) @@ -638,7 +690,14 @@ logline(3,"RBL checking completed without match"); } } - +#ifdef RBLTAG + if (rbltagenabled && !relayclient) + { + logline(3,"RBL TAGGING enabled, going through list of RBLs"); + rblcheck_tag(); + } +#endif + /* DENYMAIL is set for this session from this client, so heavy checking * of mailfrom is done. If one of the following is set: * SPAM -> refuse all mail @@ -865,6 +924,37 @@ return r; } +#ifdef RBLTAG +void rblcheckfmt(qqt, rblid) +struct qmail *qqt; +char *rblid; +{ + unsigned int j,k; + + if (!rblid) return; + + j=0; + while ('\0'!=rblid[j] && ' '==rblid[j]) j++; /* eat up whitespace */ + k=j; + while ('\0' != rblid[j]) { + if (' ' == rblid[j]) { + rblid[j] = '\0'; + qmail_puts(qqt,"X-RBL-Check: "); + qmail_puts(qqt,rblid+k); + qmail_puts(qqt,"\n"); + rblid[j] = ' '; + while (' ' == rblid[++j]); /* eat up whitespace */ + k=j; + } else j++; + } + if (j!=k) { + qmail_puts(qqt,"X-RBL-Check: "); + qmail_puts(qqt,rblid+k); + qmail_puts(qqt,"\n"); + } +} +#endif + char ssinbuf[1024]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); @@ -992,6 +1082,9 @@ #else received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]); #endif +#ifdef RBLTAG + rblcheckfmt(&qqt, tagrblid.s); +#endif blast(&hops); receivedbytes[fmt_ulong(receivedbytes,(unsigned long) bytesreceived)] = 0; --- qmail-qmtpd.c.orig Mon Apr 23 15:29:38 2001 +++ qmail-qmtpd.c Mon Apr 23 12:20:25 2001 @@ -12,6 +12,11 @@ #include "control.h" #include "received.h" +#ifdef RBLTAG + #include "ipalloc.h" + #include "dns.h" +#endif + void badproto() { _exit(100); } void resources() { _exit(111); } @@ -73,6 +78,129 @@ char *relayclient; int relayclientlen; +#ifdef RBLTAG +char *rbltagenabled; +int rbltagok = 0; +stralloc rbltag = {0}; +#endif + +/* RBL */ + +stralloc ip_reverse; +#ifdef RBLTAG +stralloc tagrblid; + +void rbl_init() +{ + unsigned int i; + unsigned int j; + char *ip_env; + + ip_env = remoteip; + if (!ip_env) ip_env = ""; + + if (!stralloc_copys(&ip_reverse,"")) resources(); + + i = str_len(ip_env); + while (i) { + for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break; + if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) resources(); + if (!stralloc_cats(&ip_reverse,".")) resources(); + if (!j) break; + i = j - 1; + } +} + +stralloc rbl_tmp; + +int rbl_lookup(char *base) +{ + ipalloc rblsa = {0}; + + if (!*base) return 2; + + if (!stralloc_copys(&rbl_tmp,"")) resources(); + + if (!stralloc_copy(&rbl_tmp,&ip_reverse)) resources(); + if (!stralloc_cats(&rbl_tmp,base)) resources(); + + switch (dns_ip(&rblsa,&rbl_tmp)) + { + case DNS_MEM: + case DNS_SOFT: + return 2; /* soft error */ + break; + + case DNS_HARD: + return 0; /* found no match */ + break; + + default: + return 1; /* found match */ + break; + } +} + +int rblcheck_tag() +{ + int r; + char *p; + rbl_init(); + + p = &rbltag.s[0]; + while(p < &rbltag.s[0]+rbltag.len) + { + r = rbl_lookup(p); + switch(r) { + case 2: + break; + case 1: + if ( 0 != tagrblid.len ) if (!stralloc_cats(&tagrblid," ")) resources(); + if (!stralloc_cats(&tagrblid,p)) resources(); + break; + default: + break; + } + /* continue */ + p = p+strlen(p); + p++; + } + if ( 0 != tagrblid.len ) tagrblid.s[tagrblid.len]='\0'; + return r; +} + +void rblcheckfmt(qqt, rblid) +struct qmail *qqt; +char *rblid; +{ + unsigned int j,k; + + if (!rblid) return; + + j=0; + while ('\0'!=rblid[j] && ' '==rblid[j]) j++; /* eat up whitespace */ + k=j; + while ('\0' != rblid[j]) { + if (' ' == rblid[j]) { + rblid[j] = '\0'; + qmail_puts(qqt,"X-RBL-Check: "); + qmail_puts(qqt,rblid+k); + qmail_puts(qqt,"\n"); + rblid[j] = ' '; + while (' ' == rblid[++j]); /* eat up whitespace */ + k=j; + } else j++; + } + if (j!=k) { + qmail_puts(qqt,"X-RBL-Check: "); + qmail_puts(qqt,rblid+k); + qmail_puts(qqt,"\n"); + } +} +#endif +/* RBL */ + + main() { @@ -112,6 +240,14 @@ local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; +#ifdef RBLTAG + rbltagok = control_readfile(&rbltag,"control/rbltags",0); + if (rbltagok == -1) resources(); + if (rbltagok) + { + rblcheck_tag(); + } +#endif for (;;) { if (!stralloc_copys(&failure,"")) resources(); @@ -131,6 +267,9 @@ else badproto(); received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0); +#ifdef RBLTAG + rblcheckfmt(&qq, tagrblid.s); +#endif /* XXX: check for loops? only if len is big? */