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