X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/e1d04f48a45c9f8e8ff75610003048f8ead73219..71b32d412ac4792ca5e8d4a697afddb46c407bd9:/src/src/malware.c diff --git a/src/src/malware.c b/src/src/malware.c index 547bc26e6..f9c4c414f 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -13,7 +13,7 @@ #ifdef WITH_CONTENT_SCAN typedef enum {M_FPROTD, M_DRWEB, M_AVES, M_FSEC, M_KAVD, M_CMDL, - M_SOPHIE, M_CLAMD, M_SOCK, M_MKSD, M_AVAST} scanner_t; + M_SOPHIE, M_CLAMD, M_SOCK, M_MKSD, M_AVAST, M_FPROT6D} scanner_t; typedef enum {MC_NONE, MC_TCP, MC_UNIX, MC_STRM} contype_t; static struct scan { @@ -34,6 +34,7 @@ static struct scan { M_SOCK, US"sock", US"/tmp/malware.sock", MC_STRM }, { M_MKSD, US"mksd", NULL, MC_NONE }, { M_AVAST, US"avast", US"/var/run/avast/scan.sock", MC_STRM }, + { M_FPROT6D, US"f-prot6d", US"localhost 10200", MC_TCP }, { -1, NULL, NULL, MC_NONE } /* end-marker */ }; @@ -84,6 +85,11 @@ static const uschar * ava_re_virus_str = US "(?!\\\\)\\t\\[L\\]\\d\\.\\d\\t\\d\\ static const pcre * ava_re_clean = NULL; static const pcre * ava_re_virus = NULL; +static const uschar * fprot6d_re_error_str = US "^\\d+\\s<(.+?)>$"; +static const uschar * fprot6d_re_virus_str = US "^\\d+\\s\\s+.+$"; +static const pcre * fprot6d_re_error = NULL; +static const pcre * fprot6d_re_virus = NULL; + /******************************************************************************/ @@ -503,8 +509,8 @@ if (!malware_ok) break; switch(scanent->conn) { - case MC_TCP: sock = ip_tcpsocket(scanner_options, &errstr, 5); break; - case MC_UNIX: sock = ip_unixsocket(scanner_options, &errstr); break; + case MC_TCP: sock = ip_tcpsocket(scanner_options, &errstr, 5); break; + case MC_UNIX: sock = ip_unixsocket(scanner_options, &errstr); break; case MC_STRM: sock = ip_streamsocket(scanner_options, &errstr, 5); break; default: /* compiler quietening */ break; } @@ -1911,8 +1917,53 @@ if (!malware_ok) sock); default: break; } + break; } + + case M_FPROT6D: /* "f-prot6d" scanner type ----------------------------------- */ + { + int bread; + uschar * e; + uschar * linebuffer; + uschar * scanrequest; + uschar av_buffer[1024]; + + if ((!fprot6d_re_virus && !(fprot6d_re_virus = m_pcre_compile(fprot6d_re_virus_str, &errstr))) + || (!fprot6d_re_error && !(fprot6d_re_error = m_pcre_compile(fprot6d_re_error_str, &errstr)))) + return malware_errlog_defer(errstr); + + scanrequest = string_sprintf("SCAN FILE %s\n", eml_filename); + DEBUG(D_acl) debug_printf_indent("Malware scan: issuing %s: %s\n", + scanner_name, scanrequest); + + if (m_sock_send(sock, scanrequest, Ustrlen(scanrequest), &errstr) < 0) + return m_errlog_defer(scanent, CUS callout_address, errstr); + + bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL)); + + if (bread <= 0) + return m_errlog_defer_3(scanent, CUS callout_address, + string_sprintf("unable to read from socket (%s)", strerror(errno)), + sock); + + if (bread == sizeof(av_buffer)) + return m_errlog_defer_3(scanent, CUS callout_address, + US"buffer too small", sock); + + av_buffer[bread] = '\0'; + linebuffer = string_copy(av_buffer); + + m_sock_send(sock, US"QUIT\n", 5, 0); + + if ((e = m_pcre_exec(fprot6d_re_error, linebuffer))) + return m_errlog_defer_3(scanent, CUS callout_address, + string_sprintf("scanner reported error (%s)", e), sock); + + if (!(malware_name = m_pcre_exec(fprot6d_re_virus, linebuffer))) + malware_name = NULL; + break; + } /* f-prot6d */ } /* scanner type switch */ if (sock >= 0) @@ -2028,6 +2079,10 @@ 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); +if (!fprot6d_re_error) + fprot6d_re_error = regex_must_compile(fprot6d_re_error_str, FALSE, TRUE); +if (!fprot6d_re_virus) + fprot6d_re_virus = regex_must_compile(fprot6d_re_virus_str, FALSE, TRUE); } #endif /*WITH_CONTENT_SCAN*/