X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fmalware.c;h=d24f09b88794035fd33c89ceed083de2e8022a81;hb=b3b370766107a2bda78f6362170ddbe4b2c0bb21;hp=e74ba983004f179aaa1b6ea23b1ac4acdb174564;hpb=83d2a8615f6fede0c99dda5cb83dd510d7ad0269;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/malware.c b/src/src/malware.c index e74ba9830..d24f09b88 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -4,7 +4,7 @@ /* Copyright (c) Tom Kistner 2003 - 2015 * License: GPL - * Copyright (c) The Exim Maintainers 2017 - 2018 + * Copyright (c) The Exim Maintainers 2015 - 2018 */ /* Code for calling virus (malware) scanners. Called from acl.c. */ @@ -1277,7 +1277,7 @@ badseek: err = errno; sep = pclose(scanner_out); signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe); if (sep != 0) - return m_errlog_defer(scanent, NULL, + return m_errlog_defer(scanent, NULL, sep == -1 ? string_sprintf("running scanner failed: %s", strerror(sep)) : string_sprintf("scanner returned error code: %d", sep)); @@ -1432,13 +1432,13 @@ badseek: err = errno; sublist = scanner_options; if (!(cd->hostspec = string_nextinlist(&sublist, &subsep, NULL, 0))) { - (void) m_errlog_defer(scanent, NULL, + (void) m_errlog_defer(scanent, NULL, string_sprintf("missing address: '%s'", scanner_options)); continue; } if (!(s = string_nextinlist(&sublist, &subsep, NULL, 0))) { - (void) m_errlog_defer(scanent, NULL, + (void) m_errlog_defer(scanent, NULL, string_sprintf("missing port: '%s'", scanner_options)); continue; } @@ -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; @@ -2133,13 +2146,13 @@ if (!kav_re_sus) if (!kav_re_inf) kav_re_inf = regex_must_compile(kav_re_inf_str, FALSE, TRUE); #endif -#ifndef DISABLE_MAL_AVA +#ifndef DISABLE_MAL_AVAST if (!ava_re_clean) ava_re_clean = regex_must_compile(ava_re_clean_str, FALSE, TRUE); if (!ava_re_virus) ava_re_virus = regex_must_compile(ava_re_virus_str, FALSE, TRUE); #endif -#ifndef DISABLE_MAL_FPROT6D +#ifndef DISABLE_MAL_FFROT6D if (!fprot6d_re_error) fprot6d_re_error = regex_must_compile(fprot6d_re_error_str, FALSE, TRUE); if (!fprot6d_re_virus)