changeset 167:9b129ed78d7d stable-6-0-6

actually use spamassassin result, allow build without spam assassin, only call it if some recipient needs it.
author carl
date Mon, 27 Aug 2007 20:49:19 -0700
parents 7161d8451fcf
children 6bac960af6b4
files ChangeLog NEWS configure.in dnsbl.conf src/context.cpp src/context.h src/dnsbl.cpp src/dnsbl.h src/includes.h src/spamass.cpp.in src/spamass.h xml/dnsbl.in
diffstat 12 files changed, 101 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- 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.
 
--- 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.
--- 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
--- 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
 };
 
--- 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);
--- 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);
 };
 
 
--- 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 {
--- 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
--- 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"
--- 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!
--- 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 <list>
 
+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;
--- 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 @@
 
     <refentry id="@PACKAGE@.1">
         <refentryinfo>
-            <date>2007-07-26</date>
+            <date>2007-07-27</date>
         </refentryinfo>
 
         <refmeta>
@@ -375,9 +375,10 @@
                 ignore list, the mail is rejected.
             </para>
             <para>
-                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.
             </para>
             <para>
                 We also scan for excessive bad html tags, and if a &lt;configurable&gt;
@@ -530,7 +531,7 @@
 
     <refentry id="@PACKAGE@.conf.5">
         <refentryinfo>
-            <date>2007-07-26</date>
+            <date>2007-07-27</date>
         </refentryinfo>
 
         <refmeta>