From eb445b049c9b78cbe187b9cb3c318d65862d4851 Mon Sep 17 00:00:00 2001 From: "Heiko Schlittermann (HS12-RIPE)" Date: Mon, 2 Apr 2018 17:39:39 +0200 Subject: [PATCH] Avast: implement pass_unscanned option --- doc/doc-docbook/spec.xfpt | 29 ++++++----- doc/doc-txt/ChangeLog | 10 ++-- doc/doc-txt/NewStuff | 4 ++ src/src/malware.c | 30 +++++++----- test/log/4017 | 12 +++-- test/rejectlog/4017 | 12 +++++ test/scripts/4017_scan_avast_multiline/4017 | 54 +++++++++++++++++++++ test/stdout/4017 | 48 +++++++++++++++++- 8 files changed, 165 insertions(+), 34 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 6353e29fb..f455c9f0c 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -31858,9 +31858,7 @@ If the value of &%av_scanner%& starts with a dollar character, it is expanded before use. The usual list-parsing of the content (see &<>&) applies. The following scanner types are supported in this release, -.new though individual ones can be included or not at build time: -.wen .vlist .vitem &%avast%& @@ -31874,11 +31872,22 @@ which can be either a full path to a UNIX socket, or host and port specifiers separated by white space. The host may be a name or an IP address; the port is either a single number or a pair of numbers with a dash between. -Any further options are given, on separate lines, -to the daemon as options before the main scan command. +A list of options may follow. These options are interpreted on the +Exim's side of the malware scanner, or are given on separate lines to +the daemon as options before the main scan command. + +.new +.cindex &`pass_unscanned`& "avast" +If &`pass_unscanned`& +is set, any files the Avast scanner can't scan (e.g. +decompression bombs, or invalid archives) are considered clean. Use with +care. +.wen + For example: .code av_scanner = avast:/var/run/avast/scan.sock:FLAGS -fullfiles:SENSITIVITY -pup +av_scanner = avast:/var/run/avast/scan.sock:pass_unscanned:FLAGS -fullfiles:SENSITIVITY -pup av_scanner = avast:192.168.2.22 5036 .endd If you omit the argument, the default path @@ -31895,13 +31904,9 @@ $ socat UNIX:/var/run/avast/scan.sock STDIO: PACK .endd -A paniclog entry is logged and the message is deferred (except the -malware condition uses "defer_ok") if the scanner returns a tmpfail -(e.g. on license issues, or permission problems). If the scanner can't -scan a file for internal reasons (e.g. decompression bomb), this is -treated as an infection and malware_name is set to the error message. -We do this err on the safe side. - +If the scanner returns a temporary failure (e.g. license issues, or +permission problems), the message is deferred and a paniclog entry is +written. The usual &`defer_ok`& option is available. .vitem &%aveserver%& .cindex "virus scanners" "Kaspersky" @@ -31952,7 +31957,7 @@ av_scanner = clamd:192.0.2.3 1234 : 192.0.2.4 1234 If the value of av_scanner points to a UNIX socket file or contains the &`local`& option, then the ClamAV interface will pass a filename containing the data -to be scanned, which will should normally result in less I/O happening and be +to be scanned, which should normally result in less I/O happening and be more efficient. Normally in the TCP case, the data is streamed to ClamAV as Exim does not assume that there is a common filesystem with the remote host. diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 837b38083..a18c57e3c 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -190,11 +190,11 @@ JH/35 Cutthrough: for a final-dot response timeout (and nonunderstood responses) PP/02 DANE: add dane_require_tls_ciphers SMTP Transport option; if unset, tls_require_ciphers is used as before. -HS/03 Malware Avast: Better match the Avast multiline protocol. - Only tmpfails from the scanner are written to the paniclog, as - they may require admin intervention (permission denied, license - issues). Other scanner errors (like decompression bombs) do not - cause a paniclog entry. +HS/03 Malware Avast: Better match the Avast multiline protocol. Add + "pass_unscanned". Only tmpfails from the scanner are written to + the paniclog, as they may require admin intervention (permission + denied, license issues). Other scanner errors (like decompression + bombs) do not cause a paniclog entry. Exim version 4.90 diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 4bf04ec8d..ea190aafb 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -54,6 +54,10 @@ Version 4.91 the running exim instance. If the cluster has master/slave replication, the list must contain all the master and slave servers. +16. Add an option to the Avast scanner interface: "pass_unscanned". This + allows to treat unscanned files as clean. Files may be unscanned for + several reasons: decompression bombs, broken archives. + Version 4.90 ------------ diff --git a/src/src/malware.c b/src/src/malware.c index 7c57c0090..730a2be22 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -1921,13 +1921,14 @@ b_seek: err = errno; #ifndef DISABLE_MAL_AVAST case M_AVAST: /* "avast" scanner type ----------------------------------- */ { - int ovector[10*3]; + int ovector[3*3]; uschar buf[1024]; uschar * scanrequest; enum {AVA_HELO, AVA_OPT, AVA_RSP, AVA_DONE} avast_stage; int nread; int more_data; uschar * error_message = NULL; + int strict = TRUE; /* According to Martin Tuma @avast the protocol uses "escaped whitespace", that is, every embedded whitespace is backslash @@ -2015,6 +2016,12 @@ b_seek: err = errno; if ((scanrequest = string_nextinlist(&av_scanner_work, &sep, NULL, 0))) { + if (Ustrcmp(scanrequest, "pass_unscanned") == 0) + { + DEBUG(D_acl) debug_printf_indent("pass unscanned files as clean\n"); + strict = FALSE; + goto sendreq; + } scanrequest = string_sprintf("%s\n", scanrequest); avast_stage = AVA_OPT; /* just sent option */ DEBUG(D_acl) debug_printf_indent("send to avast OPTION: %s", scanrequest); @@ -2055,19 +2062,13 @@ b_seek: err = errno; goto endloop; } - #if 0 - /* found malware or another error already, nothing to do anymore, just read on */ - if (malware_name || error_message) + if (malware_name) /* nothing else matters, just read on */ break; - #endif if (pcre_exec(ava_re_clean, NULL, CS buf, slen, 0, 0, ovector, nelem(ovector)) > 0) break; - if (malware_name) - break; - if (malware_name = m_pcre_exec(ava_re_virus, buf)) { unescape(malware_name); @@ -2076,10 +2077,7 @@ b_seek: err = errno; break; } - /*if (pcre_exec(ava_re_error, NULL, CS buf, nread, 0, 0, ovector, nelem(ovector)) == 2) - unescape(malware_name = buf + ovector[1*2]); - */ - if (malware_name = m_pcre_exec(ava_re_error, buf)) + if (strict && (malware_name = m_pcre_exec(ava_re_error, buf))) { unescape(malware_name); DEBUG(D_acl) @@ -2087,7 +2085,15 @@ b_seek: err = errno; break; } + if (pcre_exec(ava_re_error, NULL, CS buf, slen, 0, 0, NULL, 0) == 0) + { + log_write(0, LOG_MAIN, "internal scanner error (ignored): %s", buf); + break; + } + /* here also for any unexpected response from the scanner */ + DEBUG(D_acl) debug_printf("avast response not handled: '%s'\n", buf); + error_message = string_sprintf(string_sprintf("unexpected response from scanner: '%s'", buf)); goto endloop; default: log_write(0, LOG_PANIC, "%s:%d:%s: should not happen", diff --git a/test/log/4017 b/test/log/4017 index 480ac5d19..9d07f31bf 100644 --- a/test/log/4017 +++ b/test/log/4017 @@ -1,9 +1,15 @@ -1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss T="message should be accepted" -1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: R=r -1999-03-02 09:44:33 10HmbA-0005vi-00 Completed +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss T="message should be accepted" +1999-03-02 09:44:33 10HmbB-0005vi-00 => :blackhole: R=r +1999-03-02 09:44:33 10HmbB-0005vi-00 Completed 1999-03-02 09:44:33 10HmaX-0005vi-00 malware acl condition: avast TESTSUITE/eximdir/avast_sock : 451 SCAN Engine error 13 Permission denied 1999-03-02 09:44:33 10HmaX-0005vi-00 U=CALLER F= temporarily rejected after DATA 1999-03-02 09:44:33 10HmaY-0005vi-00 malware_name This is not even an EICAR test virus. 1999-03-02 09:44:33 10HmaY-0005vi-00 U=CALLER F= rejected after DATA 1999-03-02 09:44:33 10HmaZ-0005vi-00 malware_name The file is a decompression bomb 1999-03-02 09:44:33 10HmaZ-0005vi-00 U=CALLER F= rejected after DATA +1999-03-02 09:44:33 10HmbA-0005vi-00 malware_name The file is a decompression bomb +1999-03-02 09:44:33 10HmbA-0005vi-00 U=CALLER F= rejected after DATA +1999-03-02 09:44:33 10HmbC-0005vi-00 internal scanner error (ignored): /bin/error [E]0.0 Error 42110 The\ file\ is\ a\ decompression\ bomb +1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss T="message should be accepted" +1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: R=r +1999-03-02 09:44:33 10HmbC-0005vi-00 Completed diff --git a/test/rejectlog/4017 b/test/rejectlog/4017 index ca3f3888f..670b9057b 100644 --- a/test/rejectlog/4017 +++ b/test/rejectlog/4017 @@ -34,3 +34,15 @@ P Received: from CALLER (helo=test.ex) Subject: message should be rejected I Message-Id: F From: CALLER_NAME +1999-03-02 09:44:33 10HmbA-0005vi-00 U=CALLER F= rejected after DATA +Envelope-from: +Envelope-to: +P Received: from CALLER (helo=test.ex) + by myhost.test.ex with local-esmtp (Exim x.yz) + (envelope-from ) + id 10HmbA-0005vi-00 + for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000 + Date: Tue, 2 Mar 1999 09:44:33 +0000 + Subject: message should be rejected +I Message-Id: +F From: CALLER_NAME diff --git a/test/scripts/4017_scan_avast_multiline/4017 b/test/scripts/4017_scan_avast_multiline/4017 index 3e6b06713..3f888ea63 100644 --- a/test/scripts/4017_scan_avast_multiline/4017 +++ b/test/scripts/4017_scan_avast_multiline/4017 @@ -110,3 +110,57 @@ Subject: message should be rejected . quit **** +# +# +# clean, error -> reject +server DIR/eximdir/avast_sock +>LF>220 ready +LF>210 SCAN DATA +>LF>/bin/clean [+] +>LF>/bin/error [E]0.0 Error 42110 The\\ file\\ is\\ a\\ decompression\\ bomb +>LF>200 SCAN OK + +rcpt to: +data +Date: Fri, 17 Dec 2004 14:35:01 +0100 +Subject: message should be rejected + +. +quit +**** +# +# +# clean, error (pass_unscanned) -> accept +server DIR/eximdir/avast_sock +>LF>220 ready +LF>210 SCAN DATA +>LF>/bin/clean [+] +>LF>/bin/error [E]0.0 Error 42110 The\\ file\\ is\\ a\\ decompression\\ bomb +>LF>200 SCAN OK + +rcpt to: +data +Date: Fri, 17 Dec 2004 14:35:01 +0100 +Subject: message should be accepted + +. +quit +**** diff --git a/test/stdout/4017 b/test/stdout/4017 index 388af3dd4..7d731ae90 100644 --- a/test/stdout/4017 +++ b/test/stdout/4017 @@ -8,7 +8,7 @@ 250 OK 250 Accepted 354 Enter message, ending with "." on a line by itself -250 OK id=10HmbA-0005vi-00 +250 OK id=10HmbB-0005vi-00 221 myhost.test.ex closing connection ### scanner tmpfail -> defer 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 @@ -44,6 +44,28 @@ 354 Enter message, ending with "." on a line by itself 550 Administrative prohibition 221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +550 Administrative prohibition +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at test.ex +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK +250 Accepted +354 Enter message, ending with "." on a line by itself +250 OK id=10HmbC-0005vi-00 +221 myhost.test.ex closing connection ******** SERVER ******** ### clean | multiline response @@ -55,7 +77,7 @@ Connection request >LF>FLAGS -fullfiles >LF>FLAGS +extra >LF>200 FLAGS OK -LF>210 SCAN DATA >LF>/bin/clean1\x09[+] >LF>/bin/clean2\x09[+] @@ -97,3 +119,25 @@ Connection request LF>220 ready +LF>210 SCAN DATA +>LF>/bin/clean\x09[+] +>LF>/bin/error\x09[E]0.0\x09Error 42110 The\\ file\\ is\\ a\\ decompression\\ bomb +>LF>200 SCAN OK +LF>220 ready +LF>210 SCAN DATA +>LF>/bin/clean\x09[+] +>LF>/bin/error\x09[E]0.0\x09Error 42110 The\\ file\\ is\\ a\\ decompression\\ bomb +>LF>200 SCAN OK +