X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/0a5441fcd93ae4145c07b3ed138dfe0e107174e0..7dd52d1ff8cd5e8914172d3131412bf1c2ceaf92:/src/src/malware.c diff --git a/src/src/malware.c b/src/src/malware.c index 91649cf20..7ed4d358d 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 2015 - 2018 + * Copyright (c) The Exim Maintainers 2015 - 2020 */ /* Code for calling virus (malware) scanners. Called from acl.c. */ @@ -262,6 +262,7 @@ static inline int m_panic_defer_3(struct scan * scanent, const uschar * hostport, const uschar * str, int fd_to_close) { +DEBUG(D_acl) debug_print_socket(fd_to_close); (void) close(fd_to_close); return m_panic_defer(scanent, hostport, str); } @@ -302,8 +303,7 @@ const uschar * rerror; int roffset; const pcre * cre; -cre = pcre_compile(CS re, PCRE_COPT, (const char **)&rerror, &roffset, NULL); -if (!cre) +if (!(cre = pcre_compile(CS re, PCRE_COPT, CCSS &rerror, &roffset, NULL))) *errstr= string_sprintf("regular expression error in '%s': %s at offset %d", re, rerror, roffset); return cre; @@ -317,7 +317,7 @@ int i = pcre_exec(cre, NULL, CS text, Ustrlen(text), 0, 0, ovector, nelem(ovector)); uschar * substr = NULL; if (i >= 2) /* Got it */ - pcre_get_substring(CS text, ovector, i, 1, (const char **) &substr); + pcre_get_substring(CS text, ovector, i, 1, CCSS &substr); return substr; } @@ -339,6 +339,7 @@ else return cre; } + /* Simple though inefficient wrapper for reading a line. Drop CRs and the trailing newline. Can return early on buffer full. Null-terminate. @@ -370,8 +371,12 @@ while ((rcv = read(fd, p, 1)) > 0) } if (!ok) { - DEBUG(D_acl) debug_printf_indent("Malware scan: read %s (%s)\n", + DEBUG(D_acl) + { + debug_printf_indent("Malware scan: read %s (%s)\n", rcv==0 ? "EOF" : "error", strerror(errno)); + debug_print_socket(fd); + } return rcv==0 ? -1 : -2; } *p = '\0'; @@ -655,11 +660,11 @@ if (!malware_ok) switch(scanent->conn) { case MC_TCP: - malware_daemon_ctx.sock = ip_tcpsocket(scanner_options, &errstr, 5); break; + malware_daemon_ctx.sock = ip_tcpsocket(scanner_options, &errstr, 5, NULL); 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; + malware_daemon_ctx.sock = ip_streamsocket(scanner_options, &errstr, 5, NULL); break; default: /* compiler quietening */ break; } @@ -792,7 +797,7 @@ if (!malware_ok) if (*scanner_options != '/') { /* calc file size */ - if ((drweb_fd = open(CCS eml_filename, O_RDONLY)) == -1) + if ((drweb_fd = exim_open2(CCS eml_filename, O_RDONLY)) == -1) return m_panic_defer_3(scanent, NULL, string_sprintf("can't open spool file %s: %s", eml_filename, strerror(errno)), @@ -836,7 +841,7 @@ badseek: err = errno; malware_daemon_ctx.sock); } - if (!(drweb_fbuf = US malloc(fsize_uint))) + if (!(drweb_fbuf = store_malloc(fsize_uint))) { (void)close(drweb_fd); return m_panic_defer_3(scanent, NULL, @@ -849,7 +854,7 @@ badseek: err = errno; { int err = errno; (void)close(drweb_fd); - free(drweb_fbuf); + store_free(drweb_fbuf); return m_panic_defer_3(scanent, NULL, string_sprintf("can't read spool file %s: %s", eml_filename, strerror(err)), @@ -860,11 +865,12 @@ badseek: err = errno; /* send file body to socket */ if (send(malware_daemon_ctx.sock, drweb_fbuf, fsize, 0) < 0) { - free(drweb_fbuf); + store_free(drweb_fbuf); return m_panic_defer_3(scanent, CUS callout_address, string_sprintf( "unable to send file body to socket (%s)", scanner_options), malware_daemon_ctx.sock); } + store_free(drweb_fbuf); } else { @@ -917,7 +923,9 @@ badseek: err = errno; return m_panic_defer_3(scanent, CUS callout_address, US"cannot read report size", malware_daemon_ctx.sock); drweb_slen = ntohl(drweb_slen); - tmpbuf = store_get(drweb_slen); + + /* assume tainted, since it is external input */ + tmpbuf = store_get(drweb_slen, TRUE); /* read report body */ if (!recv_len(malware_daemon_ctx.sock, tmpbuf, drweb_slen, tmo)) @@ -1360,13 +1368,10 @@ badseek: err = errno; malware_name = US"unknown"; /* re-open the scanner output file, look for name match */ - scanner_record = fopen(CS file_name, "rb"); - while (fgets(CS linebuffer, sizeof(linebuffer), scanner_record)) - { - /* try match */ - if ((s = m_pcre_exec(cmdline_regex_re, linebuffer))) + scanner_record = Ufopen(file_name, "rb"); + while (Ufgets(linebuffer, sizeof(linebuffer), scanner_record)) + if ((s = m_pcre_exec(cmdline_regex_re, linebuffer))) /* try match */ malware_name = s; - } (void)fclose(scanner_record); } else /* no virus found */ @@ -1463,7 +1468,7 @@ badseek: err = errno; /* Local file; so we def want to use_scan_command and don't want to try * passing IP/port combinations */ use_scan_command = TRUE; - cd = (clamd_address *) store_get(sizeof(clamd_address)); + cd = (clamd_address *) store_get(sizeof(clamd_address), FALSE); /* extract socket-path part */ sublist = scanner_options; @@ -1497,7 +1502,7 @@ badseek: err = errno; continue; } - cd = (clamd_address *) store_get(sizeof(clamd_address)); + cd = (clamd_address *) store_get(sizeof(clamd_address), FALSE); /* extract host and port part */ sublist = scanner_options; @@ -1636,7 +1641,7 @@ badseek: err = errno; malware_daemon_ctx.sock); /* calc file size */ - if ((clam_fd = open(CS eml_filename, O_RDONLY)) < 0) + if ((clam_fd = exim_open2(CS eml_filename, O_RDONLY)) < 0) { int err = errno; return m_panic_defer_3(scanent, NULL, @@ -1666,7 +1671,7 @@ b_seek: err = errno; if (lseek(clam_fd, 0, SEEK_SET) < 0) goto b_seek; - if (!(clamav_fbuf = US malloc(fsize_uint))) + if (!(clamav_fbuf = store_malloc(fsize_uint))) { (void)close(clam_fd); return m_panic_defer_3(scanent, NULL, @@ -1678,7 +1683,7 @@ b_seek: err = errno; if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0) { int err = errno; - free(clamav_fbuf); (void)close(clam_fd); + store_free(clamav_fbuf); (void)close(clam_fd); return m_panic_defer_3(scanent, NULL, string_sprintf("can't read spool file %s: %s", eml_filename, strerror(err)), @@ -1693,13 +1698,12 @@ b_seek: err = errno; (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); + store_free(clamav_fbuf); return m_panic_defer_3(scanent, NULL, string_sprintf("unable to send file body to socket (%s)", hostname), malware_daemon_ctx.sock); } - - free(clamav_fbuf); + store_free(clamav_fbuf); } else { /* use scan command */ @@ -2278,12 +2282,13 @@ if (!fprot6d_re_virus) } -void -malware_show_supported(FILE * f) +gstring * +malware_show_supported(gstring * g) { -fprintf(f, "Malware:"); -for (struct scan * sc = m_scans; sc->scancode != (scanner_t)-1; sc++) fprintf(f, " %s", sc->name); -fprintf(f, "\n"); +g = string_cat(g, US"Malware:"); +for (struct scan * sc = m_scans; sc->scancode != (scanner_t)-1; sc++) + g = string_fmt_append(g, " %s", sc->name); +return string_cat(g, US"\n"); }