They are not recognized because their headers are mxed up a bit. For instance the messages can start with Date: or To: or any other header not recognized by the magic scan routine.
These messages were infected by viruses that clamscan detects after using munpack on them.
The messages all had a X-Scanned by clamav-milter header.
clamav-milter currently sends a pseudo "Received:" header to clamd, presumably this should force RFC822/Mbox processing.
Since I cant currently tell why amavis-milter/amavisd/uvscan catches them and clamav didnt, this patch will allow me to remove the uncertainty involved.
This patch
* updates libclamav to recognize a new option CL_UNKNOWN_MAIL which will treat the file as RFC822 if unrecognized.
* updates clamscan to recognize these new command line arguments (all equivalent) --mbox-force or --mail or -M which turns on above behavior.
* updates clamd to recognize new commands designed to ask for this behavior. MAILSCAN, CONTMAILSCAN, MAILSTREAM.
* updates clamd to recognize new configuration option "ScanUnknownAsMail" designed to ask for this behavior as a default.
* updates clamdscan to recognize the new command line arguments and use the above commands to clamd.
* updates clamav-milter to use the MAILSTREAM or MAILSCAN commands to clamd.
Some notes:
- clamd will reject with unknown command the new verbs if ScanMail is not in the config file.
- clamdscan will not use the new verbs if ScanMail is not in the config file.
- clamscan will treat the new arguments as implying -m (--mbox).
Its been 30 hours since and not a single new one of those messages has appeared with this patch.
Patches are on http://www.jmaimon.com/clamav
Attached are patches for 0.70 and clamav-devel
Joe
diff -ur clamav-devel-jm5/clamav-milter/clamav-milter.c
clamav-devel-jm4/clamav-milter/clamav-milter.c
--- clamav-devel-jm5/clamav-milter/clamav-milter.c Fri Apr 23 17:07:42 2004
+++ clamav-devel-jm4/clamav-milter/clamav-milter.c Fri Apr 23 17:16:38 2004
@@ -2083,7 +2083,7 @@
return cl_error;
}
- snprintf(cmdbuf, sizeof(cmdbuf) - 1, "SCAN %s", privdata->filename);
+ snprintf(cmdbuf, sizeof(cmdbuf) - 1, "MAILSCAN %s",
privdata->filename);
nbytes = (int)strlen(cmdbuf);
@@ -2894,7 +2894,7 @@
shutdown(privdata->dataSocket, SHUT_RD);
- if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) {
+ if(send(privdata->cmdSocket, "MAILSTREAM\n", 11, 0) < 7) {
perror("send");
if(use_syslog)
syslog(LOG_ERR, "send failed to clamd");
diff -ur clamav-devel-jm5/clamd/session.c clamav-devel-jm4/clamd/session.c
--- clamav-devel-jm5/clamd/session.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamd/session.c Fri Apr 23 17:16:38 2004
@@ -54,6 +54,9 @@
#define CMD9 "SESSION"
#define CMD10 "END"
#define CMD11 "SHUTDOWN"
+#define CMD12 "MAILSTREAM"
+#define CMD13 "MAILSCAN"
+#define CMD14 "CONTMAILSCAN"
int command(int desc, const struct cl_node *root, const struct cl_limits *limits, int
options, const struct cfgstruct *copt)
@@ -150,6 +153,27 @@
} else if(!strncmp(buff, CMD11, strlen(CMD11))) { /* SHUTDOWN */
return COMMAND_QUIT;
+ } else if(!strncmp(buff, CMD12, strlen(CMD12))) { /* MAILSTREAM */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scanstream(desc, NULL, root, limits, options, copt);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
+ } else if(!strncmp(buff, CMD13, strlen(CMD13))) { /* MAILSCAN */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scan(buff + strlen(CMD13) + 1, NULL, root, limits, options, copt, desc, 0);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
+ } else if(!strncmp(buff, CMD14, strlen(CMD14))) { /* CONTMAILSCAN */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scan(buff + strlen(CMD14) + 1, NULL, root, limits, options, copt, desc, 1);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
} else {
mdprintf(desc, "UNKNOWN COMMAND\n");
}
diff -ur clamav-devel-jm5/clamdscan/clamdscan.c clamav-devel-jm4/clamdscan/clamdscan.c
--- clamav-devel-jm5/clamdscan/clamdscan.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamdscan/clamdscan.c Fri Apr 23 17:16:38 2004
@@ -126,6 +126,8 @@
mprintf(" --verbose -v Be verbose\n");
mprintf(" --quiet Be quiet, only output error
messages\n");
mprintf(" --stdout Write to stdout instead of
stderr\n");
+ mprintf(" --mail, --mbox-force, -M All unknown file type will be a
RFC822 mail file\n");
+ mprintf(" --stdout Write to stdout instead of
stderr\n");
mprintf(" (this help is always written to
stdout)\n");
mprintf(" --log=FILE -l FILE Save scan report in FILE\n");
mprintf(" --log-verbose Log additional messages\n");
diff -ur clamav-devel-jm5/clamdscan/client.c clamav-devel-jm4/clamdscan/client.c
--- clamav-devel-jm5/clamdscan/client.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamdscan/client.c Fri Apr 23 17:16:38 2004
@@ -55,6 +55,7 @@
int sockd, wsockd, loopw = 60, bread, port;
const char *clamav_conf = getargl(opt, "config-file");
FILE *fd;
+ short unknown_mail = 0;
if(!clamav_conf)
clamav_conf = DEFAULT_CFG;
@@ -64,6 +65,15 @@
return 2;
}
+ if((cfgopt(copt, "ScanMail")) &&
+ (
+ (optl(opt, "mbox-force")) ||
+ (optl(opt, "mail")) ||
+ (optc(opt, 'M'))
+ )
+ )
+ unknown_mail = 1;
+
/* Set default address to connect to; needed for scanning a stream and no TCP
address specified */
server2.sin_addr.s_addr = inet_addr("127.0.0.1");
if(cfgopt(copt, "ScannerDaemonOutputFormat")) {
@@ -137,7 +147,7 @@
file = (char *) strdup(cwd);
} else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */
- if(write(sockd, "STREAM", 6) <= 0) {
+ if(write(sockd, (unknown_mail) ? "MAILSTREAM" : "STREAM", (unknown_mail) ? 10
: 6) <= 0) {
mprintf("@Can't write to the socket.\n");
close(sockd);
return 2;
@@ -229,7 +239,7 @@
scancmd = mcalloc(strlen(file) + 20, sizeof(char));
- sprintf(scancmd, "CONTSCAN %s", file);
+ sprintf(scancmd, "%s %s", (unknown_mail)? "CONTMAILSCAN" : "CONTSCAN", file);
free(file);
if(write(sockd, scancmd, strlen(scancmd)) <= 0) {
diff -ur clamav-devel-jm5/clamscan/clamscan.c clamav-devel-jm4/clamscan/clamscan.c
--- clamav-devel-jm5/clamscan/clamscan.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamscan/clamscan.c Fri Apr 23 17:16:38 2004
@@ -208,6 +208,10 @@
mprintf(" --bell Sound bell on virus
detection\n");
mprintf(" --no-summary Disable summary at end of
scanning\n");
mprintf(" --mbox -m Treat stdin as a mailbox\n");
+ mprintf(" --mbox-force -M\n");
+ mprintf(" --mail -M Unrecognized filetypes will be
be treated\n");
+ mprintf(" as RFC822 mail file.\n");
+ mprintf(" This implies --mbox (-m)\n");
mprintf("\n");
mprintf(" --no-ole2 Disable OLE2 support\n");
mprintf(" --no-archive Disable libclamav archive
support\n");
diff -ur clamav-devel-jm5/clamscan/manager.c clamav-devel-jm4/clamscan/manager.c
--- clamav-devel-jm5/clamscan/manager.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamscan/manager.c Fri Apr 23 17:16:38 2004
@@ -373,6 +373,12 @@
if(optc(opt, 'm'))
options |= CL_MAIL;
+ if(optc(opt, 'M') || optl(opt,"mail")) {
+ options |= CL_MAIL;
+ options |= CL_UNKNOWN_MAIL;
+ }
+
+
/*
* check the extension - this is a special case, normally we don't need to
* do this (libclamav detects archive by its magic string), but here we
diff -ur clamav-devel-jm5/clamscan/options.c clamav-devel-jm4/clamscan/options.c
--- clamav-devel-jm5/clamscan/options.c Fri Apr 23 17:07:43 2004
+++ clamav-devel-jm4/clamscan/options.c Fri Apr 23 17:16:38 2004
@@ -43,7 +43,7 @@
int ret, opt_index, i, len;
struct optstruct *opt;
- const char *getopt_parameters = "hvd:wriVl:m";
+ const char *getopt_parameters = "hvd:wriVl:mM";
static struct option long_options[] = {
/*
@@ -82,6 +82,8 @@
{"block-encrypted", 0, 0, 0},
{"no-ole2", 0, 0, 0},
{"mbox", 0, 0, 'm'},
+ {"mbox-force", 0, 0, 'M'},
+ {"mail", 0, 0, 0},
{"stdout", 0, 0, 0},
{"unzip", 2, 0, 0},
{"unrar", 2, 0, 0},
diff -ur clamav-devel-jm5/libclamav/clamav.h clamav-devel-jm4/libclamav/clamav.h
--- clamav-devel-jm5/libclamav/clamav.h Fri Apr 23 17:07:46 2004
+++ clamav-devel-jm4/libclamav/clamav.h Fri Apr 23 17:16:38 2004
@@ -69,6 +69,7 @@
#define CL_DISABLERAR 4
#define CL_OLE2 8
#define CL_ENCRYPTED 16
+#define CL_UNKNOWN_MAIL 32
struct cli_patt {
short int *pattern;
diff -ur clamav-devel-jm5/libclamav/scanners.c clamav-devel-jm4/libclamav/scanners.c
--- clamav-devel-jm5/libclamav/scanners.c Fri Apr 23 17:07:46 2004
+++ clamav-devel-jm4/libclamav/scanners.c Fri Apr 23 17:16:38 2004
@@ -58,6 +58,7 @@
#define SCAN_OLE2 (options & CL_OLE2)
#define DISABLE_RAR (options & CL_DISABLERAR)
#define DETECT_ENCRYPTED (options & CL_ENCRYPTED)
+#define SCAN_UNKNOWN_MAIL (options & CL_UNKNOWN_MAIL)
struct cli_magic_s {
int offset;
@@ -882,6 +883,9 @@
}
type = cli_filetype(magic, bread);
+
+ if(type == CL_UNKNOWN_TYPE && SCAN_UNKNOWN_MAIL)
+ type = CL_MAILFILE;
switch(type) {
case CL_RARFILE:
diff -ur clamav-devel-jm5/shared/cfgparser.c clamav-devel-jm4/shared/cfgparser.c
--- clamav-devel-jm5/shared/cfgparser.c Fri Apr 23 17:07:46 2004
+++ clamav-devel-jm4/shared/cfgparser.c Fri Apr 23 17:16:38 2004
@@ -62,6 +62,7 @@
{"TemporaryDirectory", OPT_STR},
{"MaxFileSize", OPT_COMPSIZE},
{"ScanMail", OPT_NOARG},
+ {"ScanUnknownAsMail", OPT_NOARG},
{"ScanOLE2", OPT_NOARG},
{"ScanArchive", OPT_NOARG},
{"ScanRAR", OPT_NOARG},
diff -urwN clamav-0.70-orig/clamav-milter/clamav-milter.c
clamav-0.70-virus-skips/clamav-milter/clamav-milter.c
--- clamav-0.70-orig/clamav-milter/clamav-milter.c Thu Apr 15 10:24:32 2004
+++ clamav-0.70-virus-skips/clamav-milter/clamav-milter.c Fri Apr 23 14:50:10
2004
@@ -1947,7 +1947,7 @@
return cl_error;
}
- snprintf(cmdbuf, sizeof(cmdbuf) - 1, "SCAN %s", privdata->filename);
+ snprintf(cmdbuf, sizeof(cmdbuf) - 1, "MAILSCAN %s",
privdata->filename);
nbytes = (int)strlen(cmdbuf);
@@ -2662,7 +2662,7 @@
shutdown(privdata->dataSocket, SHUT_RD);
- if(send(privdata->cmdSocket, "STREAM\n", 7, 0) < 7) {
+ if(send(privdata->cmdSocket, "MAILSTREAM\n", 11, 0) < 7) {
perror("send");
if(use_syslog)
syslog(LOG_ERR, "send failed to clamd");
diff -urwN clamav-0.70-orig/clamd/session.c clamav-0.70-virus-skips/clamd/session.c
--- clamav-0.70-orig/clamd/session.c Mon Mar 29 11:09:15 2004
+++ clamav-0.70-virus-skips/clamd/session.c Fri Apr 23 14:52:37 2004
@@ -54,6 +54,9 @@
#define CMD9 "SESSION"
#define CMD10 "END"
#define CMD11 "SHUTDOWN"
+#define CMD12 "MAILSTREAM"
+#define CMD13 "MAILSCAN"
+#define CMD14 "CONTMAILSCAN"
int command(int desc, const struct cl_node *root, const struct cl_limits *limits, int
options, const struct cfgstruct *copt)
@@ -150,6 +153,27 @@
} else if(!strncmp(buff, CMD11, strlen(CMD11))) { /* SHUTDOWN */
return COMMAND_QUIT;
+ } else if(!strncmp(buff, CMD12, strlen(CMD12))) { /* MAILSTREAM */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scanstream(desc, NULL, root, limits, options, copt);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
+ } else if(!strncmp(buff, CMD13, strlen(CMD13))) { /* MAILSCAN */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scan(buff + strlen(CMD13) + 1, NULL, root, limits, options, copt, desc, 0);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
+ } else if(!strncmp(buff, CMD14, strlen(CMD14))) { /* CONTMAILSCAN */
+ if((cpt = cfgopt(copt,"ScanMail"))) {
+ options |= CL_UNKNOWN_MAIL;
+ scan(buff + strlen(CMD14) + 1, NULL, root, limits, options, copt, desc, 1);
+ } else {
+ mdprintf(desc, "UNKNOWN COMMAND\n");
+ }
} else {
mdprintf(desc, "UNKNOWN COMMAND\n");
}
diff -urwN clamav-0.70-orig/clamdscan/clamdscan.c
clamav-0.70-virus-skips/clamdscan/clamdscan.c
--- clamav-0.70-orig/clamdscan/clamdscan.c Sat Apr 10 18:55:45 2004
+++ clamav-0.70-virus-skips/clamdscan/clamdscan.c Fri Apr 23 12:38:24 2004
@@ -126,6 +126,8 @@
mprintf(" --verbose -v Be verbose\n");
mprintf(" --quiet Be quiet, only output error
messages\n");
mprintf(" --stdout Write to stdout instead of
stderr\n");
+ mprintf(" --mail, --mbox-force, -M All unknown file type will be a
RFC822 mail file\n");
+ mprintf(" --stdout Write to stdout instead of
stderr\n");
mprintf(" (this help is always written to
stdout)\n");
mprintf(" --log=FILE -l FILE Save scan report in FILE\n");
mprintf(" --log-verbose Log additional messages\n");
diff -urwN clamav-0.70-orig/clamdscan/client.c
clamav-0.70-virus-skips/clamdscan/client.c
--- clamav-0.70-orig/clamdscan/client.c Tue Apr 6 18:38:40 2004
+++ clamav-0.70-virus-skips/clamdscan/client.c Fri Apr 23 14:52:17 2004
@@ -55,6 +55,7 @@
int sockd, wsockd, loopw = 60, bread, port;
const char *clamav_conf = getargl(opt, "config-file");
FILE *fd;
+ short unknown_mail = 0;
if(!clamav_conf)
clamav_conf = DEFAULT_CFG;
@@ -64,6 +65,15 @@
return 2;
}
+ if((cfgopt(copt, "ScanMail")) &&
+ (
+ (optl(opt, "mbox-force")) ||
+ (optl(opt, "mail")) ||
+ (optc(opt, 'M'))
+ )
+ )
+ unknown_mail = 1;
+
/* Set default address to connect to; needed for scanning a stream and no TCP
address specified */
server2.sin_addr.s_addr = inet_addr("127.0.0.1");
if(cfgopt(copt, "ScannerDaemonOutputFormat")) {
@@ -137,7 +147,7 @@
file = (char *) strdup(cwd);
} else if(!strcmp(opt->filename, "-")) { /* scan data from stdin */
- if(write(sockd, "STREAM", 6) <= 0) {
+ if(write(sockd, (unknown_mail) ? "MAILSTREAM" : "STREAM", (unknown_mail) ? 10
: 6) <= 0) {
mprintf("@Can't write to the socket.\n");
close(sockd);
return 2;
@@ -229,7 +239,7 @@
scancmd = mcalloc(strlen(file) + 20, sizeof(char));
- sprintf(scancmd, "CONTSCAN %s", file);
+ sprintf(scancmd, "%s %s", (unknown_mail)? "CONTMAILSCAN" : "CONTSCAN", file);
free(file);
if(write(sockd, scancmd, strlen(scancmd)) <= 0) {
diff -urwN clamav-0.70-orig/clamscan/clamscan.c
clamav-0.70-virus-skips/clamscan/clamscan.c
--- clamav-0.70-orig/clamscan/clamscan.c Fri Apr 16 11:26:18 2004
+++ clamav-0.70-virus-skips/clamscan/clamscan.c Fri Apr 23 12:37:51 2004
@@ -208,6 +208,10 @@
mprintf(" --bell Sound bell on virus
detection\n");
mprintf(" --no-summary Disable summary at end of
scanning\n");
mprintf(" --mbox -m Treat stdin as a mailbox\n");
+ mprintf(" --mbox-force -M\n");
+ mprintf(" --mail -M Unrecognized filetypes will be
be treated\n");
+ mprintf(" as RFC822 mail file.\n");
+ mprintf(" This implies --mbox (-m)\n");
mprintf("\n");
mprintf(" --no-ole2 Disable OLE2 support\n");
mprintf(" --no-archive Disable libclamav archive
support\n");
diff -urwN clamav-0.70-orig/clamscan/manager.c
clamav-0.70-virus-skips/clamscan/manager.c
--- clamav-0.70-orig/clamscan/manager.c Fri Apr 16 11:26:54 2004
+++ clamav-0.70-virus-skips/clamscan/manager.c Fri Apr 23 14:46:15 2004
@@ -369,6 +369,12 @@
if(optc(opt, 'm'))
options |= CL_MAIL;
+ if(optc(opt, 'M') || optl(opt,"mail")) {
+ options |= CL_MAIL;
+ options |= CL_UNKNOWN_MAIL;
+ }
+
+
/*
* check the extension - this is a special case, normally we don't need to
* do this (libclamav detects archive by its magic string), but here we
diff -urwN clamav-0.70-orig/clamscan/options.c
clamav-0.70-virus-skips/clamscan/options.c
--- clamav-0.70-orig/clamscan/options.c Fri Apr 16 11:30:35 2004
+++ clamav-0.70-virus-skips/clamscan/options.c Fri Apr 23 10:32:38 2004
@@ -43,7 +43,7 @@
int ret, opt_index, i, len;
struct optstruct *opt;
- const char *getopt_parameters = "hvd:wriVl:m";
+ const char *getopt_parameters = "hvd:wriVl:mM";
static struct option long_options[] = {
/*
@@ -81,6 +81,8 @@
{"block-encrypted", 0, 0, 0},
{"no-ole2", 0, 0, 0},
{"mbox", 0, 0, 'm'},
+ {"mbox-force", 0, 0, 'M'},
+ {"mail", 0, 0, 0},
{"stdout", 0, 0, 0},
{"unzip", 2, 0, 0},
{"unrar", 2, 0, 0},
diff -urwN clamav-0.70-orig/libclamav/clamav.h
clamav-0.70-virus-skips/libclamav/clamav.h
--- clamav-0.70-orig/libclamav/clamav.h Wed Mar 31 02:03:35 2004
+++ clamav-0.70-virus-skips/libclamav/clamav.h Fri Apr 23 14:41:22 2004
@@ -69,6 +69,7 @@
#define CL_DISABLERAR 4
#define CL_OLE2 8
#define CL_ENCRYPTED 16
+#define CL_UNKNOWN_MAIL 32
struct cli_patt {
short int *pattern;
diff -urwN clamav-0.70-orig/libclamav/scanners.c
clamav-0.70-virus-skips/libclamav/scanners.c
--- clamav-0.70-orig/libclamav/scanners.c Fri Apr 16 08:12:09 2004
+++ clamav-0.70-virus-skips/libclamav/scanners.c Fri Apr 23 14:42:12 2004
@@ -58,6 +58,7 @@
#define SCAN_OLE2 (options & CL_OLE2)
#define DISABLE_RAR (options & CL_DISABLERAR)
#define DETECT_ENCRYPTED (options & CL_ENCRYPTED)
+#define SCAN_UNKNOWN_MAIL (options & CL_UNKNOWN_MAIL)
struct cli_magic_s {
int offset;
@@ -822,6 +823,10 @@
}
type = cli_filetype(magic, bread);
+
+ if(type == CL_UNKNOWN_TYPE && SCAN_UNKNOWN_MAIL)
+ type = CL_MAILFILE;
+
switch(type) {
case CL_RARFILE:
diff -urwN clamav-0.70-orig/shared/cfgparser.c
clamav-0.70-virus-skips/shared/cfgparser.c
--- clamav-0.70-orig/shared/cfgparser.c Fri Apr 16 11:25:02 2004
+++ clamav-0.70-virus-skips/shared/cfgparser.c Fri Apr 23 14:31:31 2004
@@ -62,6 +62,7 @@
{"TemporaryDirectory", OPT_STR},
{"MaxFileSize", OPT_COMPSIZE},
{"ScanMail", OPT_NOARG},
+ {"ScanUnknownAsMail", OPT_NOARG},
{"ScanOLE2", OPT_NOARG},
{"ScanArchive", OPT_NOARG},
{"ScanRAR", OPT_NOARG},
