Compiler quietening
[exim.git] / src / src / malware.c
index e74ba983004f179aaa1b6ea23b1ac4acdb174564..948aedea18f5880ce691c661dec03b8f99aee00f 100644 (file)
@@ -4,7 +4,7 @@
 
 /* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003 - 2015
  * License: GPL
- * Copyright (c) The Exim Maintainers 2017 - 2018
+ * Copyright (c) The Exim Maintainers 2015 - 2018
  */
 
 /* Code for calling virus (malware) scanners. Called from acl.c. */
@@ -1277,7 +1277,7 @@ badseek:  err = errno;
       sep = pclose(scanner_out);
       signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
       if (sep != 0)
-         return m_errlog_defer(scanent, NULL, 
+         return m_errlog_defer(scanent, NULL,
              sep == -1
              ? string_sprintf("running scanner failed: %s", strerror(sep))
              : string_sprintf("scanner returned error code: %d", sep));
@@ -1432,13 +1432,13 @@ badseek:  err = errno;
          sublist = scanner_options;
          if (!(cd->hostspec = string_nextinlist(&sublist, &subsep, NULL, 0)))
            {
-           (void) m_errlog_defer(scanent, NULL, 
+           (void) m_errlog_defer(scanent, NULL,
                      string_sprintf("missing address: '%s'", scanner_options));
            continue;
            }
          if (!(s = string_nextinlist(&sublist, &subsep, NULL, 0)))
            {
-           (void) m_errlog_defer(scanent, NULL, 
+           (void) m_errlog_defer(scanent, NULL,
                      string_sprintf("missing port: '%s'", scanner_options));
            continue;
            }
@@ -1893,6 +1893,7 @@ b_seek:   err = errno;
       uschar * scanrequest;
       enum {AVA_HELO, AVA_OPT, AVA_RSP, AVA_DONE} avast_stage;
       int nread;
+      int more_data;
 
       /* According to Martin Tuma @avast the protocol uses "escaped
       whitespace", that is, every embedded whitespace is backslash
@@ -1902,7 +1903,9 @@ b_seek:   err = errno;
       [+] - not infected
       [L] - infected
       [E] - some error occured
-      Such marker follows the first non-escaped TAB.  */
+      Such marker follows the first non-escaped TAB.  For more information
+      see avast-protocol(5)
+      */
       if (  (  !ava_re_clean
             && !(ava_re_clean = m_pcre_compile(ava_re_clean_str, &errstr)))
         || (  !ava_re_virus
@@ -1918,17 +1921,25 @@ b_seek:   err = errno;
        int slen = Ustrlen(buf);
        if (slen >= 1)
          {
-         DEBUG(D_acl) debug_printf_indent("got from avast: %s\n", buf);
+
+          /* Multi line responses are bracketed between 210 … and nnn … */
+          if (Ustrncmp(buf, "210", 3) == 0)
+            {
+            more_data = 1;
+            continue;
+            }
+          else if (more_data && isdigit(buf[0])) more_data = 0;
+
          switch (avast_stage)
            {
            case AVA_HELO:
+              if (more_data) continue;
              if (Ustrncmp(buf, "220", 3) != 0)
                goto endloop;                   /* require a 220 */
              goto sendreq;
 
            case AVA_OPT:
-             if (Ustrncmp(buf, "210", 3) == 0)
-               break;                          /* ignore 210 responses */
+              if (more_data) continue;
              if (Ustrncmp(buf, "200", 3) != 0)
                goto endloop;                   /* require a 200 */
 
@@ -1941,11 +1952,13 @@ b_seek:   err = errno;
                {
                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);
                }
              else
                {
                scanrequest = string_sprintf("SCAN %s\n", eml_dir);
                avast_stage = AVA_RSP;          /* just sent command */
+               DEBUG(D_acl) debug_printf_indent("send to avast REQUEST: SCAN %s\n", eml_dir);
                }
 
              /* send config-cmd or scan-request to socket */
@@ -1961,15 +1974,27 @@ b_seek:   err = errno;
              }
 
            case AVA_RSP:
-             if (Ustrncmp(buf, "210", 3) == 0)
-               break;  /* ignore the "210 SCAN DATA" message */
+
+             if (Ustrncmp(buf, "200", 3) == 0)
+               { /* we're done finally */
+               if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
+                 return m_errlog_defer_3(scanent, CUS callout_address,
+                         string_sprintf(
+                             "unable to send quit request to socket (%s): %s",
+                             scanner_options, strerror(errno)),
+                             sock);
+
+               avast_stage = AVA_DONE;
+                goto endloop;
+               }
+
+              if (malware_name) break;  /* found malware already, nothing to do anymore */
 
              if (pcre_exec(ava_re_clean, NULL, CS buf, slen,
                    0, 0, ovector, nelem(ovector)) > 0)
                break;
 
-             if (  !malware_name
-                && (malware_name = m_pcre_exec(ava_re_virus, buf)))
+             if (malware_name = m_pcre_exec(ava_re_virus, buf))
                { /* remove backslash in front of [whitespace|backslash] */
                uschar * p, * p0;
                for (p = malware_name; *p; ++p)
@@ -1977,22 +2002,10 @@ b_seek:   err = errno;
                    for (p0 = p; *p0; ++p0) *p0 = p0[1];
 
                DEBUG(D_acl)
-                 debug_printf_indent("unescaped m-name: '%s'\n", malware_name);
+                 debug_printf_indent("unescaped malware name: '%s'\n", malware_name);
                break;
                }
 
-             if (Ustrncmp(buf, "200 SCAN OK", 11) == 0)
-               { /* we're done finally */
-               if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
-                 return m_errlog_defer_3(scanent, CUS callout_address,
-                         string_sprintf(
-                             "unable to send quit request to socket (%s): %s",
-                             scanner_options, strerror(errno)),
-                             sock);
-
-               avast_stage = AVA_DONE;
-               }
-
              /* here also for any unexpected response from the scanner */
              goto endloop;