sa-exim (4.2.1-13) sa-exim.c

Summary

 sa-exim.c |   79 +++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 53 insertions(+), 26 deletions(-)

    
download this patch

Patch contents

--- sa-exim-4.2.1.orig/sa-exim.c
+++ sa-exim-4.2.1/sa-exim.c
@@ -29,10 +29,8 @@
 #include "sa-exim.h"
 
 /* Exim includes */
-#include "local_scan.h"
-extern FILE   *smtp_out;               /* Exim's incoming SMTP output file */
-extern int     body_linecount;         /* Line count in body */
-extern uschar *primary_hostname;
+#include <local_scan.h>
+//extern int     body_linecount;         /* Line count in body */
 
 #ifdef DLOPEN_LOCAL_SCAN
 
@@ -515,6 +513,7 @@
     int pid;
     int writefd[2];
     int readfd[2];
+    char *spamc_argv[10];
     int i;
     /* These are the only values that we want working after the longjmp 
      * The automatic ones can be clobbered, but we don't really care */
@@ -552,6 +551,7 @@
     static char *SAspamcSockPath=NULL;
     static char *SAspamcPort="783";
     static char *SAspamcHost="127.0.0.1";
+    static char *SAspamcUser=NULL;
     static char *SAEximRunCond="0";
     static char *SAEximRejCond="1";
     static int SAmaxbody=250*1024;
@@ -602,6 +602,15 @@
     /* Do not put a %s in there, or you'll segfault */
     static char *SAmsgerror="Temporary local error while processing message, please contact postmaster";
 
+    /* This needs to be retrieved through expand_string in order
+       not to violate the API. */
+    static uschar *primary_hostname;
+    if (!primary_hostname) {
+        store_pool = POOL_PERM;
+        primary_hostname = expand_string("$primary_hostname");
+        store_pool = POOL_MAIN;
+    }
+
     /* New values we read from spamassassin */
     char *xspamstatus=NULL;
     char *xspamflag=NULL;
@@ -712,6 +721,7 @@
 	    M_CHECKFORSTR(SAspamcSockPath);
 	    M_CHECKFORSTR(SAspamcPort);
 	    M_CHECKFORSTR(SAspamcHost);
+	    M_CHECKFORSTR(SAspamcUser);
 	    M_CHECKFORSTR(SAEximRunCond);
 	    M_CHECKFORSTR(SAEximRejCond);
 	    M_CHECKFORVAR(SAmaxbody, "%d");
@@ -914,6 +924,22 @@
 	ret=dup2(readfd[1],2);
 	CHECKERR(ret,"dup2 stderr",__LINE__);
 
+	i = 0;
+	spamc_argv[i++] = "spamc";
+	if (SAspamcUser && SAspamcUser[0])
+	{
+	    expand=expand_string(SAspamcUser);
+	    if (expand == NULL)
+	    {
+		log_write(0, LOG_MAIN | LOG_PANIC, "SA: SAspamcUser expansion failure on %s, will run as Exim user instead.", SAspamcUser);
+	    }
+	    else if (expand[0] != '\0')
+	    {
+		spamc_argv[i++] = "-u";
+		spamc_argv[i++] = expand;
+	    }
+	}
+
 	/* 
          * I could implement the spamc protocol and talk to spamd directly
          * instead of forking spamc, but considering the overhead spent
@@ -924,17 +950,26 @@
 	/* Ok, we cheat, spamc cares about how big the whole message is and
          * we only know about the body size, so I'll  give an extra 16K
          * to account for any headers that can accompany the message */
+
+	spamc_argv[i++] = "-s";
+	spamc_argv[i++] = string_sprintf("%d", SAmaxbody+16384);
+
 	if(SAspamcSockPath)
 	{
-	    ret=execl(SAspamcpath, "spamc", "-s", string_sprintf("%d", SAmaxbody+16384), "-U", SAspamcSockPath, NULL);
-	    CHECKERR(ret,string_sprintf("exec %s", SAspamcpath),__LINE__);
+    	    spamc_argv[i++] = "-U";
+	    spamc_argv[i++] = SAspamcSockPath;
 	}
 	else
 	{
-	    ret=execl(SAspamcpath, "spamc", "-s", string_sprintf("%d", SAmaxbody+16384), "-d", SAspamcHost, "-p", SAspamcPort, NULL);
-	    CHECKERR(ret,string_sprintf("exec %s", SAspamcpath),__LINE__);
+    	    spamc_argv[i++] = "-d";
+	    spamc_argv[i++] = SAspamcHost;
+    	    spamc_argv[i++] = "-p";
+	    spamc_argv[i++] = SAspamcPort;
 	}
-	
+	spamc_argv[i++] = NULL;
+
+	ret=execv(SAspamcpath, spamc_argv);
+	CHECKERR(ret,string_sprintf("exec %s", SAspamcpath),__LINE__);
     }
 
     if (SAEximDebug > 8)
@@ -1229,18 +1264,19 @@
 	    }
 	}
 
-	if (SAEximDebug > 1)
+/*	if (SAEximDebug > 1)
 	{
 	    log_write(0, LOG_MAIN, "SA: Debug2: body_linecount before SA: %d", body_linecount);
 	}
-
+*/
 	/* update global variable $body_linecount to reflect the new body size*/
-	body_linecount = (line - 1);
+/*	body_linecount = (line - 1);
 
 	if (SAEximDebug > 1)
 	{
 	    log_write(0, LOG_MAIN, "SA: Debug2: body_linecount after SA: %d", body_linecount);
 	}
+*/
     }
 
     fclose((FILE *)readfh);
@@ -1331,6 +1367,9 @@
 	
 	if (dorej && doteergrube)
 	{
+	    char *teergrubewaitstr;
+	    teergrubewaitstr=string_sprintf(SAmsgteergrubewait, spamstatus);
+
 	    /* By default, we'll only save temp bounces by message ID so
 	     * that when the same message is submitted several times, we
 	     * overwrite the same file on disk and not create a brand new
@@ -1353,20 +1392,8 @@
 
 	    for (i=0;i<SAteergrubetime/10;i++)
 	    {
-		char *str;
-		
-		/* Unfortunately, we can't use exim's smtp_printf because it
-		 * doesn't return an error code if the write gets an EPIPE.
-		 * So, we write ourselves, but this won't work if you have a
-		 * TLS connection opened (that said, if you are teergrubing
-		 * a TLS connection, it's probably a relay host, not a
-		 * spammer, and in this case you should not teergrube a
-		 * friendly relay, so basically we should be ok).
-		 * If you do teergrube an SSL connection with the current
-		 * code, you will break it, but that's acceptable */
-		str=string_sprintf(string_sprintf("451- %s\r\n",SAmsgteergrubewait), spamstatus);
-		fprintf(smtp_out, str);
-		ret=fflush(smtp_out);
+		smtp_printf("451-%s\r\n", teergrubewaitstr);
+		ret=smtp_fflush();
 		if (ret != 0)
 		{
 		    log_write(0, LOG_MAIN | LOG_REJECT, "SA: Action: teergrubed sender for %d secs until it closed the connection: %s (scanned in %d/%d secs | Message-Id: %s). %s", i*10, spamstatus, scantime, fulltime, safemesgid, mailinfo);