Add timeout option to spamd_address server specification. Bug 68
[exim.git] / src / src / malware.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003-2014 */
6 /* License: GPL */
7
8 /* Code for calling virus (malware) scanners. Called from acl.c. */
9
10 #include "exim.h"
11 #ifdef WITH_CONTENT_SCAN
12
13 typedef enum {M_FPROTD, M_DRWEB, M_AVES, M_FSEC, M_KAVD, M_CMDL,
14                 M_SOPHIE, M_CLAMD, M_SOCK, M_MKSD, M_AVAST} scanner_t;
15 typedef enum {MC_NONE, MC_TCP, MC_UNIX, MC_STRM} contype_t;
16 static struct scan
17 {
18   scanner_t     scancode;
19   const uschar * name;
20   const uschar * options_default;
21   contype_t     conn;
22 } m_scans[] =
23 {
24   { M_FPROTD,   US"f-protd",    US"localhost 10200-10204",            MC_TCP },
25   { M_DRWEB,    US"drweb",      US"/usr/local/drweb/run/drwebd.sock", MC_STRM },
26   { M_AVES,     US"aveserver",  US"/var/run/aveserver",               MC_UNIX },
27   { M_FSEC,     US"fsecure",    US"/var/run/.fsav",                   MC_UNIX },
28   { M_KAVD,     US"kavdaemon",  US"/var/run/AvpCtl",                  MC_UNIX },
29   { M_CMDL,     US"cmdline",    NULL,                                 MC_NONE },
30   { M_SOPHIE,   US"sophie",     US"/var/run/sophie",                  MC_UNIX },
31   { M_CLAMD,    US"clamd",      US"/tmp/clamd",                       MC_NONE },
32   { M_SOCK,     US"sock",       US"/tmp/malware.sock",                MC_STRM },
33   { M_MKSD,     US"mksd",       NULL,                                 MC_NONE },
34   { M_AVAST,    US"avast",      US"/var/run/avast/scan.sock",         MC_STRM },
35   { -1,         NULL,           NULL, MC_NONE }         /* end-marker */
36 };
37
38 /* The maximum number of clamd servers that are supported in the configuration */
39 #define MAX_CLAMD_SERVERS 32
40 #define MAX_CLAMD_SERVERS_S "32"
41 /* Maximum length of the hostname that can be specified in the clamd address list */
42 #define MAX_CLAMD_ADDRESS_LENGTH 64
43 #define MAX_CLAMD_ADDRESS_LENGTH_S "64"
44
45 typedef struct clamd_address_container {
46   uschar tcp_addr[MAX_CLAMD_ADDRESS_LENGTH+1];
47   unsigned int tcp_port;
48 } clamd_address_container;
49
50 #ifndef nelements
51 # define nelements(arr) (sizeof(arr) / sizeof(arr[0]))
52 #endif
53
54
55 #define MALWARE_TIMEOUT 120     /* default timeout, seconds */
56
57
58 #define DRWEBD_SCAN_CMD             (1)     /* scan file, buffer or diskfile */
59 #define DRWEBD_RETURN_VIRUSES       (1<<0)   /* ask daemon return to us viruses names from report */
60 #define DRWEBD_IS_MAIL              (1<<19)  /* say to daemon that format is "archive MAIL" */
61
62 #define DERR_READ_ERR               (1<<0)   /* read error */
63 #define DERR_NOMEMORY               (1<<2)   /* no memory */
64 #define DERR_TIMEOUT                (1<<9)   /* scan timeout has run out */
65 #define DERR_BAD_CALL               (1<<15)  /* wrong command */
66
67
68 static const uschar * malware_regex_default = US ".+";
69 static const pcre * malware_default_re = NULL;
70
71 static const uschar * drweb_re_str = US "infected\\swith\\s*(.+?)$";
72 static const pcre * drweb_re = NULL;
73
74 static const uschar * fsec_re_str = US "\\S{0,5}INFECTED\\t[^\\t]*\\t([^\\t]+)\\t\\S*$";
75 static const pcre * fsec_re = NULL;
76
77 static const uschar * kav_re_sus_str = US "suspicion:\\s*(.+?)\\s*$";
78 static const uschar * kav_re_inf_str = US "infected:\\s*(.+?)\\s*$";
79 static const pcre * kav_re_sus = NULL;
80 static const pcre * kav_re_inf = NULL;
81
82 static const uschar * ava_re_clean_str = US "(?!\\\\)\\t\\[\\+\\]";
83 static const uschar * ava_re_virus_str = US "(?!\\\\)\\t\\[L\\]\\d\\.\\d\\t\\d\\s(.*)";
84 static const pcre * ava_re_clean = NULL;
85 static const pcre * ava_re_virus = NULL;
86
87
88
89 /******************************************************************************/
90
91 /* Routine to check whether a system is big- or little-endian.
92    Ripped from http://www.faqs.org/faqs/graphics/fileformats-faq/part4/section-7.html
93    Needed for proper kavdaemon implementation. Sigh. */
94 #define BIG_MY_ENDIAN      0
95 #define LITTLE_MY_ENDIAN   1
96 static int test_byte_order(void);
97 static inline int
98 test_byte_order()
99 {
100   short int word = 0x0001;
101   char *byte = (char *) &word;
102   return(byte[0] ? LITTLE_MY_ENDIAN : BIG_MY_ENDIAN);
103 }
104
105 BOOL malware_ok = FALSE;
106
107 /* Gross hacks for the -bmalware option; perhaps we should just create
108 the scan directory normally for that case, but look into rigging up the
109 needed header variables if not already set on the command-line? */
110 extern int spool_mbox_ok;
111 extern uschar spooled_message_id[17];
112
113
114
115 static inline int
116 malware_errlog_defer(const uschar * str)
117 {
118   log_write(0, LOG_MAIN|LOG_PANIC, "malware acl condition: %s", str);
119   return DEFER;
120 }
121
122 static int
123 m_errlog_defer(struct scan * scanent, const uschar * str)
124 {
125   return malware_errlog_defer(string_sprintf("%s: %s", scanent->name, str));
126 }
127 static int
128 m_errlog_defer_3(struct scan * scanent, const uschar * str,
129         int fd_to_close)
130 {
131   (void) close(fd_to_close);
132   return m_errlog_defer(scanent, str);
133 }
134
135 /*************************************************/
136
137 /* Only used by the Clamav code, which is working from a list of servers and
138 uses the returned in_addr to get a second connection to the same system.
139 */
140 static inline int
141 m_tcpsocket(const uschar * hostname, unsigned int port,
142         host_item * host, uschar ** errstr)
143 {
144   return ip_connectedsocket(SOCK_STREAM, hostname, port, port, 5, host, errstr);
145 }
146
147 static int
148 m_sock_send(int sock, uschar * buf, int cnt, uschar ** errstr)
149 {
150   if (send(sock, buf, cnt, 0) < 0) {
151     int err = errno;
152     (void)close(sock);
153     *errstr = string_sprintf("unable to send to socket (%s): %s",
154            buf, strerror(err));
155     return -1;
156     }
157   return sock;
158 }
159
160 static const pcre *
161 m_pcre_compile(const uschar * re, uschar ** errstr)
162 {
163   const uschar * rerror;
164   int roffset;
165   const pcre * cre;
166
167   cre = pcre_compile(CS re, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
168   if (!cre)
169     *errstr= string_sprintf("regular expression error in '%s': %s at offset %d",
170         re, rerror, roffset);
171   return cre;
172 }
173
174 uschar *
175 m_pcre_exec(const pcre * cre, uschar * text)
176 {
177   int ovector[10*3];
178   int i = pcre_exec(cre, NULL, CS text, Ustrlen(text), 0, 0,
179                 ovector, nelements(ovector));
180   uschar * substr = NULL;
181   if (i >= 2)                           /* Got it */
182     pcre_get_substring(CS text, ovector, i, 1, (const char **) &substr);
183   return substr;
184 }
185
186 static const pcre *
187 m_pcre_nextinlist(uschar ** list, int * sep, char * listerr, uschar ** errstr)
188 {
189   const uschar * list_ele;
190   const pcre * cre = NULL;
191
192   if (!(list_ele = string_nextinlist(list, sep, NULL, 0)))
193     *errstr = US listerr;
194   else
195     cre = m_pcre_compile(CUS list_ele, errstr);
196   return cre;
197 }
198
199 /*
200  Simple though inefficient wrapper for reading a line.  Drop CRs and the
201  trailing newline. Can return early on buffer full. Null-terminate.
202  Apply initial timeout if no data ready.
203
204  Return: number of chars - zero for an empty line
205          -1 on EOF
206          -2 on timeout or error
207 */
208 static int
209 recv_line(int fd, uschar * buffer, int bsize, int tmo)
210 {
211 uschar * p = buffer;
212 ssize_t rcv;
213 BOOL ok = FALSE;
214
215 if (!fd_ready(fd, tmo-time(NULL)))
216   return -2;
217
218 /*XXX tmo handling assumes we always get a whole line */
219 /* read until \n */
220 errno = 0;
221 while ((rcv = read(fd, p, 1)) > 0)
222   {
223   ok = TRUE;
224   if (p-buffer > bsize-2) break;
225   if (*p == '\n') break;
226   if (*p != '\r') p++;
227   }
228 if (!ok)
229   {
230   DEBUG(D_acl) debug_printf("Malware scan: read %s (%s)\n",
231                 rcv==0 ? "EOF" : "error", strerror(errno));
232   return rcv==0 ? -1 : -2;
233   }
234 *p = '\0';
235
236 DEBUG(D_acl) debug_printf("Malware scan: read '%s'\n", buffer);
237 return p - buffer;
238 }
239
240 /* return TRUE iff size as requested */
241 static BOOL
242 recv_len(int sock, void * buf, int size, int tmo)
243 {
244 return fd_ready(sock, tmo-time(NULL))
245   ? recv(sock, buf, size, 0) == size
246   : FALSE;
247 }
248
249
250
251 /* ============= private routines for the "mksd" scanner type ============== */
252
253 #include <sys/uio.h>
254
255 static inline int
256 mksd_writev (int sock, struct iovec * iov, int iovcnt)
257 {
258 int i;
259
260 for (;;)
261   {
262   do
263     i = writev (sock, iov, iovcnt);
264   while (i < 0 && errno == EINTR);
265   if (i <= 0)
266     {
267     (void) malware_errlog_defer(
268             US"unable to write to mksd UNIX socket (/var/run/mksd/socket)");
269     return -1;
270     }
271   for (;;)      /* check for short write */
272     if (i >= iov->iov_len)
273       {
274       if (--iovcnt == 0)
275         return 0;
276       i -= iov->iov_len;
277       iov++;
278       }
279     else
280       {
281       iov->iov_len -= i;
282       iov->iov_base = CS iov->iov_base + i;
283       break;
284       }
285   }
286 }
287
288 static inline int
289 mksd_read_lines (int sock, uschar *av_buffer, int av_buffer_size, int tmo)
290 {
291 int offset = 0;
292 int i;
293
294 do
295   {
296   i = ip_recv(sock, av_buffer+offset, av_buffer_size-offset, tmo-time(NULL));
297   if (i <= 0)
298     {
299     (void) malware_errlog_defer(US"unable to read from mksd UNIX socket (/var/run/mksd/socket)");
300     return -1;
301     }
302
303   offset += i;
304   /* offset == av_buffer_size -> buffer full */
305   if (offset == av_buffer_size)
306     {
307     (void) malware_errlog_defer(US"malformed reply received from mksd");
308     return -1;
309     }
310   } while (av_buffer[offset-1] != '\n');
311
312 av_buffer[offset] = '\0';
313 return offset;
314 }
315
316 static inline int
317 mksd_parse_line(struct scan * scanent, char * line)
318 {
319 char *p;
320
321 switch (*line)
322   {
323   case 'O': /* OK */
324     return OK;
325
326   case 'E':
327   case 'A': /* ERR */
328     if ((p = strchr (line, '\n')) != NULL)
329       *p = '\0';
330     return m_errlog_defer(scanent,
331       string_sprintf("scanner failed: %s", line));
332
333   default: /* VIR */
334     if ((p = strchr (line, '\n')) != NULL)
335       {
336       *p = '\0';
337       if (  p-line > 5
338          && line[3] == ' '
339          && (p = strchr(line+4, ' ')) != NULL
340          && p-line > 4
341          )
342         {
343         *p = '\0';
344         malware_name = string_copy(US line+4);
345         return OK;
346         }
347       }
348     return m_errlog_defer(scanent,
349       string_sprintf("malformed reply received: %s", line));
350   }
351 }
352
353 static int
354 mksd_scan_packed(struct scan * scanent, int sock, const uschar * scan_filename,
355   int tmo)
356 {
357 struct iovec iov[3];
358 const char *cmd = "MSQ\n";
359 uschar av_buffer[1024];
360
361 iov[0].iov_base = (void *) cmd;
362 iov[0].iov_len = 3;
363 iov[1].iov_base = (void *) scan_filename;
364 iov[1].iov_len = Ustrlen(scan_filename);
365 iov[2].iov_base = (void *) (cmd + 3);
366 iov[2].iov_len = 1;
367
368 if (mksd_writev (sock, iov, 3) < 0)
369   return DEFER;
370
371 if (mksd_read_lines (sock, av_buffer, sizeof (av_buffer), tmo) < 0)
372   return DEFER;
373
374 return mksd_parse_line (scanent, CS av_buffer);
375 }
376
377 /*************************************************
378 *          Scan content for malware              *
379 *************************************************/
380
381 /* This is an internal interface for scanning an email; the normal interface
382 is via malware(), or there's malware_in_file() used for testing/debugging.
383
384 Arguments:
385   malware_re    match condition for "malware="
386   eml_filename  the file holding the email to be scanned
387   timeout       if nonzero, non-default timeoutl
388   faking        whether or not we're faking this up for the -bmalware test
389
390 Returns:        Exim message processing code (OK, FAIL, DEFER, ...)
391                 where true means malware was found (condition applies)
392 */
393 static int
394 malware_internal(const uschar * malware_re, const uschar * eml_filename,
395   int timeout, BOOL faking)
396 {
397 int sep = 0;
398 uschar *av_scanner_work = av_scanner;
399 uschar *scanner_name;
400 unsigned long mbox_size;
401 FILE *mbox_file;
402 const pcre *re;
403 uschar * errstr;
404 struct scan * scanent;
405 const uschar * scanner_options;
406 int sock = -1;
407 time_t tmo;
408
409 /* make sure the eml mbox file is spooled up */
410 if (!(mbox_file = spool_mbox(&mbox_size, faking ? eml_filename : NULL)))
411   return malware_errlog_defer(US"error while creating mbox spool file");
412
413 /* none of our current scanners need the mbox
414    file as a stream, so we can close it right away */
415 (void)fclose(mbox_file);
416
417 if (!malware_re)
418   return FAIL;          /* empty means "don't match anything" */
419
420 /* parse 1st option */
421   if ( (strcmpic(malware_re, US"false") == 0) ||
422      (Ustrcmp(malware_re,"0") == 0) )
423   return FAIL;          /* explicitly no matching */
424
425 /* special cases (match anything except empty) */
426 if (  strcmpic(malware_re,US"true") == 0
427    || Ustrcmp(malware_re,"*") == 0
428    || Ustrcmp(malware_re,"1") == 0
429    )
430   {
431   if (  !malware_default_re
432      && !(malware_default_re = m_pcre_compile(malware_regex_default, &errstr)))
433     return malware_errlog_defer(errstr);
434   malware_re = malware_regex_default;
435   re = malware_default_re;
436   }
437
438 /* compile the regex, see if it works */
439 else if (!(re = m_pcre_compile(malware_re, &errstr)))
440   return malware_errlog_defer(errstr);
441
442 /* Reset sep that is set by previous string_nextinlist() call */
443 sep = 0;
444
445 /* if av_scanner starts with a dollar, expand it first */
446 if (*av_scanner == '$')
447   {
448   if (!(av_scanner_work = expand_string(av_scanner)))
449     return malware_errlog_defer(
450          string_sprintf("av_scanner starts with $, but expansion failed: %s",
451          expand_string_message));
452
453   DEBUG(D_acl)
454     debug_printf("Expanded av_scanner global: %s\n", av_scanner_work);
455   /* disable result caching in this case */
456   malware_name = NULL;
457   malware_ok = FALSE;
458   }
459
460 /* Do not scan twice (unless av_scanner is dynamic). */
461 if (!malware_ok)
462   {
463   /* find the scanner type from the av_scanner option */
464   if (!(scanner_name = string_nextinlist(&av_scanner_work, &sep, NULL, 0)))
465     return malware_errlog_defer(US"av_scanner configuration variable is empty");
466   if (!timeout) timeout = MALWARE_TIMEOUT;
467   tmo = time(NULL) + timeout;
468
469   for (scanent = m_scans; ; scanent++)
470     {
471     if (!scanent->name)
472       return malware_errlog_defer(string_sprintf("unknown scanner type '%s'",
473         scanner_name));
474     if (strcmpic(scanner_name, US scanent->name) != 0)
475       continue;
476     if (!(scanner_options = string_nextinlist(&av_scanner_work, &sep, NULL, 0)))
477       scanner_options = scanent->options_default;
478     if (scanent->conn == MC_NONE)
479       break;
480     switch(scanent->conn)
481     {
482     case MC_TCP:  sock = ip_tcpsocket(scanner_options, &errstr, 5);       break;
483     case MC_UNIX: sock = ip_unixsocket(scanner_options, &errstr);         break;
484     case MC_STRM: sock = ip_streamsocket(scanner_options, &errstr, 5);  break;
485     default: /* compiler quietening */ break;
486     }
487     if (sock < 0)
488       return m_errlog_defer(scanent, errstr);
489     break;
490   }
491   DEBUG(D_acl) debug_printf("Malware scan: %s tmo %s\n", scanner_name, readconf_printtime(timeout));
492
493   switch (scanent->scancode)
494     {
495     case M_FPROTD: /* "f-protd" scanner type -------------------------------- */
496       {
497       uschar *fp_scan_option;
498       unsigned int detected=0, par_count=0;
499       uschar * scanrequest;
500       uschar buf[32768], *strhelper, *strhelper2;
501       uschar * malware_name_internal = NULL;
502       int len;
503
504       scanrequest = string_sprintf("GET %s", eml_filename);
505
506       while ((fp_scan_option = string_nextinlist(&av_scanner_work, &sep,
507                             NULL, 0)))
508         {
509         scanrequest = string_sprintf("%s%s%s", scanrequest,
510                                   par_count ? "%20" : "?", fp_scan_option);
511         par_count++;
512         }
513       scanrequest = string_sprintf("%s HTTP/1.0\r\n\r\n", scanrequest);
514       DEBUG(D_acl) debug_printf("Malware scan: issuing %s: %s\n",
515         scanner_name, scanrequest);
516
517       /* send scan request */
518       if (m_sock_send(sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0)
519         return m_errlog_defer(scanent, errstr);
520
521       while ((len = recv_line(sock, buf, sizeof(buf), tmo)) >= 0)
522         if (len > 0)
523           {
524           if (Ustrstr(buf, US"<detected type=\"") != NULL)
525             detected = 1;
526           else if (detected && (strhelper = Ustrstr(buf, US"<name>")))
527             {
528             if ((strhelper2 = Ustrstr(buf, US"</name>")) != NULL)
529               {
530               *strhelper2 = '\0';
531               malware_name_internal = string_copy(strhelper+6);
532               }
533             }
534           else if (Ustrstr(buf, US"<summary code=\""))
535             {
536             malware_name = Ustrstr(buf, US"<summary code=\"11\">")
537                 ? malware_name_internal : NULL;
538             break;
539             }
540           }
541       if (len < -1)
542         {
543         (void)close(sock);
544         return DEFER;
545         }
546       break;
547       } /* f-protd */
548
549     case M_DRWEB: /* "drweb" scanner type ----------------------------------- */
550   /* v0.1 - added support for tcp sockets          */
551   /* v0.0 - initial release -- support for unix sockets      */
552       {
553       int result;
554       off_t fsize;
555       unsigned int fsize_uint;
556       uschar * tmpbuf, *drweb_fbuf;
557       int drweb_rc, drweb_cmd, drweb_flags = 0x0000, drweb_fd,
558           drweb_vnum, drweb_slen, drweb_fin = 0x0000;
559
560       /* prepare variables */
561       drweb_cmd = htonl(DRWEBD_SCAN_CMD);
562       drweb_flags = htonl(DRWEBD_RETURN_VIRUSES | DRWEBD_IS_MAIL);
563
564       if (*scanner_options != '/')
565         {
566         /* calc file size */
567         if ((drweb_fd = open(CCS eml_filename, O_RDONLY)) == -1)
568           return m_errlog_defer_3(scanent,
569             string_sprintf("can't open spool file %s: %s",
570               eml_filename, strerror(errno)),
571             sock);
572
573         if ((fsize = lseek(drweb_fd, 0, SEEK_END)) == -1)
574           {
575           int err = errno;
576           (void)close(drweb_fd);
577           return m_errlog_defer_3(scanent,
578             string_sprintf("can't seek spool file %s: %s",
579               eml_filename, strerror(err)),
580             sock);
581           }
582         fsize_uint = (unsigned int) fsize;
583         if ((off_t)fsize_uint != fsize)
584           {
585           (void)close(drweb_fd);
586           return m_errlog_defer_3(scanent,
587             string_sprintf("seeking spool file %s, size overflow",
588               eml_filename),
589             sock);
590           }
591         drweb_slen = htonl(fsize);
592         lseek(drweb_fd, 0, SEEK_SET);
593
594         DEBUG(D_acl) debug_printf("Malware scan: issuing %s remote scan [%s]\n",
595             scanner_name, scanner_options);
596
597         /* send scan request */
598         if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
599             (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
600             (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0) ||
601             (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0))
602           {
603           (void)close(drweb_fd);
604           return m_errlog_defer_3(scanent, string_sprintf(
605             "unable to send commands to socket (%s)", scanner_options),
606             sock);
607           }
608
609         if (!(drweb_fbuf = (uschar *) malloc (fsize_uint)))
610           {
611           (void)close(drweb_fd);
612           return m_errlog_defer_3(scanent,
613             string_sprintf("unable to allocate memory %u for file (%s)",
614               fsize_uint, eml_filename),
615             sock);
616           }
617
618         if ((result = read (drweb_fd, drweb_fbuf, fsize)) == -1)
619           {
620           int err = errno;
621           (void)close(drweb_fd);
622           free(drweb_fbuf);
623           return m_errlog_defer_3(scanent,
624             string_sprintf("can't read spool file %s: %s",
625               eml_filename, strerror(err)),
626             sock);
627           }
628         (void)close(drweb_fd);
629
630         /* send file body to socket */
631         if (send(sock, drweb_fbuf, fsize, 0) < 0)
632           {
633           free(drweb_fbuf);
634           return m_errlog_defer_3(scanent, string_sprintf(
635             "unable to send file body to socket (%s)", scanner_options),
636             sock);
637           }
638         (void)close(drweb_fd);
639         }
640       else
641         {
642         drweb_slen = htonl(Ustrlen(eml_filename));
643
644         DEBUG(D_acl) debug_printf("Malware scan: issuing %s local scan [%s]\n",
645             scanner_name, scanner_options);
646
647         /* send scan request */
648         if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
649             (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
650             (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0) ||
651             (send(sock, eml_filename, Ustrlen(eml_filename), 0) < 0) ||
652             (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0))
653           return m_errlog_defer_3(scanent, string_sprintf(
654             "unable to send commands to socket (%s)", scanner_options),
655             sock);
656         }
657
658       /* wait for result */
659       if (!recv_len(sock, &drweb_rc, sizeof(drweb_rc), tmo))
660         return m_errlog_defer_3(scanent,
661                     US"unable to read return code", sock);
662       drweb_rc = ntohl(drweb_rc);
663
664       if (!recv_len(sock, &drweb_vnum, sizeof(drweb_vnum), tmo))
665         return m_errlog_defer_3(scanent,
666                             US"unable to read the number of viruses", sock);
667       drweb_vnum = ntohl(drweb_vnum);
668
669       /* "virus(es) found" if virus number is > 0 */
670       if (drweb_vnum)
671         {
672         int i;
673
674         /* setup default virus name */
675         malware_name = US"unknown";
676
677         /* set up match regex */
678         if (!drweb_re)
679           drweb_re = m_pcre_compile(drweb_re_str, &errstr);
680
681         /* read and concatenate virus names into one string */
682         for (i = 0; i < drweb_vnum; i++)
683           {
684           int size = 0, off = 0, ovector[10*3];
685           /* read the size of report */
686           if (!recv_len(sock, &drweb_slen, sizeof(drweb_slen), tmo))
687             return m_errlog_defer_3(scanent,
688                               US"cannot read report size", sock);
689           drweb_slen = ntohl(drweb_slen);
690           tmpbuf = store_get(drweb_slen);
691
692           /* read report body */
693           if (!recv_len(sock, tmpbuf, drweb_slen, tmo))
694             return m_errlog_defer_3(scanent,
695                               US"cannot read report string", sock);
696           tmpbuf[drweb_slen] = '\0';
697
698           /* try matcher on the line, grab substring */
699           result = pcre_exec(drweb_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0,
700                                   ovector, nelements(ovector));
701           if (result >= 2)
702             {
703             const char * pre_malware_nb;
704
705             pcre_get_substring(CS tmpbuf, ovector, result, 1, &pre_malware_nb);
706
707             if (i==0)   /* the first name we just copy to malware_name */
708               malware_name = string_append(NULL, &size, &off,
709                                           1, pre_malware_nb);
710
711             else        /* concatenate each new virus name to previous */
712               malware_name = string_append(malware_name, &size, &off,
713                                           2, "/", pre_malware_nb);
714
715             pcre_free_substring(pre_malware_nb);
716             }
717           }
718         }
719       else
720         {
721         const char *drweb_s = NULL;
722
723         if (drweb_rc & DERR_READ_ERR) drweb_s = "read error";
724         if (drweb_rc & DERR_NOMEMORY) drweb_s = "no memory";
725         if (drweb_rc & DERR_TIMEOUT)  drweb_s = "timeout";
726         if (drweb_rc & DERR_BAD_CALL) drweb_s = "wrong command";
727         /* retcodes DERR_SYMLINK, DERR_NO_REGFILE, DERR_SKIPPED.
728          * DERR_TOO_BIG, DERR_TOO_COMPRESSED, DERR_SPAM,
729          * DERR_CRC_ERROR, DERR_READSOCKET, DERR_WRITE_ERR
730          * and others are ignored */
731         if (drweb_s)
732           return m_errlog_defer_3(scanent,
733             string_sprintf("drweb daemon retcode 0x%x (%s)", drweb_rc, drweb_s),
734             sock);
735
736         /* no virus found */
737         malware_name = NULL;
738         }
739       break;
740       } /* drweb */
741
742     case M_AVES: /* "aveserver" scanner type -------------------------------- */
743       {
744       uschar buf[32768];
745       int result;
746
747       /* read aveserver's greeting and see if it is ready (2xx greeting) */
748       buf[0] = 0;
749       recv_line(sock, buf, sizeof(buf), tmo);
750
751       if (buf[0] != '2')                /* aveserver is having problems */
752         return m_errlog_defer_3(scanent,
753           string_sprintf("unavailable (Responded: %s).",
754                           ((buf[0] != 0) ? buf : (uschar *)"nothing") ),
755           sock);
756
757       /* prepare our command */
758       (void)string_format(buf, sizeof(buf), "SCAN bPQRSTUW %s\r\n",
759                                                 eml_filename);
760
761       /* and send it */
762       DEBUG(D_acl) debug_printf("Malware scan: issuing %s %s\n",
763         scanner_name, buf);
764       if (m_sock_send(sock, buf, Ustrlen(buf), &errstr) < 0)
765         return m_errlog_defer(scanent, errstr);
766
767       malware_name = NULL;
768       result = 0;
769       /* read response lines, find malware name and final response */
770       while (recv_line(sock, buf, sizeof(buf), tmo) > 0)
771         {
772         if (buf[0] == '2')
773           break;
774         if (buf[0] == '5')              /* aveserver is having problems */
775           {
776           result = m_errlog_defer(scanent,
777              string_sprintf("unable to scan file %s (Responded: %s).",
778                              eml_filename, buf));
779           break;
780           }
781         if (Ustrncmp(buf,"322",3) == 0)
782           {
783           uschar *p = Ustrchr(&buf[4], ' ');
784           *p = '\0';
785           malware_name = string_copy(&buf[4]);
786           }
787         }
788
789       if (m_sock_send(sock, US"quit\r\n", 6, &errstr) < 0)
790         return m_errlog_defer(scanent, errstr);
791
792       /* read aveserver's greeting and see if it is ready (2xx greeting) */
793       buf[0] = 0;
794       recv_line(sock, buf, sizeof(buf), tmo);
795
796       if (buf[0] != '2')                /* aveserver is having problems */
797         return m_errlog_defer_3(scanent,
798           string_sprintf("unable to quit dialogue (Responded: %s).",
799                         ((buf[0] != 0) ? buf : (uschar *)"nothing") ),
800           sock);
801
802       if (result == DEFER)
803         {
804         (void)close(sock);
805         return DEFER;
806         }
807       break;
808       } /* aveserver */
809
810     case M_FSEC: /* "fsecure" scanner type ---------------------------------- */
811       {
812       int i, j, bread = 0;
813       uschar * file_name;
814       uschar av_buffer[1024];
815       static uschar *cmdopt[] = { US"CONFIGURE\tARCHIVE\t1\n",
816                                       US"CONFIGURE\tTIMEOUT\t0\n",
817                                       US"CONFIGURE\tMAXARCH\t5\n",
818                                       US"CONFIGURE\tMIME\t1\n" };
819
820       malware_name = NULL;
821
822       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan [%s]\n",
823           scanner_name, scanner_options);
824       /* pass options */
825       memset(av_buffer, 0, sizeof(av_buffer));
826       for (i = 0; i != nelements(cmdopt); i++)
827         {
828
829         if (m_sock_send(sock, cmdopt[i], Ustrlen(cmdopt[i]), &errstr) < 0)
830           return m_errlog_defer(scanent, errstr);
831
832         bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL));
833         if (bread > 0) av_buffer[bread]='\0';
834         if (bread < 0)
835           return m_errlog_defer_3(scanent,
836             string_sprintf("unable to read answer %d (%s)", i, strerror(errno)),
837             sock);
838         for (j = 0; j < bread; j++)
839           if (av_buffer[j] == '\r' || av_buffer[j] == '\n')
840             av_buffer[j] ='@';
841         }
842
843       /* pass the mailfile to fsecure */
844       file_name = string_sprintf("SCAN\t%s\n", eml_filename);
845
846       if (m_sock_send(sock, file_name, Ustrlen(file_name), &errstr) < 0)
847         return m_errlog_defer(scanent, errstr);
848
849       /* set up match */
850       /* todo also SUSPICION\t */
851       if (!fsec_re)
852         fsec_re = m_pcre_compile(fsec_re_str, &errstr);
853
854       /* read report, linewise. Apply a timeout as the Fsecure daemon
855       sometimes wants an answer to "PING" but they won't tell us what */
856         {
857         uschar * p = av_buffer;
858         uschar * q;
859
860         for (;;)
861           {
862           errno = ETIME;
863           i =  av_buffer+sizeof(av_buffer)-p;
864           if ((bread= ip_recv(sock, p, i-1, tmo-time(NULL))) < 0)
865             return m_errlog_defer_3(scanent,
866               string_sprintf("unable to read result (%s)", strerror(errno)),
867               sock);
868
869           for (p[bread] = '\0'; q = strchr(p, '\n'); p = q+1)
870             {
871             *q = '\0';
872
873             /* Really search for virus again? */
874             if (!malware_name)
875               /* try matcher on the line, grab substring */
876               malware_name = m_pcre_exec(fsec_re, p);
877
878             if (Ustrstr(p, "OK\tScan ok."))
879               goto fsec_found;
880             }
881
882           /* copy down the trailing partial line then read another chunk */
883           i =  av_buffer+sizeof(av_buffer)-p;
884           memmove(av_buffer, p, i);
885           p = av_buffer+i;
886           }
887         }
888
889       fsec_found:
890         break;
891       } /* fsecure */
892
893     case M_KAVD: /* "kavdaemon" scanner type -------------------------------- */
894       {
895       time_t t;
896       uschar tmpbuf[1024];
897       uschar * scanrequest;
898       int kav_rc;
899       unsigned long kav_reportlen, bread;
900       const pcre *kav_re;
901       uschar *p;
902
903       /* get current date and time, build scan request */
904       time(&t);
905       /* pdp note: before the eml_filename parameter, this scanned the
906       directory; not finding documentation, so we'll strip off the directory.
907       The side-effect is that the test framework scanning may end up in
908       scanning more than was requested, but for the normal interface, this is
909       fine. */
910
911       strftime(CS tmpbuf, sizeof(tmpbuf), "%d %b %H:%M:%S", localtime(&t));
912       scanrequest = string_sprintf("<0>%s:%s", CS tmpbuf, eml_filename);
913       p = Ustrrchr(scanrequest, '/');
914       if (p)
915         *p = '\0';
916
917       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan [%s]\n",
918           scanner_name, scanner_options);
919
920       /* send scan request */
921       if (m_sock_send(sock, scanrequest, Ustrlen(scanrequest)+1, &errstr) < 0)
922         return m_errlog_defer(scanent, errstr);
923
924       /* wait for result */
925       if (!recv_len(sock, tmpbuf, 2, tmo))
926         return m_errlog_defer_3(scanent,
927                             US"unable to read 2 bytes from socket.", sock);
928
929       /* get errorcode from one nibble */
930       kav_rc = tmpbuf[ test_byte_order()==LITTLE_MY_ENDIAN ? 0 : 1 ] & 0x0F;
931       switch(kav_rc)
932       {
933       case 5: case 6: /* improper kavdaemon configuration */
934         return m_errlog_defer_3(scanent,
935                 US"please reconfigure kavdaemon to NOT disinfect or remove infected files.",
936                 sock);
937       case 1:
938         return m_errlog_defer_3(scanent,
939                 US"reported 'scanning not completed' (code 1).", sock);
940       case 7:
941         return m_errlog_defer_3(scanent,
942                 US"reported 'kavdaemon damaged' (code 7).", sock);
943       }
944
945       /* code 8 is not handled, since it is ambigous. It appears mostly on
946       bounces where part of a file has been cut off */
947
948       /* "virus found" return codes (2-4) */
949       if (kav_rc > 1 && kav_rc < 5)
950         {
951         int report_flag = 0;
952
953         /* setup default virus name */
954         malware_name = US"unknown";
955
956         report_flag = tmpbuf[ test_byte_order() == LITTLE_MY_ENDIAN ? 1 : 0 ];
957
958         /* read the report, if available */
959         if (report_flag == 1)
960           {
961           /* read report size */
962           if (!recv_len(sock, &kav_reportlen, 4, tmo))
963             return m_errlog_defer_3(scanent,
964                   US"cannot read report size", sock);
965
966           /* it's possible that avp returns av_buffer[1] == 1 but the
967           reportsize is 0 (!?) */
968           if (kav_reportlen > 0)
969             {
970             /* set up match regex, depends on retcode */
971             if (kav_rc == 3)
972               {
973               if (!kav_re_sus) kav_re_sus = m_pcre_compile(kav_re_sus_str, &errstr);
974               kav_re = kav_re_sus;
975               }
976             else
977               {
978               if (!kav_re_inf) kav_re_inf = m_pcre_compile(kav_re_inf_str, &errstr);
979               kav_re = kav_re_inf;
980               }
981
982             /* read report, linewise */
983             while (kav_reportlen > 0)
984               {
985               if ((bread = recv_line(sock, tmpbuf, sizeof(tmpbuf), tmo)) < 0)
986                 break;
987               kav_reportlen -= bread+1;
988
989               /* try matcher on the line, grab substring */
990               if ((malware_name = m_pcre_exec(kav_re, tmpbuf)))
991                 break;
992               }
993             }
994           }
995         }
996       else /* no virus found */
997         malware_name = NULL;
998
999       break;
1000       }
1001
1002     case M_CMDL: /* "cmdline" scanner type ---------------------------------- */
1003       {
1004       const uschar *cmdline_scanner = scanner_options;
1005       const pcre *cmdline_trigger_re;
1006       const pcre *cmdline_regex_re;
1007       uschar * file_name;
1008       uschar * commandline;
1009       void (*eximsigchld)(int);
1010       void (*eximsigpipe)(int);
1011       FILE *scanner_out = NULL;
1012       int scanner_fd;
1013       FILE *scanner_record = NULL;
1014       uschar linebuffer[32767];
1015       int rcnt;
1016       int trigger = 0;
1017       uschar *p;
1018
1019       if (!cmdline_scanner)
1020         return m_errlog_defer(scanent, errstr);
1021
1022       /* find scanner output trigger */
1023       cmdline_trigger_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1024                                 "missing trigger specification", &errstr);
1025       if (!cmdline_trigger_re)
1026         return m_errlog_defer(scanent, errstr);
1027
1028       /* find scanner name regex */
1029       cmdline_regex_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1030                           "missing virus name regex specification", &errstr);
1031       if (!cmdline_regex_re)
1032         return m_errlog_defer(scanent, errstr);
1033
1034       /* prepare scanner call; despite the naming, file_name holds a directory
1035       name which is documented as the value given to %s. */
1036
1037       file_name = string_copy(eml_filename);
1038       p = Ustrrchr(file_name, '/');
1039       if (p)
1040         *p = '\0';
1041       commandline = string_sprintf(CS cmdline_scanner, file_name);
1042
1043       /* redirect STDERR too */
1044       commandline = string_sprintf("%s 2>&1", commandline);
1045
1046       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan [%s]\n",
1047               scanner_name, commandline);
1048
1049       /* store exims signal handlers */
1050       eximsigchld = signal(SIGCHLD,SIG_DFL);
1051       eximsigpipe = signal(SIGPIPE,SIG_DFL);
1052
1053       if (!(scanner_out = popen(CS commandline,"r")))
1054         {
1055         int err = errno;
1056         signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
1057         return m_errlog_defer(scanent,
1058           string_sprintf("call (%s) failed: %s.", commandline, strerror(err)));
1059         }
1060       scanner_fd = fileno(scanner_out);
1061
1062       file_name = string_sprintf("%s/scan/%s/%s_scanner_output",
1063                                 spool_directory, message_id, message_id);
1064
1065       if (!(scanner_record = modefopen(file_name, "wb", SPOOL_MODE)))
1066         {
1067         int err = errno;
1068         (void) pclose(scanner_out);
1069         signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
1070         return m_errlog_defer(scanent, string_sprintf(
1071             "opening scanner output file (%s) failed: %s.",
1072             file_name, strerror(err)));
1073         }
1074
1075       /* look for trigger while recording output */
1076       while ((rcnt = recv_line(scanner_fd, linebuffer,
1077                       sizeof(linebuffer), tmo)))
1078         {
1079         if (rcnt < 0)
1080           if (rcnt == -1)
1081             break;
1082           else
1083             {
1084             int err = errno;
1085             (void) pclose(scanner_out);
1086             signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
1087             return m_errlog_defer(scanent, string_sprintf(
1088                 "unable to read from scanner (%s): %s",
1089                 commandline, strerror(err)));
1090             }
1091
1092         if (Ustrlen(linebuffer) > fwrite(linebuffer, 1, Ustrlen(linebuffer), scanner_record))
1093           {
1094           /* short write */
1095           (void) pclose(scanner_out);
1096           signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
1097           return m_errlog_defer(scanent, string_sprintf(
1098             "short write on scanner output file (%s).", file_name));
1099           }
1100         putc('\n', scanner_record);
1101         /* try trigger match */
1102         if (  !trigger
1103            && regex_match_and_setup(cmdline_trigger_re, linebuffer, 0, -1)
1104            )
1105           trigger = 1;
1106         }
1107
1108       (void)fclose(scanner_record);
1109       sep = pclose(scanner_out);
1110       signal(SIGCHLD,eximsigchld); signal(SIGPIPE,eximsigpipe);
1111       if (sep != 0)
1112           return m_errlog_defer(scanent,
1113               sep == -1
1114               ? string_sprintf("running scanner failed: %s", strerror(sep))
1115               : string_sprintf("scanner returned error code: %d", sep));
1116
1117       if (trigger)
1118         {
1119         uschar * s;
1120         /* setup default virus name */
1121         malware_name = US"unknown";
1122
1123         /* re-open the scanner output file, look for name match */
1124         scanner_record = fopen(CS file_name, "rb");
1125         while (fgets(CS linebuffer, sizeof(linebuffer), scanner_record))
1126           {
1127           /* try match */
1128           if ((s = m_pcre_exec(cmdline_regex_re, linebuffer)))
1129             malware_name = s;
1130           }
1131         (void)fclose(scanner_record);
1132         }
1133       else /* no virus found */
1134         malware_name = NULL;
1135       break;
1136       } /* cmdline */
1137
1138     case M_SOPHIE: /* "sophie" scanner type --------------------------------- */
1139       {
1140       int bread = 0;
1141       uschar *p;
1142       uschar * file_name;
1143       uschar av_buffer[1024];
1144
1145       /* pass the scan directory to sophie */
1146       file_name = string_copy(eml_filename);
1147       if ((p = Ustrrchr(file_name, '/')))
1148         *p = '\0';
1149
1150       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan [%s]\n",
1151           scanner_name, scanner_options);
1152
1153       if (  write(sock, file_name, Ustrlen(file_name)) < 0
1154          || write(sock, "\n", 1) != 1
1155          )
1156         return m_errlog_defer_3(scanent,
1157           string_sprintf("unable to write to UNIX socket (%s)", scanner_options),
1158           sock);
1159
1160       /* wait for result */
1161       memset(av_buffer, 0, sizeof(av_buffer));
1162       if ((bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL))) <= 0)
1163         return m_errlog_defer_3(scanent,
1164           string_sprintf("unable to read from UNIX socket (%s)", scanner_options),
1165           sock);
1166
1167       /* infected ? */
1168       if (av_buffer[0] == '1') {
1169         uschar * s = Ustrchr(av_buffer, '\n');
1170         if (s)
1171           *s = '\0';
1172         malware_name = string_copy(&av_buffer[2]);
1173       }
1174       else if (!strncmp(CS av_buffer, "-1", 2))
1175         return m_errlog_defer_3(scanent, US"scanner reported error", sock);
1176       else /* all ok, no virus */
1177         malware_name = NULL;
1178
1179       break;
1180       }
1181
1182     case M_CLAMD: /* "clamd" scanner type ----------------------------------- */
1183       {
1184 /* This code was originally contributed by David Saez */
1185 /* There are three scanning methods available to us:
1186 *  (1) Use the SCAN command, pointing to a file in the filesystem
1187 *  (2) Use the STREAM command, send the data on a separate port
1188 *  (3) Use the zINSTREAM command, send the data inline
1189 * The zINSTREAM command was introduced with ClamAV 0.95, which marked
1190 * STREAM deprecated; see: http://wiki.clamav.net/bin/view/Main/UpgradeNotes095
1191 * In Exim, we use SCAN if using a Unix-domain socket or explicitly told that
1192 * the TCP-connected daemon is actually local; otherwise we use zINSTREAM unless
1193 * WITH_OLD_CLAMAV_STREAM is defined.
1194 * See Exim bug 926 for details.  */
1195
1196       uschar *p, *vname, *result_tag, *response_end;
1197       int bread=0;
1198       uschar * file_name;
1199       uschar av_buffer[1024];
1200       uschar *hostname = US"";
1201       host_item connhost;
1202       uschar *clamav_fbuf;
1203       int clam_fd, result;
1204       off_t fsize;
1205       unsigned int fsize_uint;
1206       BOOL use_scan_command = FALSE;
1207       clamd_address_container * clamd_address_vector[MAX_CLAMD_SERVERS];
1208       int num_servers = 0;
1209 #ifdef WITH_OLD_CLAMAV_STREAM
1210       unsigned int port;
1211       uschar av_buffer2[1024];
1212       int sockData;
1213 #else
1214       uint32_t send_size, send_final_zeroblock;
1215 #endif
1216
1217       if (*scanner_options == '/')
1218         /* Local file; so we def want to use_scan_command and don't want to try
1219          * passing IP/port combinations */
1220         use_scan_command = TRUE;
1221       else
1222         {
1223         const uschar *address = scanner_options;
1224         uschar address_buffer[MAX_CLAMD_ADDRESS_LENGTH + 20];
1225
1226         /* Go through the rest of the list of host/port and construct an array
1227          * of servers to try. The first one is the bit we just passed from
1228          * scanner_options so process that first and then scan the remainder of
1229          * the address buffer */
1230         do
1231           {
1232           clamd_address_container *this_clamd;
1233
1234           /* The 'local' option means use the SCAN command over the network
1235            * socket (ie common file storage in use) */
1236           if (strcmpic(address,US"local") == 0)
1237             {
1238             use_scan_command = TRUE;
1239             continue;
1240             }
1241
1242           /* XXX: If unsuccessful we should free this memory */
1243           this_clamd =
1244               (clamd_address_container *)store_get(sizeof(clamd_address_container));
1245
1246           /* extract host and port part */
1247           if( sscanf(CS address, "%" MAX_CLAMD_ADDRESS_LENGTH_S "s %u",
1248                  this_clamd->tcp_addr, &(this_clamd->tcp_port)) != 2 )
1249             {
1250             (void) m_errlog_defer(scanent,
1251                         string_sprintf("invalid address '%s'", address));
1252             continue;
1253             }
1254
1255           clamd_address_vector[num_servers] = this_clamd;
1256           num_servers++;
1257           if (num_servers >= MAX_CLAMD_SERVERS)
1258             {
1259             (void) m_errlog_defer(scanent,
1260                   US"More than " MAX_CLAMD_SERVERS_S " clamd servers "
1261                   "specified; only using the first " MAX_CLAMD_SERVERS_S );
1262             break;
1263             }
1264           } while ((address = string_nextinlist(&av_scanner_work, &sep,
1265                                         address_buffer,
1266                                         sizeof(address_buffer))) != NULL);
1267
1268         /* check if we have at least one server */
1269         if (!num_servers)
1270           return m_errlog_defer(scanent,
1271             US"no useable server addresses in malware configuration option.");
1272         }
1273
1274       /* See the discussion of response formats below to see why we really
1275       don't like colons in filenames when passing filenames to ClamAV. */
1276       if (use_scan_command && Ustrchr(eml_filename, ':'))
1277         return m_errlog_defer(scanent,
1278           string_sprintf("local/SCAN mode incompatible with" \
1279             " : in path to email filename [%s]", eml_filename));
1280
1281       /* We have some network servers specified */
1282       if (num_servers)
1283         {
1284         /* Confirmed in ClamAV source (0.95.3) that the TCPAddr option of clamd
1285          * only supports AF_INET, but we should probably be looking to the
1286          * future and rewriting this to be protocol-independent anyway. */
1287
1288         while (num_servers > 0)
1289           {
1290           int i;
1291           int current_server = random_number( num_servers );
1292
1293           DEBUG(D_acl)
1294             debug_printf("trying server name %s, port %u\n",
1295                        clamd_address_vector[current_server]->tcp_addr,
1296                        clamd_address_vector[current_server]->tcp_port);
1297
1298           /* Lookup the host. This is to ensure that we connect to the same IP
1299            * on both connections (as one host could resolve to multiple ips) */
1300           sock= m_tcpsocket(clamd_address_vector[current_server]->tcp_addr,
1301                               clamd_address_vector[current_server]->tcp_port,
1302                               &connhost, &errstr);
1303           if (sock >= 0)
1304             {
1305             /* Connection successfully established with a server */
1306             hostname = clamd_address_vector[current_server]->tcp_addr;
1307             break;
1308             }
1309
1310           log_write(0, LOG_MAIN, "malware acl condition: %s: %s",
1311             scanent->name, errstr);
1312
1313           /* Remove the server from the list. XXX We should free the memory */
1314           num_servers--;
1315           for (i = current_server; i < num_servers; i++)
1316             clamd_address_vector[i] = clamd_address_vector[i+1];
1317           }
1318
1319         if (num_servers == 0)
1320           return m_errlog_defer(scanent, US"all servers failed");
1321         }
1322       else
1323         {
1324         if ((sock = ip_unixsocket(scanner_options, &errstr)) < 0)
1325           return m_errlog_defer(scanent, errstr);
1326         }
1327
1328       /* have socket in variable "sock"; command to use is semi-independent of
1329        * the socket protocol.  We use SCAN if is local (either Unix/local
1330        * domain socket, or explicitly told local) else we stream the data.
1331        * How we stream the data depends upon how we were built.  */
1332
1333       if (!use_scan_command)
1334         {
1335 #ifdef WITH_OLD_CLAMAV_STREAM
1336         /* "STREAM\n" command, get back a "PORT <N>\n" response, send data to
1337          * that port on a second connection; then in the scan-method-neutral
1338          * part, read the response back on the original connection. */
1339
1340         DEBUG(D_acl) debug_printf(
1341             "Malware scan: issuing %s old-style remote scan (PORT)\n",
1342             scanner_name);
1343
1344         /* Pass the string to ClamAV (7 = "STREAM\n") */
1345         if (m_sock_send(sock, US"STREAM\n", 7, &errstr) < 0)
1346           return m_errlog_defer(scanent, errstr);
1347
1348         memset(av_buffer2, 0, sizeof(av_buffer2));
1349         bread = ip_recv(sock, av_buffer2, sizeof(av_buffer2), tmo-time(NULL));
1350
1351         if (bread < 0)
1352           return m_errlog_defer_3(scanent,
1353             string_sprintf("unable to read PORT from socket (%s)",
1354                 strerror(errno)),
1355             sock);
1356
1357         if (bread == sizeof(av_buffer2))
1358           return m_errlog_defer_3(scanent, "buffer too small", sock);
1359
1360         if (!(*av_buffer2))
1361           return m_errlog_defer_3(scanent, "ClamAV returned null", sock);
1362
1363         av_buffer2[bread] = '\0';
1364         if( sscanf(CS av_buffer2, "PORT %u\n", &port) != 1 )
1365           return m_errlog_defer_3(scanent,
1366             string_sprintf("Expected port information from clamd, got '%s'",
1367               av_buffer2),
1368             sock);
1369
1370         sockData = m_tcpsocket(connhost.address, port, NULL, &errstr);
1371         if (sockData < 0)
1372           return m_errlog_defer_3(scanent, errstr, sock);
1373
1374 # define CLOSE_SOCKDATA (void)close(sockData)
1375 #else /* WITH_OLD_CLAMAV_STREAM not defined */
1376         /* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
1377         chunks, <n> a 4-byte number (network order), terminated by a zero-length
1378         chunk. */
1379
1380         DEBUG(D_acl) debug_printf(
1381             "Malware scan: issuing %s new-style remote scan (zINSTREAM)\n",
1382             scanner_name);
1383
1384         /* Pass the string to ClamAV (10 = "zINSTREAM\0") */
1385         if (send(sock, "zINSTREAM", 10, 0) < 0)
1386           return m_errlog_defer_3(scanent,
1387             string_sprintf("unable to send zINSTREAM to socket (%s)",
1388               strerror(errno)),
1389             sock);
1390
1391 # define CLOSE_SOCKDATA /**/
1392 #endif
1393
1394         /* calc file size */
1395         if ((clam_fd = open(CS eml_filename, O_RDONLY)) < 0)
1396           {
1397           int err = errno;
1398           CLOSE_SOCKDATA;
1399           return m_errlog_defer_3(scanent,
1400             string_sprintf("can't open spool file %s: %s",
1401               eml_filename, strerror(err)),
1402             sock);
1403           }
1404         if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0)
1405           {
1406           int err = errno;
1407           CLOSE_SOCKDATA; (void)close(clam_fd);
1408           return m_errlog_defer_3(scanent,
1409             string_sprintf("can't seek spool file %s: %s",
1410               eml_filename, strerror(err)),
1411             sock);
1412           }
1413         fsize_uint = (unsigned int) fsize;
1414         if ((off_t)fsize_uint != fsize)
1415           {
1416           CLOSE_SOCKDATA; (void)close(clam_fd);
1417           return m_errlog_defer_3(scanent,
1418             string_sprintf("seeking spool file %s, size overflow",
1419               eml_filename),
1420             sock);
1421           }
1422         lseek(clam_fd, 0, SEEK_SET);
1423
1424         if (!(clamav_fbuf = (uschar *) malloc (fsize_uint)))
1425           {
1426           CLOSE_SOCKDATA; (void)close(clam_fd);
1427           return m_errlog_defer_3(scanent,
1428             string_sprintf("unable to allocate memory %u for file (%s)",
1429               fsize_uint, eml_filename),
1430             sock);
1431           }
1432
1433         if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
1434           {
1435           int err = errno;
1436           free(clamav_fbuf); CLOSE_SOCKDATA; (void)close(clam_fd);
1437           return m_errlog_defer_3(scanent,
1438             string_sprintf("can't read spool file %s: %s",
1439               eml_filename, strerror(err)),
1440             sock);
1441           }
1442         (void)close(clam_fd);
1443
1444         /* send file body to socket */
1445 #ifdef WITH_OLD_CLAMAV_STREAM
1446         if (send(sockData, clamav_fbuf, fsize_uint, 0) < 0)
1447           {
1448           free(clamav_fbuf); CLOSE_SOCKDATA;
1449           return m_errlog_defer_3(scanent,
1450             string_sprintf("unable to send file body to socket (%s:%u)",
1451               hostname, port),
1452             sock);
1453           }
1454 #else
1455         send_size = htonl(fsize_uint);
1456         send_final_zeroblock = 0;
1457         if ((send(sock, &send_size, sizeof(send_size), 0) < 0) ||
1458             (send(sock, clamav_fbuf, fsize_uint, 0) < 0) ||
1459             (send(sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
1460           {
1461           free(clamav_fbuf);
1462           return m_errlog_defer_3(scanent,
1463             string_sprintf("unable to send file body to socket (%s)", hostname),
1464             sock);
1465           }
1466 #endif
1467
1468         free(clamav_fbuf);
1469
1470         CLOSE_SOCKDATA;
1471 #undef CLOSE_SOCKDATA
1472         }
1473       else
1474         { /* use scan command */
1475         /* Send a SCAN command pointing to a filename; then in the then in the
1476          * scan-method-neutral part, read the response back */
1477
1478 /* ================================================================= */
1479
1480         /* Prior to the reworking post-Exim-4.72, this scanned a directory,
1481         which dates to when ClamAV needed us to break apart the email into the
1482         MIME parts (eg, with the now deprecated demime condition coming first).
1483         Some time back, ClamAV gained the ability to deconstruct the emails, so
1484         doing this would actually have resulted in the mail attachments being
1485         scanned twice, in the broken out files and from the original .eml.
1486         Since ClamAV now handles emails (and has for quite some time) we can
1487         just use the email file itself. */
1488         /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
1489         file_name = string_sprintf("SCAN %s\n", eml_filename);
1490
1491         DEBUG(D_acl) debug_printf(
1492             "Malware scan: issuing %s local-path scan [%s]\n",
1493             scanner_name, scanner_options);
1494
1495         if (send(sock, file_name, Ustrlen(file_name), 0) < 0)
1496           return m_errlog_defer_3(scanent,
1497             string_sprintf("unable to write to socket (%s)", strerror(errno)),
1498             sock);
1499
1500         /* Do not shut down the socket for writing; a user report noted that
1501          * clamd 0.70 does not react well to this. */
1502         }
1503       /* Commands have been sent, no matter which scan method or connection
1504        * type we're using; now just read the result, independent of method. */
1505
1506       /* Read the result */
1507       memset(av_buffer, 0, sizeof(av_buffer));
1508       bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL));
1509       (void)close(sock);
1510       sock = -1;
1511
1512       if (bread <= 0)
1513         return m_errlog_defer(scanent,
1514           string_sprintf("unable to read from socket (%s)",
1515           errno == 0 ? "EOF" : strerror(errno)));
1516
1517       if (bread == sizeof(av_buffer))
1518         return m_errlog_defer(scanent, US"buffer too small");
1519       /* We're now assured of a NULL at the end of av_buffer */
1520
1521       /* Check the result. ClamAV returns one of two result formats.
1522       In the basic mode, the response is of the form:
1523         infected: -> "<filename>: <virusname> FOUND"
1524         not-infected: -> "<filename>: OK"
1525         error: -> "<filename>: <errcode> ERROR
1526       If the ExtendedDetectionInfo option has been turned on, then we get:
1527         "<filename>: <virusname>(<virushash>:<virussize>) FOUND"
1528       for the infected case.  Compare:
1529 /tmp/eicar.com: Eicar-Test-Signature FOUND
1530 /tmp/eicar.com: Eicar-Test-Signature(44d88612fea8a8f36de82e1278abb02f:68) FOUND
1531
1532       In the streaming case, clamd uses the filename "stream" which you should
1533       be able to verify with { ktrace clamdscan --stream /tmp/eicar.com }.  (The
1534       client app will replace "stream" with the original filename before returning
1535       results to stdout, but the trace shows the data).
1536
1537       We will assume that the pathname passed to clamd from Exim does not contain
1538       a colon.  We will have whined loudly above if the eml_filename does (and we're
1539       passing a filename to clamd). */
1540
1541       if (!(*av_buffer))
1542         return m_errlog_defer(scanent, US"ClamAV returned null");
1543
1544       /* strip newline at the end (won't be present for zINSTREAM)
1545       (also any trailing whitespace, which shouldn't exist, but we depend upon
1546       this below, so double-check) */
1547       p = av_buffer + Ustrlen(av_buffer) - 1;
1548       if (*p == '\n') *p = '\0';
1549
1550       DEBUG(D_acl) debug_printf("Malware response: %s\n", av_buffer);
1551
1552       while (isspace(*--p) && (p > av_buffer))
1553         *p = '\0';
1554       if (*p) ++p;
1555       response_end = p;
1556
1557       /* colon in returned output? */
1558       if((p = Ustrchr(av_buffer,':')) == NULL)
1559         return m_errlog_defer(scanent, string_sprintf(
1560                   "ClamAV returned malformed result (missing colon): %s",
1561                   av_buffer));
1562
1563       /* strip filename */
1564       while (*p && isspace(*++p)) /**/;
1565       vname = p;
1566
1567       /* It would be bad to encounter a virus with "FOUND" in part of the name,
1568       but we should at least be resistant to it. */
1569       p = Ustrrchr(vname, ' ');
1570       result_tag = p ? p+1 : vname;
1571
1572       if (Ustrcmp(result_tag, "FOUND") == 0)
1573         {
1574         /* p should still be the whitespace before the result_tag */
1575         while (isspace(*p)) --p;
1576         *++p = '\0';
1577         /* Strip off the extended information too, which will be in parens
1578         after the virus name, with no intervening whitespace. */
1579         if (*--p == ')')
1580           {
1581           /* "(hash:size)", so previous '(' will do; if not found, we have
1582           a curious virus name, but not an error. */
1583           p = Ustrrchr(vname, '(');
1584           if (p)
1585             *p = '\0';
1586           }
1587         malware_name = string_copy(vname);
1588         DEBUG(D_acl) debug_printf("Malware found, name \"%s\"\n", malware_name);
1589
1590         }
1591       else if (Ustrcmp(result_tag, "ERROR") == 0)
1592         return m_errlog_defer(scanent,
1593           string_sprintf("ClamAV returned: %s", av_buffer));
1594
1595       else if (Ustrcmp(result_tag, "OK") == 0)
1596         {
1597         /* Everything should be OK */
1598         malware_name = NULL;
1599         DEBUG(D_acl) debug_printf("Malware not found\n");
1600
1601         }
1602       else
1603         return m_errlog_defer(scanent,
1604           string_sprintf("unparseable response from ClamAV: {%s}", av_buffer));
1605
1606       break;
1607       } /* clamd */
1608
1609     case M_SOCK: /* "sock" scanner type ------------------------------------- */
1610     /* This code was derived by Martin Poole from the clamd code contributed
1611        by David Saez and the cmdline code
1612     */
1613       {
1614       int bread;
1615       uschar * commandline;
1616       uschar av_buffer[1024];
1617       uschar * linebuffer;
1618       uschar * sockline_scanner;
1619       uschar sockline_scanner_default[] = "%s\n";
1620       const pcre *sockline_trig_re;
1621       const pcre *sockline_name_re;
1622
1623       /* find scanner command line */
1624       if ((sockline_scanner = string_nextinlist(&av_scanner_work, &sep,
1625                                           NULL, 0)))
1626       { /* check for no expansions apart from one %s */
1627         uschar * s = Ustrchr(sockline_scanner, '%');
1628         if (s++)
1629           if ((*s != 's' && *s != '%') || Ustrchr(s+1, '%'))
1630             return m_errlog_defer_3(scanent,
1631                                   US"unsafe sock scanner call spec", sock);
1632       }
1633       else
1634         sockline_scanner = sockline_scanner_default;
1635
1636       /* find scanner output trigger */
1637       sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1638                                 "missing trigger specification", &errstr);
1639       if (!sockline_trig_re)
1640         return m_errlog_defer_3(scanent, errstr, sock);
1641
1642       /* find virus name regex */
1643       sockline_name_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1644                           "missing virus name regex specification", &errstr);
1645       if (!sockline_name_re)
1646         return m_errlog_defer_3(scanent, errstr, sock);
1647
1648       /* prepare scanner call - security depends on expansions check above */
1649       commandline = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
1650       commandline = string_sprintf( CS sockline_scanner, CS commandline);
1651
1652
1653       /* Pass the command string to the socket */
1654       if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0)
1655         return m_errlog_defer(scanent, errstr);
1656
1657       /* Read the result */
1658       bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL));
1659
1660       if (bread <= 0)
1661         return m_errlog_defer_3(scanent,
1662           string_sprintf("unable to read from socket (%s)", strerror(errno)),
1663           sock);
1664
1665       if (bread == sizeof(av_buffer))
1666         return m_errlog_defer_3(scanent, US"buffer too small", sock);
1667       av_buffer[bread] = '\0';
1668       linebuffer = string_copy(av_buffer);
1669
1670       /* try trigger match */
1671       if (regex_match_and_setup(sockline_trig_re, linebuffer, 0, -1))
1672         {
1673         if (!(malware_name = m_pcre_exec(sockline_name_re, av_buffer)))
1674           malware_name = US "unknown";
1675         }
1676       else /* no virus found */
1677         malware_name = NULL;
1678       break;
1679       }
1680
1681     case M_MKSD: /* "mksd" scanner type ------------------------------------- */
1682       {
1683       char *mksd_options_end;
1684       int mksd_maxproc = 1;  /* default, if no option supplied */
1685       int retval;
1686
1687       if (scanner_options)
1688         {
1689         mksd_maxproc = (int)strtol(CS scanner_options, &mksd_options_end, 10);
1690         if (  *scanner_options == '\0'
1691            || *mksd_options_end != '\0'
1692            || mksd_maxproc < 1
1693            || mksd_maxproc > 32
1694            )
1695           return m_errlog_defer(scanent,
1696             string_sprintf("invalid option '%s'", scanner_options));
1697         }
1698
1699       if((sock = ip_unixsocket(US "/var/run/mksd/socket", &errstr)) < 0)
1700         return m_errlog_defer(scanent, errstr);
1701
1702       malware_name = NULL;
1703
1704       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan\n", scanner_name);
1705
1706       if ((retval = mksd_scan_packed(scanent, sock, eml_filename, tmo)) != OK)
1707         {
1708         close (sock);
1709         return retval;
1710         }
1711       break;
1712       }
1713
1714     case M_AVAST: /* "avast" scanner type ----------------------------------- */
1715       {
1716       int ovector[1*3];
1717       uschar buf[1024];
1718       uschar * scanrequest;
1719       enum {AVA_HELO, AVA_OPT, AVA_RSP, AVA_DONE} avast_stage;
1720       int nread;
1721
1722       /* According to Martin Tuma @avast the protocol uses "escaped
1723       whitespace", that is, every embedded whitespace is backslash
1724       escaped, as well as backslash is protected by backslash.
1725       The returned lines contain the name of the scanned file, a tab
1726       and the [ ] marker.
1727       [+] - not infected
1728       [L] - infected
1729       [E] - some error occured
1730       Such marker follows the first non-escaped TAB.  */
1731       if (  (  !ava_re_clean
1732             && !(ava_re_clean = m_pcre_compile(ava_re_clean_str, &errstr)))
1733          || (  !ava_re_virus
1734             && !(ava_re_virus = m_pcre_compile(ava_re_virus_str, &errstr)))
1735          )
1736         return malware_errlog_defer(errstr);
1737
1738       /* wait for result */
1739       for (avast_stage = AVA_HELO;
1740            (nread = recv_line(sock, buf, sizeof(buf), tmo)) > 0;
1741           )
1742         {
1743         int slen = Ustrlen(buf);
1744         if (slen >= 1) 
1745           {
1746           DEBUG(D_acl) debug_printf("got from avast: %s\n", buf);
1747           switch (avast_stage)
1748             {
1749             case AVA_HELO:
1750               if (Ustrncmp(buf, "220", 3) != 0)
1751                 goto endloop;                   /* require a 220 */
1752               goto sendreq;
1753
1754             case AVA_OPT:
1755               if (Ustrncmp(buf, "210", 3) == 0)
1756                 break;                          /* ignore 210 responses */
1757               if (Ustrncmp(buf, "200", 3) != 0)
1758                 goto endloop;                   /* require a 200 */
1759
1760             sendreq:
1761               {
1762               int len;
1763               /* Check for another option to send. Newline-terminate it. */
1764               if ((scanrequest = string_nextinlist(&av_scanner_work, &sep,
1765                                 NULL, 0)))
1766                 {
1767                 scanrequest = string_sprintf("%s\n", scanrequest);
1768                 avast_stage = AVA_OPT;          /* just sent option */
1769                 }
1770               else
1771                 {
1772                 scanrequest = string_sprintf("SCAN %s/scan/%s\n",
1773                     spool_directory, message_id);
1774                 avast_stage = AVA_RSP;          /* just sent command */
1775                 }
1776
1777               /* send config-cmd or scan-request to socket */
1778               len = Ustrlen(scanrequest);
1779               if (send(sock, scanrequest, len, 0) < 0)
1780                 {
1781                 scanrequest[len-1] = '\0';
1782                 return m_errlog_defer_3(scanent, string_sprintf(
1783                       "unable to send request '%s' to socket (%s): %s",
1784                       scanrequest, scanner_options, strerror(errno)), sock);
1785                 }
1786               break;
1787               }
1788
1789             case AVA_RSP:
1790               if (Ustrncmp(buf, "210", 3) == 0)
1791                 break;  /* ignore the "210 SCAN DATA" message */
1792
1793               if (pcre_exec(ava_re_clean, NULL, CS buf, slen,
1794                     0, 0, ovector, nelements(ovector)) > 0)
1795                 break;
1796
1797               if ((malware_name = m_pcre_exec(ava_re_virus, buf)))
1798                 { /* remove backslash in front of [whitespace|backslash] */
1799                 uschar * p, * p0;
1800                 for (p = malware_name; *p; ++p) 
1801                   if (*p == '\\' && (isspace(p[1]) || p[1] == '\\'))
1802                     for (p0 = p; *p0; ++p0) *p0 = p0[1];
1803                 
1804                 avast_stage = AVA_DONE;
1805                 goto endloop;
1806                 }
1807
1808               if (Ustrncmp(buf, "200 SCAN OK", 11) == 0) 
1809                 { /* we're done finally */
1810                 if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
1811                   return m_errlog_defer_3(scanent, string_sprintf(
1812                               "unable to send quit request to socket (%s): %s",
1813                               scanner_options, strerror(errno)),
1814                               sock);
1815                 malware_name = NULL;
1816                 avast_stage = AVA_DONE;
1817                 goto endloop;
1818                 }
1819
1820               /* here for any unexpected response from the scanner */
1821               goto endloop;
1822             }
1823           }
1824         }
1825       endloop:
1826
1827       switch(avast_stage)
1828         {
1829         case AVA_HELO:  
1830         case AVA_OPT:
1831         case AVA_RSP:   return m_errlog_defer_3(scanent,
1832                             nread >= 0
1833                             ? string_sprintf(
1834                                 "invalid response from scanner: '%s'", buf)
1835                             : nread == -1
1836                             ? US"EOF from scanner"
1837                             : US"timeout from scanner",
1838                           sock);
1839         default:        break;
1840         }
1841       }
1842       break;
1843   }     /* scanner type switch */
1844
1845   if (sock >= 0)
1846     (void) close (sock);
1847   malware_ok = TRUE;                    /* set "been here, done that" marker */
1848   }
1849
1850 /* match virus name against pattern (caseless ------->----------v) */
1851 if (malware_name && regex_match_and_setup(re, malware_name, 0, -1))
1852   {
1853   DEBUG(D_acl) debug_printf(
1854       "Matched regex to malware [%s] [%s]\n", malware_re, malware_name);
1855   return OK;
1856   }
1857 else
1858   return FAIL;
1859 }
1860
1861
1862 /*************************************************
1863 *          Scan an email for malware             *
1864 *************************************************/
1865
1866 /* This is the normal interface for scanning an email, which doesn't need a
1867 filename; it's a wrapper around the malware_file function.
1868
1869 Arguments:
1870   malware_re  match condition for "malware="
1871   timeout     if nonzero, timeout in seconds
1872
1873 Returns:      Exim message processing code (OK, FAIL, DEFER, ...)
1874               where true means malware was found (condition applies)
1875 */
1876 int
1877 malware(const uschar * malware_re, int timeout)
1878 {
1879   uschar * scan_filename;
1880   int ret;
1881
1882   scan_filename = string_sprintf("%s/scan/%s/%s.eml",
1883                     spool_directory, message_id, message_id);
1884   ret = malware_internal(malware_re, scan_filename, timeout, FALSE);
1885   if (ret == DEFER) av_failed = TRUE;
1886
1887   return ret;
1888 }
1889
1890
1891 /*************************************************
1892 *          Scan a file for malware               *
1893 *************************************************/
1894
1895 /* This is a test wrapper for scanning an email, which is not used in
1896 normal processing.  Scan any file, using the Exim scanning interface.
1897 This function tampers with various global variables so is unsafe to use
1898 in any other context.
1899
1900 Arguments:
1901   eml_filename  a file holding the message to be scanned
1902
1903 Returns:        Exim message processing code (OK, FAIL, DEFER, ...)
1904                 where true means malware was found (condition applies)
1905 */
1906 int
1907 malware_in_file(uschar *eml_filename)
1908 {
1909   uschar message_id_buf[64];
1910   int ret;
1911
1912   /* spool_mbox() assumes various parameters exist, when creating
1913   the relevant directory and the email within */
1914   (void) string_format(message_id_buf, sizeof(message_id_buf),
1915       "dummy-%d", vaguely_random_number(INT_MAX));
1916   message_id = message_id_buf;
1917   sender_address = US"malware-sender@example.net";
1918   return_path = US"";
1919   recipients_list = NULL;
1920   receive_add_recipient(US"malware-victim@example.net", -1);
1921   enable_dollar_recipients = TRUE;
1922
1923   ret = malware_internal(US"*", eml_filename, 0,  TRUE);
1924
1925   Ustrncpy(spooled_message_id, message_id, sizeof(spooled_message_id));
1926   spool_mbox_ok = 1;
1927   /* don't set no_mbox_unspool; at present, there's no way for it to become
1928   set, but if that changes, then it should apply to these tests too */
1929   unspool_mbox();
1930
1931   /* silence static analysis tools */
1932   message_id = NULL;
1933
1934   return ret;
1935 }
1936
1937
1938 void
1939 malware_init(void)
1940 {
1941 if (!malware_default_re)
1942   malware_default_re = regex_must_compile(malware_regex_default, FALSE, TRUE);
1943 if (!drweb_re)
1944   drweb_re = regex_must_compile(drweb_re_str, FALSE, TRUE);
1945 if (!fsec_re)
1946   fsec_re = regex_must_compile(fsec_re_str, FALSE, TRUE);
1947 if (!kav_re_sus)
1948   kav_re_sus = regex_must_compile(kav_re_sus_str, FALSE, TRUE);
1949 if (!kav_re_inf)
1950   kav_re_inf = regex_must_compile(kav_re_inf_str, FALSE, TRUE);
1951 if (!ava_re_clean)
1952   ava_re_clean = regex_must_compile(ava_re_clean_str, FALSE, TRUE);
1953 if (!ava_re_virus)
1954   ava_re_virus = regex_must_compile(ava_re_virus_str, FALSE, TRUE);
1955 }
1956
1957 #endif /*WITH_CONTENT_SCAN*/
1958 /*
1959  * vi: aw ai sw=2
1960  */