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