Avast: implement pass_unscanned option
[exim.git] / src / src / malware.c
index 7c57c0090058fd0d66f7e086a7a8352acc28d0f0..730a2be22389330608576d7c5c6d6532db64eff9 100644 (file)
@@ -1921,13 +1921,14 @@ b_seek:   err = errno;
 #ifndef DISABLE_MAL_AVAST
     case M_AVAST: /* "avast" scanner type ----------------------------------- */
       {
-      int ovector[10*3];
+      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;
 
       /* According to Martin Tuma @avast the protocol uses "escaped
       whitespace", that is, every embedded whitespace is backslash
@@ -2015,6 +2016,12 @@ b_seek:   err = errno;
              if ((scanrequest = string_nextinlist(&av_scanner_work, &sep,
                                NULL, 0)))
                {
+                if (Ustrcmp(scanrequest, "pass_unscanned") == 0)
+                  {
+                  DEBUG(D_acl) debug_printf_indent("pass unscanned files as clean\n");
+                  strict = FALSE;
+                  goto sendreq;
+                  }
                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);
@@ -2055,19 +2062,13 @@ b_seek:   err = errno;
                 goto endloop;
                }
 
-              #if 0
-              /* found malware or another error already, nothing to do anymore, just read on */
-              if (malware_name || error_message)
+              if (malware_name) /* nothing else matters, just read on */
                 break;
-              #endif
 
              if (pcre_exec(ava_re_clean, NULL, CS buf, slen,
                    0, 0, ovector, nelem(ovector)) > 0)
                break;
 
-             if (malware_name)
-                break;
-
               if (malware_name = m_pcre_exec(ava_re_virus, buf))
                 {
                 unescape(malware_name);
@@ -2076,10 +2077,7 @@ b_seek:   err = errno;
                 break;
                 }
 
-              /*if (pcre_exec(ava_re_error, NULL, CS buf, nread, 0, 0, ovector, nelem(ovector)) == 2)
-              unescape(malware_name = buf + ovector[1*2]);
-              */
-              if (malware_name = m_pcre_exec(ava_re_error, buf))
+              if (strict && (malware_name = m_pcre_exec(ava_re_error, buf)))
                 {
                 unescape(malware_name);
                 DEBUG(D_acl)
@@ -2087,7 +2085,15 @@ b_seek:   err = errno;
                 break;
                 }
 
+              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;
+                }
+
              /* 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",