X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fmalware.c;h=d7be4edbb599b51a76351db980d35d0cb669c50a;hb=af542dcfa62fc2341e8253f10c5c778b887444b9;hp=f9c4c414f71633c5af3c8bc21cca3b4a33f55a23;hpb=71b32d412ac4792ca5e8d4a697afddb46c407bd9;p=exim.git diff --git a/src/src/malware.c b/src/src/malware.c index f9c4c414f..d7be4edbb 100644 --- a/src/src/malware.c +++ b/src/src/malware.c @@ -202,7 +202,11 @@ const pcre * cre = NULL; if (!(list_ele = string_nextinlist(list, sep, NULL, 0))) *errstr = US listerr; else + { + DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "RE: ", + string_printing(list_ele)); cre = m_pcre_compile(CUS list_ele, errstr); + } return cre; } @@ -413,16 +417,16 @@ is via malware(), or there's malware_in_file() used for testing/debugging. Arguments: malware_re match condition for "malware=" - eml_filename the file holding the email to be scanned + scan_filename the file holding the email to be scanned, if we're faking + this up for the -bmalware test, else NULL timeout if nonzero, non-default timeoutl - faking whether or not we're faking this up for the -bmalware test Returns: Exim message processing code (OK, FAIL, DEFER, ...) where true means malware was found (condition applies) */ static int -malware_internal(const uschar * malware_re, const uschar * eml_filename, - int timeout, BOOL faking) +malware_internal(const uschar * malware_re, const uschar * scan_filename, + int timeout) { int sep = 0; const uschar *av_scanner_work = av_scanner; @@ -435,21 +439,24 @@ struct scan * scanent; const uschar * scanner_options; int sock = -1; time_t tmo; +uschar * eml_filename, * eml_dir; + +if (!malware_re) + return FAIL; /* empty means "don't match anything" */ -/* make sure the eml mbox file is spooled up */ -if (!(mbox_file = spool_mbox(&mbox_size, faking ? eml_filename : NULL))) +/* Ensure the eml mbox file is spooled up */ + +if (!(mbox_file = spool_mbox(&mbox_size, scan_filename, &eml_filename))) return malware_errlog_defer(US"error while creating mbox spool file"); -/* none of our current scanners need the mbox - file as a stream, so we can close it right away */ -(void)fclose(mbox_file); +/* None of our current scanners need the mbox file as a stream (they use +the name), so we can close it right away. Get the directory too. */ -if (!malware_re) - return FAIL; /* empty means "don't match anything" */ +(void) fclose(mbox_file); +eml_dir = string_copyn(eml_filename, Ustrrchr(eml_filename, '/') - eml_filename); /* parse 1st option */ - if ( (strcmpic(malware_re, US"false") == 0) || - (Ustrcmp(malware_re,"0") == 0) ) +if (strcmpic(malware_re, US"false") == 0 || Ustrcmp(malware_re,"0") == 0) return FAIL; /* explicitly no matching */ /* special cases (match anything except empty) */ @@ -469,9 +476,6 @@ if ( strcmpic(malware_re,US"true") == 0 else if (!(re = m_pcre_compile(malware_re, &errstr))) return malware_errlog_defer(errstr); -/* Reset sep that is set by previous string_nextinlist() call */ -sep = 0; - /* if av_scanner starts with a dollar, expand it first */ if (*av_scanner == '$') { @@ -503,10 +507,15 @@ if (!malware_ok) scanner_name)); if (strcmpic(scanner_name, US scanent->name) != 0) continue; + DEBUG(D_acl) debug_printf_indent("Malware scan: %s tmo=%s\n", + scanner_name, readconf_printtime(timeout)); + if (!(scanner_options = string_nextinlist(&av_scanner_work, &sep, NULL, 0))) scanner_options = scanent->options_default; if (scanent->conn == MC_NONE) break; + + 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; @@ -518,7 +527,6 @@ if (!malware_ok) return m_errlog_defer(scanent, CUS callout_address, errstr); break; } - DEBUG(D_acl) debug_printf_indent("Malware scan: %s tmo %s\n", scanner_name, readconf_printtime(timeout)); switch (scanent->scancode) { @@ -602,7 +610,8 @@ if (!malware_ok) if ((fsize = lseek(drweb_fd, 0, SEEK_END)) == -1) { - int err = errno; + int err; +badseek: err = errno; (void)close(drweb_fd); return m_errlog_defer_3(scanent, NULL, string_sprintf("can't seek spool file %s: %s", @@ -619,7 +628,8 @@ if (!malware_ok) sock); } drweb_slen = htonl(fsize); - lseek(drweb_fd, 0, SEEK_SET); + if (lseek(drweb_fd, 0, SEEK_SET) < 0) + goto badseek; DEBUG(D_acl) debug_printf_indent("Malware scan: issuing %s remote scan [%s]\n", scanner_name, scanner_options); @@ -1091,8 +1101,7 @@ if (!malware_ok) } scanner_fd = fileno(scanner_out); - file_name = string_sprintf("%s/scan/%s/%s_scanner_output", - spool_directory, message_id, message_id); + file_name = string_sprintf("%s/%s_scanner_output", eml_dir, message_id); if (!(scanner_record = modefopen(file_name, "wb", SPOOL_MODE))) { @@ -1476,7 +1485,8 @@ if (!malware_ok) } if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0) { - int err = errno; + int err; +b_seek: err = errno; CLOSE_SOCKDATA; (void)close(clam_fd); return m_errlog_defer_3(scanent, NULL, string_sprintf("can't seek spool file %s: %s", @@ -1492,7 +1502,8 @@ if (!malware_ok) eml_filename), sock); } - lseek(clam_fd, 0, SEEK_SET); + if (lseek(clam_fd, 0, SEEK_SET) < 0) + goto b_seek; if (!(clamav_fbuf = US malloc(fsize_uint))) { @@ -1695,8 +1706,10 @@ if (!malware_ok) const pcre *sockline_name_re; /* find scanner command line */ - if ((sockline_scanner = string_nextinlist(&av_scanner_work, &sep, - NULL, 0))) + if ( (sockline_scanner = string_nextinlist(&av_scanner_work, &sep, + NULL, 0)) + && *sockline_scanner + ) { /* check for no expansions apart from one %s */ uschar * s = Ustrchr(sockline_scanner, '%'); if (s++) @@ -1706,6 +1719,8 @@ if (!malware_ok) } else sockline_scanner = sockline_scanner_default; + DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "cmdline: ", + string_printing(sockline_scanner)); /* find scanner output trigger */ sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep, @@ -1720,9 +1735,9 @@ if (!malware_ok) return m_errlog_defer_3(scanent, NULL, errstr, sock); /* prepare scanner call - security depends on expansions check above */ - commandline = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id, message_id); - commandline = string_sprintf( CS sockline_scanner, CS commandline); - + commandline = string_sprintf( CS sockline_scanner, CS eml_filename); + DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "expanded: ", + string_printing(commandline)); /* Pass the command string to the socket */ if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0) @@ -1741,12 +1756,16 @@ if (!malware_ok) US"buffer too small", sock); av_buffer[bread] = '\0'; linebuffer = string_copy(av_buffer); + DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "answer: ", + string_printing(linebuffer)); /* try trigger match */ if (regex_match_and_setup(sockline_trig_re, linebuffer, 0, -1)) { if (!(malware_name = m_pcre_exec(sockline_name_re, av_buffer))) malware_name = US "unknown"; + DEBUG(D_acl) debug_printf_indent("%15s%10s'%s'\n", "", "name: ", + string_printing(malware_name)); } else /* no virus found */ malware_name = NULL; @@ -1844,8 +1863,7 @@ if (!malware_ok) } else { - scanrequest = string_sprintf("SCAN %s/scan/%s\n", - spool_directory, message_id); + scanrequest = string_sprintf("SCAN %s\n", eml_dir); avast_stage = AVA_RSP; /* just sent command */ } @@ -2000,14 +2018,9 @@ Returns: Exim message processing code (OK, FAIL, DEFER, ...) int malware(const uschar * malware_re, int timeout) { -uschar * scan_filename; -int ret; +int ret = malware_internal(malware_re, NULL, timeout); -scan_filename = string_sprintf("%s/scan/%s/%s.eml", - spool_directory, message_id, message_id); -ret = malware_internal(malware_re, scan_filename, timeout, FALSE); if (ret == DEFER) av_failed = TRUE; - return ret; } @@ -2045,7 +2058,7 @@ recipients_list = NULL; receive_add_recipient(US"malware-victim@example.net", -1); enable_dollar_recipients = TRUE; -ret = malware_internal(US"*", eml_filename, 0, TRUE); +ret = malware_internal(US"*", eml_filename, 0); Ustrncpy(spooled_message_id, message_id, sizeof(spooled_message_id)); spool_mbox_ok = 1;