[Exim] Re: Exiscan Patch - multiple spamd servers and/or vir…

Top Page
Delete this message
Reply to this message
Author: Dagfinn Ilmari Mannsåker
Date:  
To: exim-users
CC: exiscanusers
Subject: [Exim] Re: Exiscan Patch - multiple spamd servers and/or virus scanners
Zarjazz <zarjazz@???> writes:

> Hi.
>
> Attached is a patch against exiscan versions 4.30-14 or 4.30-15 to add
> the following two new features.

[...]
> *) Multiple virus (malware) scanners.
>
> For the really paranoid you can have the option to have multiple AV
> programs scan your mail. Just add the extra configuration options to
> your existing av_scanner line.
>
> Example:
>
> av_scanner = \
>         clamd:/var/run/clamav/clamd.sock:\
>         cmdline:/opt/kav/bin/aveclient -p /var/run/aveserver -s
> %s/*.eml:INFECTED:^LINFECTED (.+)

>
> - -----
>
> I have run both features on my own setup without any problems but I
> would appreciate any comments from anyone who could test on other systems.


I need the multiple anti-virus scanner functionality for a customer, and
a co-worker pointed me at this patch. The problem was it was totally
unreviewable due to including loads of irrelevant whitespace and
coding-style changes. I spent a few hours doing cycles of applying,
cleaning up, 'diff -w', lather, rinse, repeat, and here's the result for
the virus scanner part, rediffed against exiscan-acl-4.34-22.

The forward declarations are mainly for patch readability, feel free to
remove them and move the malware() function after the scan_*() functions
if you prefer that.

Also, the indentation and coding style is quite inconsistent, since
stuff has been written by different people, and I didn't reindent the
scanning functions after splitting them out. I'll follow-up with a
cleanup patch on top of this one.

--- exiscan-4.34-22/src/malware.c.orig    2004-06-18 20:33:47.000000000 +0200
+++ exiscan-4.34-22/src/malware.c    2004-06-19 00:47:44.000000000 +0200
@@ -39,6 +39,14 @@
 uschar malware_name_buffer[256];
 int malware_ok = 0;


+/* Forward declarations. */
+static int scan_drweb(uschar **pscanner, int *psep);
+static int scan_kavdaemon(uschar **pscanner, int *psep);
+static int scan_cmdline(uschar **pscanner, int *psep);
+static int scan_sophie(uschar **pscanner, int *psep);
+static int scan_clamd(uschar **pscanner, int *psep);
+static int scan_mksd(uschar **pscanner, int *psep);
+
int malware(uschar **listptr) {
int sep = 0;
uschar *list = *listptr;
@@ -100,21 +108,90 @@

   /* Do not scan twice. */
   if (malware_ok == 0) {
+    int rc, n = 0;


     /* find the scanner type from the av_scanner option */
-    if ((scanner_name = string_nextinlist(&av_scanner_work, &sep,
-                                          scanner_name_buffer,
-                                          sizeof(scanner_name_buffer))) == NULL) {
+    /* loop until we find a virus or reach end of list */
+    while (malware_name == NULL &&
+           (scanner_name = string_nextinlist(&av_scanner_work, &sep,
+                                             scanner_name_buffer,
+                                             sizeof(scanner_name_buffer))) != NULL) {
+      /* "drweb" scanner type ----------------------------------------------- */
+      if (strcmpic(scanner_name, US "drweb") == 0) {
+        rc = scan_drweb(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+      /* "kavdaemon" scanner type ------------------------------------------------ */
+      else if (strcmpic(scanner_name, US "kavdaemon") == 0) {
+        rc = scan_kavdaemon(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+
+      /* "cmdline" scanner type ------------------------------------------------ */
+      else if (strcmpic(scanner_name, US "cmdline") == 0) {
+        rc = scan_cmdline(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+
+      /* "sophie" scanner type ------------------------------------------------- */
+      else if (strcmpic(scanner_name, US "sophie") == 0) {
+        rc = scan_sophie(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+
+      /* "clamd" scanner type ------------------------------------------------- */
+      else if (strcmpic(scanner_name, US "clamd") == 0) {
+        rc = scan_clamd(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+
+      /* "mksd" scanner type --------------------------------------------------- */
+      else if (strcmpic(scanner_name, US "mksd") == 0) {
+        rc = scan_mksd(&av_scanner_work, &sep);
+        if (rc != OK)
+          return rc;
+      }
+
+      /* "unknown" scanner type ------------------------------------------------- */
+      else {
+        log_write(0, LOG_MAIN | LOG_PANIC,
+                  "malware condition: unknown scanner type '%s'", scanner_name);
+        return DEFER;
+      }
+      n++;
+    }
+
+    if (malware_name == NULL && n == 0) {
       /* no scanner given */
       log_write(0, LOG_MAIN|LOG_PANIC,
              "malware acl condition: av_scanner configuration variable is empty");
       return DEFER;
     };


+    /* set "been here, done that" marker */
+    malware_ok = 1;
+  };
+
+  /* match virus name against pattern (caseless ------->----------v) */
+  if ((malware_name != NULL) &&
+      (regex_match_and_setup(re, malware_name, 0, -1))) {
+    return OK;
+  }
+  else {
+    return FAIL;
+  };
+}
+
     /* "drweb" scanner type ----------------------------------------------- */
     /* v0.1 - added support for tcp sockets                    */
     /* v0.0 - initial release -- support for unix sockets            */
-    if (strcmpic(scanner_name,US"drweb") == 0) {
+static int scan_drweb(uschar ** pscanner, int *psep)
+{
         uschar *drweb_options;
         uschar drweb_options_buffer[1024];
         uschar drweb_options_default[] = "/usr/local/drweb/run/drwebd.sock";
@@ -131,8 +208,10 @@
         struct hostent *he;
         struct in_addr in;
         pcre *drweb_re;
+            int roffset;
+        uschar *rerror;


-        if ((drweb_options = string_nextinlist(&av_scanner_work, &sep,
+        if ((drweb_options = string_nextinlist(pscanner, psep,
             drweb_options_buffer, sizeof(drweb_options_buffer))) == NULL) {
             /* no options supplied, use default options */
             drweb_options = drweb_options_default;
@@ -355,11 +434,12 @@
             malware_name = NULL;
         };
         close(sock);
-    }
-    /* ----------------------------------------------------------------------- */
+    return OK;
+}


     /* "kavdaemon" scanner type ------------------------------------------------ */
-    else if (strcmpic(scanner_name,US"kavdaemon") == 0) {
+static int scan_kavdaemon(uschar ** pscanner, int *psep)
+{
       uschar *kav_options;
       uschar kav_options_buffer[1024];
       uschar kav_options_default[] = "/var/run/AvpCtl";
@@ -372,8 +452,10 @@
       int kav_rc;
       unsigned long kav_reportlen, bread;
       pcre *kav_re;
+      int roffset;
+      uschar *rerror;


-      if ((kav_options = string_nextinlist(&av_scanner_work, &sep,
+      if ((kav_options = string_nextinlist(pscanner, psep,
                                            kav_options_buffer,
                                            sizeof(kav_options_buffer))) == NULL) {
         /* no options supplied, use default options */
@@ -520,12 +602,12 @@
       };


       close(sock);
-    }
-    /* ----------------------------------------------------------------------- */
-
+      return OK;
+}


     /* "cmdline" scanner type ------------------------------------------------ */
-    else if (strcmpic(scanner_name,US"cmdline") == 0) {
+static int scan_cmdline(uschar ** pscanner, int *psep)
+{
       uschar *cmdline_scanner;
       uschar cmdline_scanner_buffer[1024];
       uschar *cmdline_trigger;
@@ -544,9 +626,11 @@
       int trigger = 0;
       int result;
       int ovector[30];
+      int roffset;
+      const uschar *rerror;


       /* find scanner command line */
-      if ((cmdline_scanner = string_nextinlist(&av_scanner_work, &sep,
+      if ((cmdline_scanner = string_nextinlist(pscanner, psep,
                                           cmdline_scanner_buffer,
                                           sizeof(cmdline_scanner_buffer))) == NULL) {
         /* no command line supplied */
@@ -556,7 +640,7 @@
       };


       /* find scanner output trigger */
-      if ((cmdline_trigger = string_nextinlist(&av_scanner_work, &sep,
+      if ((cmdline_trigger = string_nextinlist(pscanner, psep,
                                           cmdline_trigger_buffer,
                                           sizeof(cmdline_trigger_buffer))) == NULL) {
         /* no trigger regex supplied */
@@ -574,7 +658,7 @@
       };


       /* find scanner name regex */
-      if ((cmdline_regex = string_nextinlist(&av_scanner_work, &sep,
+      if ((cmdline_regex = string_nextinlist(pscanner, psep,
                                              cmdline_regex_buffer,
                                              sizeof(cmdline_regex_buffer))) == NULL) {
         /* no name regex supplied */
@@ -663,12 +747,12 @@
         /* no virus found */
         malware_name = NULL;
       };
-    }
-    /* ----------------------------------------------------------------------- */
-
+      return OK;
+}


     /* "sophie" scanner type ------------------------------------------------- */
-    else if (strcmpic(scanner_name,US"sophie") == 0) {
+static int scan_sophie(uschar ** pscanner, int *psep)
+{
       uschar *sophie_options;
       uschar sophie_options_buffer[1024];
       uschar sophie_options_default[] = "/var/run/sophie";
@@ -678,7 +762,7 @@
       uschar file_name[1024];
       uschar av_buffer[1024];


-      if ((sophie_options = string_nextinlist(&av_scanner_work, &sep,
+      if ((sophie_options = string_nextinlist(pscanner, psep,
                                           sophie_options_buffer,
                                           sizeof(sophie_options_buffer))) == NULL) {
         /* no options supplied, use default options */
@@ -738,13 +822,13 @@
         /* all ok, no virus */
         malware_name = NULL;
       };
-    }
-    /* ----------------------------------------------------------------------- */
-
+      return OK;
+}


     /* "clamd" scanner type ------------------------------------------------- */
     /* This code was contributed by David Saez <david@???> */
-    else if (strcmpic(scanner_name,US"clamd") == 0) {
+static int scan_clamd(uschar ** pscanner, int *psep)
+{
       uschar *clamd_options;
       uschar clamd_options_buffer[1024];
       uschar clamd_options_default[] = "/tmp/clamd";
@@ -757,7 +841,7 @@
       struct hostent *he;
       struct in_addr in;


-      if ((clamd_options = string_nextinlist(&av_scanner_work, &sep,
+      if ((clamd_options = string_nextinlist(pscanner, psep,
                                              clamd_options_buffer,
                                              sizeof(clamd_options_buffer))) == NULL) {
         /* no options supplied, use default options */
@@ -907,12 +991,12 @@
               malware_name = NULL;
            }
       }
-    }
-    /* ----------------------------------------------------------------------- */
-
+    return OK;
+}


     /* "mksd" scanner type --------------------------------------------------- */
-    else if (strcmpic(scanner_name,US"mksd") == 0) {
+static int scan_mksd(uschar ** pscanner, int *psep)
+{
       uschar *mksd_options;
       char *mksd_options_end;
       uschar mksd_options_buffer[32];
@@ -921,7 +1005,7 @@
       int sock;
       int retval;


-      if ((mksd_options = string_nextinlist(&av_scanner_work, &sep,
+      if ((mksd_options = string_nextinlist(pscanner, psep,
                                             mksd_options_buffer,
                                             sizeof(mksd_options_buffer))) != NULL) {
         mksd_maxproc = (int) strtol(CS mksd_options, &mksd_options_end, 10);
@@ -958,31 +1042,8 @@


       if (retval != OK)
         return retval;
-    }
-    /* ----------------------------------------------------------------------- */
-
-
-
-    /* "unknown" scanner type ------------------------------------------------- */
-    else {
-      log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware condition: unknown scanner type '%s'", scanner_name);
-      return DEFER;
-    };
-    /* ----------------------------------------------------------------------- */


-    /* set "been here, done that" marker */
-    malware_ok = 1;
-  };
-
-  /* match virus name against pattern (caseless ------->----------v) */
-  if ( (malware_name != NULL) &&
-       (regex_match_and_setup(re, malware_name, 0, -1)) ) {
     return OK;
-  }
-  else {
-    return FAIL;
-  };
 }


/* ============= private routines for the "mksd" scanner type ============== */

--
ilmari