Malware: make "sock" cmdline default usable. Bug 2111
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 29 May 2017 16:23:12 +0000 (17:23 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 30 May 2017 19:05:40 +0000 (20:05 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/malware.c
test/confs/4012 [new file with mode: 0644]
test/scripts/4000-scanning/4012 [new file with mode: 0644]

index 6fb150428ca1a09f8154f29660507cd536c67551..b891679a0c9b3ce44a903bc5aa46ca80cd99fc37 100644 (file)
@@ -31702,13 +31702,17 @@ an address (which may be an IP address and port, or the path of a Unix socket),
 a commandline to send (may include a single %s which will be replaced with
 the path to the mail file to be scanned),
 an RE to trigger on from the returned data,
 a commandline to send (may include a single %s which will be replaced with
 the path to the mail file to be scanned),
 an RE to trigger on from the returned data,
-an RE to extract malware_name from the returned data.
+and an RE to extract malware_name from the returned data.
 For example:
 .code
 For example:
 .code
-av_scanner = sock:127.0.0.1 6001:%s:(SPAM|VIRUS):(.*)\$
+av_scanner = sock:127.0.0.1 6001:%s:(SPAM|VIRUS):(.*)$
 .endd
 .endd
+.new
+Note that surrounding whitespace is stripped from each option, meaning
+there is no way to specify a trailing newline.
+.wen
 Default for the socket specifier is &_/tmp/malware.sock_&.
 Default for the socket specifier is &_/tmp/malware.sock_&.
-Default for the commandline is &_%s\n_&.
+Default for the commandline is &_%s\n_& (note this does have a trailing newline).
 Both regular-expressions are required.
 
 .vitem &%sophie%&
 Both regular-expressions are required.
 
 .vitem &%sophie%&
index 05dc007ded23fcc9bb052f61c7c329c1040c7628..4eb0d3b1a725a27c4a4dfa2ecfa673c3b31c1a14 100644 (file)
@@ -98,6 +98,10 @@ PP/05 OpenSSL/1.1: use DH_bits() for more accurate DH param sizes.  This
       configured limit or use OpenSSL 1.1.  Nothing we can do for older
       versions.
 
       configured limit or use OpenSSL 1.1.  Nothing we can do for older
       versions.
 
+JH/14 For the "sock" variant of the malware scanner interface, accept an empty
+      cmdline element to get the documented default one.  Previously it was
+      inaccessible.
+
 
 Exim version 4.89
 -----------------
 
 Exim version 4.89
 -----------------
index 94a271b471f8c0903e1b361bb6ee605ddc2b0fea..d7be4edbb599b51a76351db980d35d0cb669c50a 100644 (file)
@@ -202,7 +202,11 @@ const pcre * cre = NULL;
 if (!(list_ele = string_nextinlist(list, sep, NULL, 0)))
   *errstr = US listerr;
 else
 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);
   cre = m_pcre_compile(CUS list_ele, errstr);
+  }
 return cre;
 }
 
 return cre;
 }
 
@@ -472,9 +476,6 @@ if (  strcmpic(malware_re,US"true") == 0
 else if (!(re = m_pcre_compile(malware_re, &errstr)))
   return malware_errlog_defer(errstr);
 
 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 == '$')
   {
 /* if av_scanner starts with a dollar, expand it first */
 if (*av_scanner == '$')
   {
@@ -506,10 +507,15 @@ if (!malware_ok)
        scanner_name));
     if (strcmpic(scanner_name, US scanent->name) != 0)
       continue;
        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;
     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;
     switch(scanent->conn)
     {
     case MC_TCP:  sock = ip_tcpsocket(scanner_options, &errstr, 5);    break;
@@ -521,7 +527,6 @@ if (!malware_ok)
       return m_errlog_defer(scanent, CUS callout_address, errstr);
     break;
   }
       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)
     {
 
   switch (scanent->scancode)
     {
@@ -1701,8 +1706,10 @@ b_seek:   err = errno;
       const pcre *sockline_name_re;
 
       /* find scanner command line */
       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++)
       {        /* check for no expansions apart from one %s */
        uschar * s = Ustrchr(sockline_scanner, '%');
        if (s++)
@@ -1712,6 +1719,8 @@ b_seek:   err = errno;
       }
       else
        sockline_scanner = sockline_scanner_default;
       }
       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,
 
       /* find scanner output trigger */
       sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep,
@@ -1727,7 +1736,8 @@ b_seek:   err = errno;
 
       /* prepare scanner call - security depends on expansions check above */
       commandline = string_sprintf( CS sockline_scanner, CS eml_filename);
 
       /* prepare scanner call - security depends on expansions check above */
       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)
 
       /* Pass the command string to the socket */
       if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0)
@@ -1746,12 +1756,16 @@ b_seek:   err = errno;
                US"buffer too small", sock);
       av_buffer[bread] = '\0';
       linebuffer = string_copy(av_buffer);
                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";
 
       /* 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;
        }
       else /* no virus found */
        malware_name = NULL;
diff --git a/test/confs/4012 b/test/confs/4012
new file mode 100644 (file)
index 0000000..9afd4a0
--- /dev/null
@@ -0,0 +1,29 @@
+# Exim test configuration 4012
+# Content-scan: sock interface
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+av_scanner = sock : 127.0.0.1 PORT_S : : BAD : NAME:: (\w+)
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept
+acl_smtp_data = c_data
+
+begin acl
+
+c_data:
+  accept !malware = * OPT
+  deny  logwrite = $callout_address malware_name $malware_name
+
+# ----- Routers -----
+
+begin routers
+
+r:
+  driver = redirect
+  data = :blackhole:
+
+# End
diff --git a/test/scripts/4000-scanning/4012 b/test/scripts/4000-scanning/4012
new file mode 100644 (file)
index 0000000..42d108c
--- /dev/null
@@ -0,0 +1,45 @@
+# content scan interface: sock
+need_ipv4
+munge loopback
+#
+server PORT_S
+/
+>LF>RESULT: OK
+****
+#
+#
+#
+exim -odi -bs -DOPT=
+ehlo test.ex
+mail from:<>
+rcpt to:<userx@test.ex>
+data
+Date: Fri, 17 Dec 2004 14:35:01 +0100
+Subject: message should be accepted
+
+.
+quit
+****
+#
+#
+#
+server PORT_S
+/
+>LF>RESULT: BAD
+>LF>NAME: wibble
+****
+#
+#
+#
+exim -odi -bs -DOPT=
+ehlo test.ex
+mail from:<>
+rcpt to:<userx@test.ex>
+data
+Date: Fri, 17 Dec 2004 14:35:01 +0100
+Subject: message should be rejected
+
+due to the server response (above)
+.
+quit
+****