X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/eb445b049c9b78cbe187b9cb3c318d65862d4851..74f1a42304ce056cf979d22fb970faae161e3ab2:/src/src/malware.c diff --git a/src/src/malware.c b/src/src/malware.c index 730a2be22..49456de4e 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -12,8 +12,44 @@ #include "exim.h" #ifdef WITH_CONTENT_SCAN /* entire file */ -typedef enum {M_FPROTD, M_DRWEB, M_AVES, M_FSEC, M_KAVD, M_CMDL, - M_SOPHIE, M_CLAMD, M_SOCK, M_MKSD, M_AVAST, M_FPROT6D} scanner_t; +typedef enum { +#ifndef DISABLE_MAL_FFROTD + M_FPROTD, +#endif +#ifndef DISABLE_MAL_FFROT6D + M_FPROT6D, +#endif +#ifndef DISABLE_MAL_DRWEB + M_DRWEB, +#endif +#ifndef DISABLE_MAL_AVE + M_AVES, +#endif +#ifndef DISABLE_MAL_FSECURE + M_FSEC, +#endif +#ifndef DISABLE_MAL_KAV + M_KAVD, +#endif +#ifndef DISABLE_MAL_SOPHIE + M_SOPHIE, +#endif +#ifndef DISABLE_MAL_CLAM + M_CLAMD, +#endif +#ifndef DISABLE_MAL_MKS + M_MKSD, +#endif +#ifndef DISABLE_MAL_AVAST + M_AVAST, +#endif +#ifndef DISABLE_MAL_SOCK + M_SOCK, +#endif +#ifndef DISABLE_MAL_CMDLINE + M_CMDL, +#endif + } scanner_t; typedef enum {MC_NONE, MC_TCP, MC_UNIX, MC_STRM} contype_t; static struct scan { @@ -180,12 +216,14 @@ extern uschar spooled_message_id[MESSAGE_ID_LENGTH+1]; /* Some (currently avast only) use backslash escaped whitespace, this function undoes these escapes */ + static inline void -unescape(char *p) { - uschar *p0; - for (; *p; ++p) - if (*p == '\\' && (isspace(p[1]) || p[1] == '\\')) - for (p0 = p; *p0; ++p0) *p0 = p0[1]; +unescape(uschar *p) +{ +uschar *p0; +for (; *p; ++p) + if (*p == '\\' && (isspace(p[1]) || p[1] == '\\')) + for (p0 = p; *p0; ++p0) *p0 = p0[1]; } /* --- malware_*_defer --- */ @@ -398,12 +436,13 @@ for (;;) static inline int mksd_read_lines (int sock, uschar *av_buffer, int av_buffer_size, int tmo) { +client_conn_ctx cctx = {.sock = sock}; int offset = 0; int i; do { - i = ip_recv(sock, av_buffer+offset, av_buffer_size-offset, tmo-time(NULL)); + i = ip_recv(&cctx, av_buffer+offset, av_buffer_size-offset, tmo-time(NULL)); if (i <= 0) { (void) malware_panic_defer(US"unable to read from mksd UNIX socket (/var/run/mksd/socket)"); @@ -538,7 +577,7 @@ const pcre *re; uschar * errstr; struct scan * scanent; const uschar * scanner_options; -int sock = -1; +client_conn_ctx malware_daemon_ctx = {.sock = -1}; time_t tmo; uschar * eml_filename, * eml_dir; @@ -619,12 +658,16 @@ if (!malware_ok) DEBUG(D_acl) debug_printf_indent("%15s%10s%s\n", "", "socket: ", scanner_options); 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_STRM: sock = ip_streamsocket(scanner_options, &errstr, 5); break; - default: /* compiler quietening */ break; + case MC_TCP: + malware_daemon_ctx.sock = ip_tcpsocket(scanner_options, &errstr, 5); break; + case MC_UNIX: + malware_daemon_ctx.sock = ip_unixsocket(scanner_options, &errstr); break; + case MC_STRM: + malware_daemon_ctx.sock = ip_streamsocket(scanner_options, &errstr, 5); break; + default: + /* compiler quietening */ break; } - if (sock < 0) + if (malware_daemon_ctx.sock < 0) return m_panic_defer(scanent, CUS callout_address, errstr); break; } @@ -655,10 +698,10 @@ if (!malware_ok) scanner_name, scanrequest); /* send scan request */ - if (m_sock_send(sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); - while ((len = recv_line(sock, buf, sizeof(buf), tmo)) >= 0) + while ((len = recv_line(malware_daemon_ctx.sock, buf, sizeof(buf), tmo)) >= 0) if (len > 0) { if (Ustrstr(buf, US" 0 */ @@ -875,16 +918,16 @@ badseek: err = errno; int ovector[10*3]; /* read the size of report */ - if (!recv_len(sock, &drweb_slen, sizeof(drweb_slen), tmo)) + if (!recv_len(malware_daemon_ctx.sock, &drweb_slen, sizeof(drweb_slen), tmo)) return m_panic_defer_3(scanent, CUS callout_address, - US"cannot read report size", sock); + US"cannot read report size", malware_daemon_ctx.sock); drweb_slen = ntohl(drweb_slen); tmpbuf = store_get(drweb_slen); /* read report body */ - if (!recv_len(sock, tmpbuf, drweb_slen, tmo)) + if (!recv_len(malware_daemon_ctx.sock, tmpbuf, drweb_slen, tmo)) return m_panic_defer_3(scanent, CUS callout_address, - US"cannot read report string", sock); + US"cannot read report string", malware_daemon_ctx.sock); tmpbuf[drweb_slen] = '\0'; /* try matcher on the line, grab substring */ @@ -923,7 +966,7 @@ badseek: err = errno; if (drweb_s) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("drweb daemon retcode 0x%x (%s)", drweb_rc, drweb_s), - sock); + malware_daemon_ctx.sock); /* no virus found */ malware_name = NULL; @@ -940,13 +983,13 @@ badseek: err = errno; /* read aveserver's greeting and see if it is ready (2xx greeting) */ buf[0] = 0; - recv_line(sock, buf, sizeof(buf), tmo); + recv_line(malware_daemon_ctx.sock, buf, sizeof(buf), tmo); if (buf[0] != '2') /* aveserver is having problems */ return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unavailable (Responded: %s).", ((buf[0] != 0) ? buf : US "nothing") ), - sock); + malware_daemon_ctx.sock); /* prepare our command */ (void)string_format(buf, sizeof(buf), "SCAN bPQRSTUW %s\r\n", @@ -955,13 +998,13 @@ badseek: err = errno; /* and send it */ DEBUG(D_acl) debug_printf_indent("Malware scan: issuing %s %s\n", scanner_name, buf); - if (m_sock_send(sock, buf, Ustrlen(buf), &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, buf, Ustrlen(buf), &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); malware_name = NULL; result = 0; /* read response lines, find malware name and final response */ - while (recv_line(sock, buf, sizeof(buf), tmo) > 0) + while (recv_line(malware_daemon_ctx.sock, buf, sizeof(buf), tmo) > 0) { if (buf[0] == '2') break; @@ -980,22 +1023,22 @@ badseek: err = errno; } } - if (m_sock_send(sock, US"quit\r\n", 6, &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, US"quit\r\n", 6, &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); /* read aveserver's greeting and see if it is ready (2xx greeting) */ buf[0] = 0; - recv_line(sock, buf, sizeof(buf), tmo); + recv_line(malware_daemon_ctx.sock, buf, sizeof(buf), tmo); if (buf[0] != '2') /* aveserver is having problems */ return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to quit dialogue (Responded: %s).", ((buf[0] != 0) ? buf : US "nothing") ), - sock); + malware_daemon_ctx.sock); if (result == DEFER) { - (void)close(sock); + (void)close(malware_daemon_ctx.sock); return DEFER; } break; @@ -1022,15 +1065,15 @@ badseek: err = errno; for (i = 0; i != nelem(cmdopt); i++) { - if (m_sock_send(sock, cmdopt[i], Ustrlen(cmdopt[i]), &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, cmdopt[i], Ustrlen(cmdopt[i]), &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); - bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL)); + bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo-time(NULL)); if (bread > 0) av_buffer[bread]='\0'; if (bread < 0) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to read answer %d (%s)", i, strerror(errno)), - sock); + malware_daemon_ctx.sock); for (j = 0; j < bread; j++) if (av_buffer[j] == '\r' || av_buffer[j] == '\n') av_buffer[j] ='@'; @@ -1039,7 +1082,7 @@ badseek: err = errno; /* pass the mailfile to fsecure */ file_name = string_sprintf("SCAN\t%s\n", eml_filename); - if (m_sock_send(sock, file_name, Ustrlen(file_name), &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, file_name, Ustrlen(file_name), &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); /* set up match */ @@ -1057,10 +1100,10 @@ badseek: err = errno; { errno = ETIMEDOUT; i = av_buffer+sizeof(av_buffer)-p; - if ((bread= ip_recv(sock, p, i-1, tmo-time(NULL))) < 0) + if ((bread= ip_recv(&malware_daemon_ctx, p, i-1, tmo-time(NULL))) < 0) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to read result (%s)", strerror(errno)), - sock); + malware_daemon_ctx.sock); for (p[bread] = '\0'; (q = Ustrchr(p, '\n')); p = q+1) { @@ -1117,13 +1160,13 @@ badseek: err = errno; scanner_name, scanner_options); /* send scan request */ - if (m_sock_send(sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); /* wait for result */ - if (!recv_len(sock, tmpbuf, 2, tmo)) + if (!recv_len(malware_daemon_ctx.sock, tmpbuf, 2, tmo)) return m_panic_defer_3(scanent, CUS callout_address, - US"unable to read 2 bytes from socket.", sock); + US"unable to read 2 bytes from socket.", malware_daemon_ctx.sock); /* get errorcode from one nibble */ kav_rc = tmpbuf[ test_byte_order()==LITTLE_MY_ENDIAN ? 0 : 1 ] & 0x0F; @@ -1132,13 +1175,13 @@ badseek: err = errno; case 5: case 6: /* improper kavdaemon configuration */ return m_panic_defer_3(scanent, CUS callout_address, US"please reconfigure kavdaemon to NOT disinfect or remove infected files.", - sock); + malware_daemon_ctx.sock); case 1: return m_panic_defer_3(scanent, CUS callout_address, - US"reported 'scanning not completed' (code 1).", sock); + US"reported 'scanning not completed' (code 1).", malware_daemon_ctx.sock); case 7: return m_panic_defer_3(scanent, CUS callout_address, - US"reported 'kavdaemon damaged' (code 7).", sock); + US"reported 'kavdaemon damaged' (code 7).", malware_daemon_ctx.sock); } /* code 8 is not handled, since it is ambiguous. It appears mostly on @@ -1158,9 +1201,9 @@ badseek: err = errno; if (report_flag == 1) { /* read report size */ - if (!recv_len(sock, &kav_reportlen, 4, tmo)) + if (!recv_len(malware_daemon_ctx.sock, &kav_reportlen, 4, tmo)) return m_panic_defer_3(scanent, CUS callout_address, - US"cannot read report size", sock); + US"cannot read report size", malware_daemon_ctx.sock); /* it's possible that avp returns av_buffer[1] == 1 but the reportsize is 0 (!?) */ @@ -1183,7 +1226,7 @@ badseek: err = errno; /* coverity[tainted_data] */ while (kav_reportlen > 0) { - if ((bread = recv_line(sock, tmpbuf, sizeof(tmpbuf), tmo)) < 0) + if ((bread = recv_line(malware_daemon_ctx.sock, tmpbuf, sizeof(tmpbuf), tmo)) < 0) break; kav_reportlen -= bread+1; @@ -1353,19 +1396,19 @@ badseek: err = errno; DEBUG(D_acl) debug_printf_indent("Malware scan: issuing %s scan [%s]\n", scanner_name, scanner_options); - if ( write(sock, file_name, Ustrlen(file_name)) < 0 - || write(sock, "\n", 1) != 1 + if ( write(malware_daemon_ctx.sock, file_name, Ustrlen(file_name)) < 0 + || write(malware_daemon_ctx.sock, "\n", 1) != 1 ) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to write to UNIX socket (%s)", scanner_options), - sock); + malware_daemon_ctx.sock); /* wait for result */ memset(av_buffer, 0, sizeof(av_buffer)); - if ((bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL))) <= 0) + if ((bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo-time(NULL))) <= 0) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to read from UNIX socket (%s)", scanner_options), - sock); + malware_daemon_ctx.sock); /* infected ? */ if (av_buffer[0] == '1') { @@ -1376,7 +1419,7 @@ badseek: err = errno; } else if (!strncmp(CS av_buffer, "-1", 2)) return m_panic_defer_3(scanent, CUS callout_address, - US"scanner reported error", sock); + US"scanner reported error", malware_daemon_ctx.sock); else /* all ok, no virus */ malware_name = NULL; @@ -1535,7 +1578,7 @@ badseek: err = errno; * on both connections (as one host could resolve to multiple ips) */ for (;;) { - if ((sock = m_tcpsocket(cd->hostspec, cd->tcp_port, + if ((malware_daemon_ctx.sock = m_tcpsocket(cd->hostspec, cd->tcp_port, &connhost, &errstr, &cmd_str)) >= 0) { /* Connection successfully established with a server */ @@ -1546,7 +1589,7 @@ badseek: err = errno; if (cd->retry <= 0) break; while (cd->retry > 0) cd->retry = sleep(cd->retry); } - if (sock >= 0) + if (malware_daemon_ctx.sock >= 0) break; (void) m_panic_defer(scanent, CUS callout_address, errstr); @@ -1563,7 +1606,7 @@ badseek: err = errno; else for (;;) { - if ((sock = ip_unixsocket(cv[0]->hostspec, &errstr)) >= 0) + if ((malware_daemon_ctx.sock = ip_unixsocket(cv[0]->hostspec, &errstr)) >= 0) { hostname = cv[0]->hostspec; break; @@ -1590,11 +1633,11 @@ badseek: err = errno; /* Pass the string to ClamAV (10 = "zINSTREAM\0"), if not already sent */ if (cmd_str.len) - if (send(sock, cmd_str.data, cmd_str.len, 0) < 0) + if (send(malware_daemon_ctx.sock, cmd_str.data, cmd_str.len, 0) < 0) return m_panic_defer_3(scanent, CUS hostname, string_sprintf("unable to send zINSTREAM to socket (%s)", strerror(errno)), - sock); + malware_daemon_ctx.sock); /* calc file size */ if ((clam_fd = open(CS eml_filename, O_RDONLY)) < 0) @@ -1603,7 +1646,7 @@ badseek: err = errno; return m_panic_defer_3(scanent, NULL, string_sprintf("can't open spool file %s: %s", eml_filename, strerror(err)), - sock); + malware_daemon_ctx.sock); } if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0) { @@ -1613,7 +1656,7 @@ b_seek: err = errno; return m_panic_defer_3(scanent, NULL, string_sprintf("can't seek spool file %s: %s", eml_filename, strerror(err)), - sock); + malware_daemon_ctx.sock); } fsize_uint = (unsigned int) fsize; if ((off_t)fsize_uint != fsize) @@ -1622,7 +1665,7 @@ b_seek: err = errno; return m_panic_defer_3(scanent, NULL, string_sprintf("seeking spool file %s, size overflow", eml_filename), - sock); + malware_daemon_ctx.sock); } if (lseek(clam_fd, 0, SEEK_SET) < 0) goto b_seek; @@ -1633,7 +1676,7 @@ b_seek: err = errno; return m_panic_defer_3(scanent, NULL, string_sprintf("unable to allocate memory %u for file (%s)", fsize_uint, eml_filename), - sock); + malware_daemon_ctx.sock); } if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0) @@ -1643,21 +1686,21 @@ b_seek: err = errno; return m_panic_defer_3(scanent, NULL, string_sprintf("can't read spool file %s: %s", eml_filename, strerror(err)), - sock); + malware_daemon_ctx.sock); } (void)close(clam_fd); /* send file body to socket */ send_size = htonl(fsize_uint); send_final_zeroblock = 0; - if ((send(sock, &send_size, sizeof(send_size), 0) < 0) || - (send(sock, clamav_fbuf, fsize_uint, 0) < 0) || - (send(sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0)) + if ((send(malware_daemon_ctx.sock, &send_size, sizeof(send_size), 0) < 0) || + (send(malware_daemon_ctx.sock, clamav_fbuf, fsize_uint, 0) < 0) || + (send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0)) { free(clamav_fbuf); return m_panic_defer_3(scanent, NULL, string_sprintf("unable to send file body to socket (%s)", hostname), - sock); + malware_daemon_ctx.sock); } free(clamav_fbuf); @@ -1684,10 +1727,10 @@ b_seek: err = errno; scanner_name, scanner_options); if (cmd_str.len) - if (send(sock, cmd_str.data, cmd_str.len, 0) < 0) + if (send(malware_daemon_ctx.sock, cmd_str.data, cmd_str.len, 0) < 0) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to write to socket (%s)", strerror(errno)), - sock); + malware_daemon_ctx.sock); /* Do not shut down the socket for writing; a user report noted that * clamd 0.70 does not react well to this. */ @@ -1697,9 +1740,10 @@ b_seek: err = errno; /* Read the result */ memset(av_buffer, 0, sizeof(av_buffer)); - bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL)); - (void)close(sock); - sock = -1; + bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo-time(NULL)); + (void)close(malware_daemon_ctx.sock); + malware_daemon_ctx.sock = -1; + malware_daemon_ctx.tls_ctx = NULL; if (bread <= 0) return m_panic_defer(scanent, CUS callout_address, @@ -1825,7 +1869,7 @@ b_seek: err = errno; if (s++) if ((*s != 's' && *s != '%') || Ustrchr(s+1, '%')) return m_panic_defer_3(scanent, NULL, - US"unsafe sock scanner call spec", sock); + US"unsafe sock scanner call spec", malware_daemon_ctx.sock); } else sockline_scanner = sockline_scanner_default; @@ -1836,13 +1880,13 @@ b_seek: err = errno; sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep, "missing trigger specification", &errstr); if (!sockline_trig_re) - return m_panic_defer_3(scanent, NULL, errstr, sock); + return m_panic_defer_3(scanent, NULL, errstr, malware_daemon_ctx.sock); /* find virus name regex */ sockline_name_re = m_pcre_nextinlist(&av_scanner_work, &sep, "missing virus name regex specification", &errstr); if (!sockline_name_re) - return m_panic_defer_3(scanent, NULL, errstr, sock); + return m_panic_defer_3(scanent, NULL, errstr, malware_daemon_ctx.sock); /* prepare scanner call - security depends on expansions check above */ commandline = string_sprintf( CS sockline_scanner, CS eml_filename); @@ -1850,20 +1894,20 @@ b_seek: err = errno; string_printing(commandline)); /* Pass the command string to the socket */ - if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0) + if (m_sock_send(malware_daemon_ctx.sock, commandline, Ustrlen(commandline), &errstr) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); /* Read the result */ - bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL)); + bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo-time(NULL)); if (bread <= 0) return m_panic_defer_3(scanent, CUS callout_address, string_sprintf("unable to read from socket (%s)", strerror(errno)), - sock); + malware_daemon_ctx.sock); if (bread == sizeof(av_buffer)) return m_panic_defer_3(scanent, CUS callout_address, - US"buffer too small", sock); + US"buffer too small", malware_daemon_ctx.sock); av_buffer[bread] = '\0'; linebuffer = string_copy(av_buffer); DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "answer: ", @@ -1902,16 +1946,16 @@ b_seek: err = errno; string_sprintf("invalid option '%s'", scanner_options)); } - if((sock = ip_unixsocket(US "/var/run/mksd/socket", &errstr)) < 0) + if((malware_daemon_ctx.sock = ip_unixsocket(US "/var/run/mksd/socket", &errstr)) < 0) return m_panic_defer(scanent, CUS callout_address, errstr); malware_name = NULL; DEBUG(D_acl) debug_printf_indent("Malware scan: issuing %s scan\n", scanner_name); - if ((retval = mksd_scan_packed(scanent, sock, eml_filename, tmo)) != OK) + if ((retval = mksd_scan_packed(scanent, malware_daemon_ctx.sock, eml_filename, tmo)) != OK) { - close (sock); + close (malware_daemon_ctx.sock); return retval; } break; @@ -1921,14 +1965,13 @@ b_seek: err = errno; #ifndef DISABLE_MAL_AVAST case M_AVAST: /* "avast" scanner type ----------------------------------- */ { - 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; + BOOL more_data = FALSE; + BOOL strict = TRUE; /* According to Martin Tuma @avast the protocol uses "escaped whitespace", that is, every embedded whitespace is backslash @@ -1981,7 +2024,7 @@ b_seek: err = errno; /* wait for result */ for (avast_stage = AVA_HELO; - (nread = recv_line(sock, buf, sizeof(buf), tmo)) > 0; + (nread = recv_line(malware_daemon_ctx.sock, buf, sizeof(buf), tmo)) > 0; ) { int slen = Ustrlen(buf); @@ -2035,41 +2078,28 @@ b_seek: err = errno; /* send config-cmd or scan-request to socket */ len = Ustrlen(scanrequest); - if (send(sock, scanrequest, len, 0) == -1) + if (send(malware_daemon_ctx.sock, scanrequest, len, 0) == -1) { scanrequest[len-1] = '\0'; return m_panic_defer_3(scanent, CUS callout_address, string_sprintf( "unable to send request '%s' to socket (%s): %s", - scanrequest, scanner_options, strerror(errno)), sock); + scanrequest, scanner_options, strerror(errno)), malware_daemon_ctx.sock); } break; } case AVA_RSP: - if (isdigit(buf[0])) - { /* we're done, this is the last response line from the scanner */ - DEBUG(D_acl) debug_printf_indent("sent to avast QUIT\n"); - if (send(sock, "QUIT\n", 5, 0) == -1) /* courtesy */ - return m_panic_defer_3(scanent, CUS callout_address, - string_sprintf( - "unable to send quit request to socket (%s): %s", - scanner_options, strerror(errno)), - sock); - - if (buf[0] != '2') error_message = buf; - avast_stage = AVA_DONE; + if (isdigit(buf[0])) /* We're done */ goto endloop; - } - if (malware_name) /* nothing else matters, just read on */ + if (malware_name) /* Nothing else matters, just read on */ break; - if (pcre_exec(ava_re_clean, NULL, CS buf, slen, - 0, 0, ovector, nelem(ovector)) > 0) + if (pcre_exec(ava_re_clean, NULL, CS buf, slen, 0, 0, NULL, 0) == 0) break; - if (malware_name = m_pcre_exec(ava_re_virus, buf)) + if ((malware_name = m_pcre_exec(ava_re_virus, buf))) { unescape(malware_name); DEBUG(D_acl) @@ -2077,15 +2107,17 @@ b_seek: err = errno; break; } - if (strict && (malware_name = m_pcre_exec(ava_re_error, buf))) + if (strict) /* treat scanner errors as malware */ { - unescape(malware_name); - DEBUG(D_acl) - debug_printf_indent("unescaped error message: '%s'\n", malware_name); - break; + if ((malware_name = m_pcre_exec(ava_re_error, buf))) + { + unescape(malware_name); + DEBUG(D_acl) + debug_printf_indent("unescaped error message: '%s'\n", malware_name); + break; + } } - - if (pcre_exec(ava_re_error, NULL, CS buf, slen, 0, 0, NULL, 0) == 0) + else 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; @@ -2093,7 +2125,7 @@ b_seek: err = errno; /* 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", @@ -2101,29 +2133,29 @@ b_seek: err = errno; } } } + endloop: - switch(avast_stage) - { - case AVA_HELO: - case AVA_OPT: - case AVA_RSP: - if (nread == -1) error_message = "EOF from scanner"; - else if (nread < 0) error_message = "timeout from scanner"; + if (nread == -1) error_message = US"EOF from scanner"; + else if (nread < 0) error_message = US"timeout from scanner"; + else if (nread == 0) error_message = US"got nothing from scanner"; + else if (buf[0] != '2') error_message = buf; - case AVA_DONE: - if (error_message) - return m_panic_defer_3(scanent, CUS callout_address, error_message, sock); + DEBUG(D_acl) debug_printf_indent("sent to avast QUIT\n"); + if (send(malware_daemon_ctx.sock, "QUIT\n", 5, 0) == -1) + return m_panic_defer_3(scanent, CUS callout_address, + string_sprintf("unable to send quit request to socket (%s): %s", + scanner_options, strerror(errno)), malware_daemon_ctx.sock); + + if (error_message) + return m_panic_defer_3(scanent, CUS callout_address, error_message, malware_daemon_ctx.sock); - default: break; - } - break; } #endif } /* scanner type switch */ - if (sock >= 0) - (void) close (sock); + if (malware_daemon_ctx.sock >= 0) + (void) close (malware_daemon_ctx.sock); malware_ok = TRUE; /* set "been here, done that" marker */ }