# HG changeset patch # User carl # Date 1188272959 25200 # Node ID 9b129ed78d7d0750cfa1a144836db6467c8f16a6 # Parent 7161d8451fcfc1515596e52b8d0e345f301a7555 actually use spamassassin result, allow build without spam assassin, only call it if some recipient needs it. diff -r 7161d8451fcf -r 9b129ed78d7d ChangeLog --- a/ChangeLog Sun Aug 26 20:54:59 2007 -0700 +++ b/ChangeLog Mon Aug 27 20:49:19 2007 -0700 @@ -1,5 +1,11 @@ $Id$ +6.06 2007-07-27 + Fix bug that effectively disabled spamassassin filtering. Improve + spamassassin filtering documentation. Generate warning if the + config file specifies spam assassin filtering, but spamc is not + found by autoconf. + 6.05 2007-07-26 Fix unitialized variable in my spamassassin code. diff -r 7161d8451fcf -r 9b129ed78d7d NEWS --- a/NEWS Sun Aug 26 20:54:59 2007 -0700 +++ b/NEWS Mon Aug 27 20:49:19 2007 -0700 @@ -1,5 +1,6 @@ $Id$ +6.06 2007-07-27 Fix bug that effectively disabled spamassassin filtering. 6.05 2007-07-26 Fix unitialized variable in my spamassassin code. 6.04 2007-07-26 Add spamassassin integration via spamc, code from spamass-milter. 6.03 2007-07-14 Don't add auto whitelist entries for our own domains. diff -r 7161d8451fcf -r 9b129ed78d7d configure.in --- a/configure.in Sun Aug 26 20:54:59 2007 -0700 +++ b/configure.in Mon Aug 27 20:49:19 2007 -0700 @@ -1,6 +1,6 @@ AC_PREREQ(2.59) -AC_INIT(dnsbl,6.05,carl@five-ten-sg.com) +AC_INIT(dnsbl,6.06,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADER([config.h]) @@ -8,7 +8,13 @@ # Checks for programs. AC_PATH_PROG(BASH, bash) +if test "x$BASH" = x ; then + AC_MSG_ERROR([bash required for init script]) +fi AC_PATH_PROG(SPAMC, spamc) +if test "x$SPAMC" = x ; then + AC_MSG_WARN([Spamc not found. SpamAssassin filtering disabled]) +fi AC_PROG_CXX AC_PROG_CC AC_PROG_CPP diff -r 7161d8451fcf -r 9b129ed78d7d dnsbl.conf --- a/dnsbl.conf Sun Aug 26 20:54:59 2007 -0700 +++ b/dnsbl.conf Mon Aug 27 20:49:19 2007 -0700 @@ -102,6 +102,7 @@ # dcc_from { include "/var/dcc/whitecommon"; }; }; - autowhite 90 "my-auto-whitelist"; + autowhite 90 "autowhite/my-auto-whitelist"; + # install should create /etc/dnsbl/autowhite writable by userid dnsbl }; diff -r 7161d8451fcf -r 9b129ed78d7d src/context.cpp --- a/src/context.cpp Sun Aug 26 20:54:59 2007 -0700 +++ b/src/context.cpp Mon Aug 27 20:49:19 2007 -0700 @@ -646,11 +646,12 @@ void CONFIG::dump() { - if (default_context) default_context->dump(true); + bool spamass = false; + if (default_context) default_context->dump(true, spamass); for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { CONTEXTP c = *i; CONTEXTP p = c->get_parent(); - if (!p && (c != default_context)) c->dump(false); + if (!p && (c != default_context)) c->dump(false, spamass); } char buf[maxlen]; for (context_map::iterator i=env_to.begin(); i!=env_to.end(); i++) { @@ -658,6 +659,9 @@ CONTEXTP con = (*i).second; printf("// envelope to %s \t-> context %s \n", to, con->get_full_name(buf,maxlen)); } + if (spamass && (spamc == spamc_empty)) { + printf("// *** warning - spamassassin filtering requested, but spamc not found by autoconf.\n"); + } } @@ -863,23 +867,26 @@ } -bool CONTEXT::acceptable_content(recorder &memory, int score, char *&msg) { +bool CONTEXT::acceptable_content(recorder &memory, int score, string& msg) { if (spamassassin_limit && (score > spamassassin_limit)) { - msg = "Mail rejected by spam assassin"; + char buf[maxlen]; + snprintf(buf, sizeof(buf), "Mail rejected - spam assassin score %d", score); + msg = string(buf); + return false; } if (memory.excessive_bad_tags(tag_limit)) { - msg = tag_limit_message; + msg = string(tag_limit_message); return false; } if (!host_random && memory.excessive_hosts(host_limit)) { - msg = host_limit_message; + msg = string(host_limit_message); return false; } return true; } -void CONTEXT::dump(bool isdefault, int level) { +void CONTEXT::dump(bool isdefault, bool &spamass, int level) { char indent[maxlen]; int i = min(maxlen-1, level*4); memset(indent, ' ', i); @@ -960,6 +967,7 @@ } printf("%s spamassassin %d; \n", indent, spamassassin_limit); printf("%s }; \n", indent); + spamass |= (spamassassin_limit != 0); } else { printf("%s content off {}; \n", indent, env_from_default); @@ -981,7 +989,7 @@ for (context_map::iterator i=children.begin(); i!=children.end(); i++) { CONTEXTP c = (*i).second; - c->dump(false, level+1); + c->dump(false, spamass, level+1); } printf("%s env_from %s { \t// %s\n", indent, env_from_default, fullname); diff -r 7161d8451fcf -r 9b129ed78d7d src/context.h --- a/src/context.h Sun Aug 26 20:54:59 2007 -0700 +++ b/src/context.h Mon Aug 27 20:49:19 2007 -0700 @@ -191,9 +191,9 @@ void add_cctld(char *cctld) {content_cctlds.insert(cctld); }; void set_host_limit(int limit) {host_limit = limit; }; - void set_spamassassin_limit(int limit) {spamassassin_limit = limit; }; void set_host_message(char *message) {host_limit_message = message;}; void set_host_random(bool random) {host_random = random; }; + void set_spamassassin_limit(int limit) {spamassassin_limit = limit; }; void set_tag_limit(int limit) {tag_limit = limit; }; void set_tag_message(char *message) {tag_limit_message = message;}; void add_tag(char *tag) {html_tags.insert(tag); }; @@ -204,8 +204,8 @@ bool get_content_filtering() {return content_filtering; }; int get_host_limit() {return host_limit; }; - int get_spamassassin_limit() {return spamassassin_limit;}; bool get_host_random() {return host_random; }; + int get_spamassassin_limit() {return (content_filtering) ? spamassassin_limit : 0;}; char* get_content_suffix(); char* get_content_message(); char* get_uribl_suffix(); @@ -216,10 +216,10 @@ string_set& get_html_tags(); dnsblp_list& get_dnsbl_list(); - bool acceptable_content(recorder &memory, int score, char *&msg); + bool acceptable_content(recorder &memory, int score, string& msg); bool ignore_host(char *host); - void dump(bool isdefault, int level = 0); + void dump(bool isdefault, bool &spamass, int level = 0); }; diff -r 7161d8451fcf -r 9b129ed78d7d src/dnsbl.cpp --- a/src/dnsbl.cpp Sun Aug 26 20:54:59 2007 -0700 +++ b/src/dnsbl.cpp Mon Aug 27 20:49:19 2007 -0700 @@ -251,6 +251,7 @@ authenticated = NULL; have_whites = false; only_whites = true; + want_spamassassin = false; memory = NULL; scanner = NULL; assassin = NULL; @@ -286,6 +287,7 @@ authenticated = NULL; have_whites = false; only_whites = true; + want_spamassassin = false; memory = NULL; scanner = NULL; assassin = NULL; @@ -964,10 +966,9 @@ priv.queueid = strdup(smfi_getsymval(ctx, "i")); priv.authenticated = smfi_getsymval(ctx, "{auth_authen}"); if (priv.authenticated) priv.authenticated = strdup(priv.authenticated); - priv.assassin = new SpamAssassin; - priv.assassin->mlfi_connect(&priv, priv.ip); - priv.assassin->mlfi_helo(priv.helo); - priv.assassin->mlfi_envfrom(priv.mailaddr, priv.queueid); + if (spamc != spamc_empty) { + priv.assassin = new SpamAssassin(&priv, priv.ip, priv.helo, priv.mailaddr, priv.queueid); + } return SMFIS_CONTINUE; } @@ -978,7 +979,7 @@ CONFIG &dc = *priv.pc; char *rcptaddr = rcpt[0]; char *loto = to_lower_string(rcptaddr); - priv.assassin->mlfi_envrcpt(ctx, loto); + if (priv.assassin) priv.assassin->mlfi_envrcpt(ctx, loto); // priv.mailaddr sending original message to loto CONTEXT &con = *(dc.find_context(loto)->find_context(priv.mailaddr)); VERIFYP ver = con.find_verify(loto); @@ -1070,6 +1071,8 @@ // but remember the non-whites priv.need_content_filter(rcptaddr, con); priv.only_whites = false; + priv.want_spamassassin |= (priv.assassin) && // have spam assassin available and + (con.get_spamassassin_limit() != 0); // want to use it with a non-zero score } if (st == white) { priv.have_whites = true; @@ -1082,7 +1085,7 @@ mlfiPriv &priv = *MLFIPRIV; if (priv.authenticated) return SMFIS_CONTINUE; if (priv.only_whites) return SMFIS_CONTINUE; - priv.assassin->mlfi_header(headerf, headerv); + if (priv.want_spamassassin) priv.assassin->mlfi_header(headerf, headerv); return SMFIS_CONTINUE; } @@ -1091,7 +1094,7 @@ mlfiPriv &priv = *MLFIPRIV; if (priv.authenticated) return SMFIS_CONTINUE; if (priv.only_whites) return SMFIS_CONTINUE; - priv.assassin->mlfi_eoh(); + if (priv.want_spamassassin) priv.assassin->mlfi_eoh(); return SMFIS_CONTINUE; } @@ -1100,7 +1103,7 @@ mlfiPriv &priv = *MLFIPRIV; if (priv.authenticated) return SMFIS_CONTINUE; if (priv.only_whites) return SMFIS_CONTINUE; - priv.assassin->mlfi_body(data, len); + if (priv.want_spamassassin) priv.assassin->mlfi_body(data, len); priv.scanner->scan(data, len); return SMFIS_CONTINUE; } @@ -1116,10 +1119,10 @@ // process end of message if (priv.authenticated || priv.only_whites) rc = SMFIS_CONTINUE; else { - int score = priv.assassin->mlfi_eom(); + int score = (priv.want_spamassassin) ? priv.assassin->mlfi_eom() : 0; // assert env_to not empty char buf[maxlen]; - char *msg = NULL; + string msg; string_set alive; bool random = false; int limit = 0; @@ -1151,7 +1154,7 @@ inet_ntop(AF_INET, (const u_char *)&ip, adr, sizeof(adr)); snprintf(buf, sizeof(buf), fmt, host, adr); } - msg = buf; + msg = string(buf); rejecting = true; } } @@ -1160,7 +1163,8 @@ } else if (!priv.have_whites) { // can reject the entire message - smfi_setreply(ctx, "550", "5.7.1", msg); + snprintf(buf, sizeof(buf), "%s", msg.c_str()); + smfi_setreply(ctx, "550", "5.7.1", buf); rc = SMFIS_REJECT; } else { diff -r 7161d8451fcf -r 9b129ed78d7d src/dnsbl.h --- a/src/dnsbl.h Sun Aug 26 20:54:59 2007 -0700 +++ b/src/dnsbl.h Mon Aug 27 20:49:19 2007 -0700 @@ -35,6 +35,7 @@ char *authenticated; // client authenticated? if so, suppress all dnsbl checks, but check rate limits bool have_whites; // have at least one whitelisted recipient? need to accept content and remove all non-whitelisted recipients if it fails bool only_whites; // every recipient is whitelisted? + bool want_spamassassin; // at least one non-whitelisted recipients has a non zero spamassassin limit context_map env_to; // map each non-whitelisted recipient to their filtering context recorder *memory; // memory for the content scanner url_scanner *scanner; // object to handle body scanning diff -r 7161d8451fcf -r 9b129ed78d7d src/includes.h --- a/src/includes.h Sun Aug 26 20:54:59 2007 -0700 +++ b/src/includes.h Mon Aug 27 20:49:19 2007 -0700 @@ -15,3 +15,4 @@ #include "context.h" #include "dnsbl.h" #include "scanner.h" +#include "spamass.h" diff -r 7161d8451fcf -r 9b129ed78d7d src/spamass.cpp.in --- a/src/spamass.cpp.in Sun Aug 26 20:54:59 2007 -0700 +++ b/src/spamass.cpp.in Mon Aug 27 20:49:19 2007 -0700 @@ -22,15 +22,27 @@ static const char Id[] = "$Id$"; +char *spamc = "@SPAMC@"; +char *spamc_empty = ""; bool warnedmacro = false; /* have we logged that we couldn't fetch a macro? */ const int maxlen = 1000; // used for snprintf buffers -SpamAssassin::SpamAssassin() +SpamAssassin::SpamAssassin(mlfiPriv *priv_, int ip, char *helo_, char *from, char *qid) { error = false; running = false; first_recipient = true; + priv = priv_; + ip4 = ip; + helo = helo_; + envfrom = from; + queueid = qid; + pid = 0; + pipe_io[0][0] = -1; + pipe_io[0][1] = -1; + pipe_io[1][0] = -1; + pipe_io[1][1] = -1; } @@ -55,26 +67,6 @@ } -void SpamAssassin::mlfi_connect(mlfiPriv *priv_, int ip) -{ - priv = priv_; - ip4 = ip; -} - - -void SpamAssassin::mlfi_helo(char *helohost) -{ - helo = helohost; -} - - -void SpamAssassin::mlfi_envfrom(char *from, char *qid) -{ - envfrom = from; - queueid = qid; -} - - void SpamAssassin::mlfi_envrcpt(SMFICTX *ctx, char *envrcpt) { if (first_recipient) { @@ -227,7 +219,7 @@ // execute spamc char* argv[3]; - argv[0] = "@SPAMC@"; + argv[0] = spamc; argv[1] = "-c"; argv[2] = NULL; execvp(argv[0] , argv); // does not return! diff -r 7161d8451fcf -r 9b129ed78d7d src/spamass.h --- a/src/spamass.h Sun Aug 26 20:54:59 2007 -0700 +++ b/src/spamass.h Mon Aug 27 20:49:19 2007 -0700 @@ -21,18 +21,17 @@ #include +extern char *spamc; +extern char *spamc_empty; using namespace std; class mlfiPriv; class SpamAssassin { public: - SpamAssassin(); + SpamAssassin(mlfiPriv *priv_, int ip, char *helo_, char *from, char *qid); ~SpamAssassin(); - void mlfi_connect(mlfiPriv *priv_, int ip); - void mlfi_helo(char *helohost); - void mlfi_envfrom(char *from, char *qid); void mlfi_envrcpt(SMFICTX *ctx, char *envrcpt); void mlfi_header(char* headerf, char* headerv); void mlfi_eoh(); @@ -58,12 +57,12 @@ // connection back to main dnsbl priv structure for logging mlfiPriv *priv; + int ip4; // ip4 address of smtp client // strings owned by main dnsbl - char *queueid; // the sendmail queue id for this message + char *helo; // client helo value char *envfrom; // envelope from value for this message - char *helo; // client helo value - int ip4; // ip4 address of smtp client + char *queueid; // the sendmail queue id for this message // Process handling variables pid_t pid; diff -r 7161d8451fcf -r 9b129ed78d7d xml/dnsbl.in --- a/xml/dnsbl.in Sun Aug 26 20:54:59 2007 -0700 +++ b/xml/dnsbl.in Mon Aug 27 20:49:19 2007 -0700 @@ -12,7 +12,7 @@ - 2007-07-26 + 2007-07-27 @@ -375,9 +375,10 @@ ignore list, the mail is rejected. - If the spamassassin limit for this filtering context is non-zero, the - message is passed thru spamassassin (via spamc) and if the resulting - score is larger than this limit, the mail is rejected. + If any non-whitelisted recipient has a filtering context with a non-zero + spamassassin limit, then the message is passed thru spamassassin (via + spamc), and the message is rejected for those recipients with spamassassin + limits less than the resulting spamassassin score. We also scan for excessive bad html tags, and if a <configurable> @@ -530,7 +531,7 @@ - 2007-07-26 + 2007-07-27