summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2018-03-10 04:30:56 +0100
committerHeiko Schlittermann (HS12-RIPE) <hs@schlittermann.de>2018-03-12 20:39:33 +0100
commit71bb51e08dc03f768d19f237fed415bc74246de3 (patch)
tree4fbed8793eda114d7956792522ca6412c019c602 /src
parentf48946eb9bad9060dd7430bcedfeaf1c4a48dc09 (diff)
Update to protocol used by avast 2.2.0 (Multiline responses) (Bug 2112)
Based on a patch by Victor Ustugov.
Diffstat (limited to 'src')
-rw-r--r--src/src/malware.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/src/src/malware.c b/src/src/malware.c
index 5b9d5ad58..948aedea1 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -1893,6 +1893,7 @@ b_seek: err = errno;
uschar * scanrequest;
enum {AVA_HELO, AVA_OPT, AVA_RSP, AVA_DONE} avast_stage;
int nread;
+ int more_data;
/* According to Martin Tuma @avast the protocol uses "escaped
whitespace", that is, every embedded whitespace is backslash
@@ -1902,7 +1903,9 @@ b_seek: err = errno;
[+] - not infected
[L] - infected
[E] - some error occured
- Such marker follows the first non-escaped TAB. */
+ Such marker follows the first non-escaped TAB. For more information
+ see avast-protocol(5)
+ */
if ( ( !ava_re_clean
&& !(ava_re_clean = m_pcre_compile(ava_re_clean_str, &errstr)))
|| ( !ava_re_virus
@@ -1918,17 +1921,25 @@ b_seek: err = errno;
int slen = Ustrlen(buf);
if (slen >= 1)
{
- DEBUG(D_acl) debug_printf_indent("got from avast: %s\n", buf);
+
+ /* Multi line responses are bracketed between 210 … and nnn … */
+ if (Ustrncmp(buf, "210", 3) == 0)
+ {
+ more_data = 1;
+ continue;
+ }
+ else if (more_data && isdigit(buf[0])) more_data = 0;
+
switch (avast_stage)
{
case AVA_HELO:
+ if (more_data) continue;
if (Ustrncmp(buf, "220", 3) != 0)
goto endloop; /* require a 220 */
goto sendreq;
case AVA_OPT:
- if (Ustrncmp(buf, "210", 3) == 0)
- break; /* ignore 210 responses */
+ if (more_data) continue;
if (Ustrncmp(buf, "200", 3) != 0)
goto endloop; /* require a 200 */
@@ -1941,11 +1952,13 @@ b_seek: err = errno;
{
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);
}
else
{
scanrequest = string_sprintf("SCAN %s\n", eml_dir);
avast_stage = AVA_RSP; /* just sent command */
+ DEBUG(D_acl) debug_printf_indent("send to avast REQUEST: SCAN %s\n", eml_dir);
}
/* send config-cmd or scan-request to socket */
@@ -1961,15 +1974,27 @@ b_seek: err = errno;
}
case AVA_RSP:
- if (Ustrncmp(buf, "210", 3) == 0)
- break; /* ignore the "210 SCAN DATA" message */
+
+ if (Ustrncmp(buf, "200", 3) == 0)
+ { /* we're done finally */
+ if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
+ return m_errlog_defer_3(scanent, CUS callout_address,
+ string_sprintf(
+ "unable to send quit request to socket (%s): %s",
+ scanner_options, strerror(errno)),
+ sock);
+
+ avast_stage = AVA_DONE;
+ goto endloop;
+ }
+
+ if (malware_name) break; /* found malware already, nothing to do anymore */
if (pcre_exec(ava_re_clean, NULL, CS buf, slen,
0, 0, ovector, nelem(ovector)) > 0)
break;
- if ( !malware_name
- && (malware_name = m_pcre_exec(ava_re_virus, buf)))
+ if (malware_name = m_pcre_exec(ava_re_virus, buf))
{ /* remove backslash in front of [whitespace|backslash] */
uschar * p, * p0;
for (p = malware_name; *p; ++p)
@@ -1977,22 +2002,10 @@ b_seek: err = errno;
for (p0 = p; *p0; ++p0) *p0 = p0[1];
DEBUG(D_acl)
- debug_printf_indent("unescaped m-name: '%s'\n", malware_name);
+ debug_printf_indent("unescaped malware name: '%s'\n", malware_name);
break;
}
- if (Ustrncmp(buf, "200 SCAN OK", 11) == 0)
- { /* we're done finally */
- if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
- return m_errlog_defer_3(scanent, CUS callout_address,
- string_sprintf(
- "unable to send quit request to socket (%s): %s",
- scanner_options, strerror(errno)),
- sock);
-
- avast_stage = AVA_DONE;
- }
-
/* here also for any unexpected response from the scanner */
goto endloop;