Make useful socket functions more generally available
[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 current_server;
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           /* Randomly pick a server to start with */
1293           current_server = random_number( num_servers );
1294
1295           DEBUG(D_acl)
1296             debug_printf("trying server name %s, port %u\n",
1297                        clamd_address_vector[current_server]->tcp_addr,
1298                        clamd_address_vector[current_server]->tcp_port);
1299
1300           /* Lookup the host. This is to ensure that we connect to the same IP
1301            * on both connections (as one host could resolve to multiple ips) */
1302           sock= m_tcpsocket(clamd_address_vector[current_server]->tcp_addr,
1303                               clamd_address_vector[current_server]->tcp_port,
1304                               &connhost, &errstr);
1305           if (sock >= 0)
1306             {
1307             /* Connection successfully established with a server */
1308             hostname = clamd_address_vector[current_server]->tcp_addr;
1309             break;
1310             }
1311
1312           log_write(0, LOG_MAIN, "malware acl condition: %s: %s",
1313             scanent->name, errstr);
1314
1315           /* Remove the server from the list. XXX We should free the memory */
1316           num_servers--;
1317           for (i = current_server; i < num_servers; i++)
1318             clamd_address_vector[i] = clamd_address_vector[i+1];
1319           }
1320
1321         if (num_servers == 0)
1322           return m_errlog_defer(scanent, US"all servers failed");
1323         }
1324       else
1325         {
1326         if ((sock = ip_unixsocket(scanner_options, &errstr)) < 0)
1327           return m_errlog_defer(scanent, errstr);
1328         }
1329
1330       /* have socket in variable "sock"; command to use is semi-independent of
1331        * the socket protocol.  We use SCAN if is local (either Unix/local
1332        * domain socket, or explicitly told local) else we stream the data.
1333        * How we stream the data depends upon how we were built.  */
1334
1335       if (!use_scan_command)
1336         {
1337 #ifdef WITH_OLD_CLAMAV_STREAM
1338         /* "STREAM\n" command, get back a "PORT <N>\n" response, send data to
1339          * that port on a second connection; then in the scan-method-neutral
1340          * part, read the response back on the original connection. */
1341
1342         DEBUG(D_acl) debug_printf(
1343             "Malware scan: issuing %s old-style remote scan (PORT)\n",
1344             scanner_name);
1345
1346         /* Pass the string to ClamAV (7 = "STREAM\n") */
1347         if (m_sock_send(sock, US"STREAM\n", 7, &errstr) < 0)
1348           return m_errlog_defer(scanent, errstr);
1349
1350         memset(av_buffer2, 0, sizeof(av_buffer2));
1351         bread = ip_recv(sock, av_buffer2, sizeof(av_buffer2), tmo-time(NULL));
1352
1353         if (bread < 0)
1354           return m_errlog_defer_3(scanent,
1355             string_sprintf("unable to read PORT from socket (%s)",
1356                 strerror(errno)),
1357             sock);
1358
1359         if (bread == sizeof(av_buffer2))
1360           return m_errlog_defer_3(scanent, "buffer too small", sock);
1361
1362         if (!(*av_buffer2))
1363           return m_errlog_defer_3(scanent, "ClamAV returned null", sock);
1364
1365         av_buffer2[bread] = '\0';
1366         if( sscanf(CS av_buffer2, "PORT %u\n", &port) != 1 )
1367           return m_errlog_defer_3(scanent,
1368             string_sprintf("Expected port information from clamd, got '%s'",
1369               av_buffer2),
1370             sock);
1371
1372         sockData = m_tcpsocket(connhost.address, port, NULL, &errstr);
1373         if (sockData < 0)
1374           return m_errlog_defer_3(scanent, errstr, sock);
1375
1376 # define CLOSE_SOCKDATA (void)close(sockData)
1377 #else /* WITH_OLD_CLAMAV_STREAM not defined */
1378         /* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
1379         chunks, <n> a 4-byte number (network order), terminated by a zero-length
1380         chunk. */
1381
1382         DEBUG(D_acl) debug_printf(
1383             "Malware scan: issuing %s new-style remote scan (zINSTREAM)\n",
1384             scanner_name);
1385
1386         /* Pass the string to ClamAV (10 = "zINSTREAM\0") */
1387         if (send(sock, "zINSTREAM", 10, 0) < 0)
1388           return m_errlog_defer_3(scanent,
1389             string_sprintf("unable to send zINSTREAM to socket (%s)",
1390               strerror(errno)),
1391             sock);
1392
1393 # define CLOSE_SOCKDATA /**/
1394 #endif
1395
1396         /* calc file size */
1397         if ((clam_fd = open(CS eml_filename, O_RDONLY)) < 0)
1398           {
1399           int err = errno;
1400           CLOSE_SOCKDATA;
1401           return m_errlog_defer_3(scanent,
1402             string_sprintf("can't open spool file %s: %s",
1403               eml_filename, strerror(err)),
1404             sock);
1405           }
1406         if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0)
1407           {
1408           int err = errno;
1409           CLOSE_SOCKDATA; (void)close(clam_fd);
1410           return m_errlog_defer_3(scanent,
1411             string_sprintf("can't seek spool file %s: %s",
1412               eml_filename, strerror(err)),
1413             sock);
1414           }
1415         fsize_uint = (unsigned int) fsize;
1416         if ((off_t)fsize_uint != fsize)
1417           {
1418           CLOSE_SOCKDATA; (void)close(clam_fd);
1419           return m_errlog_defer_3(scanent,
1420             string_sprintf("seeking spool file %s, size overflow",
1421               eml_filename),
1422             sock);
1423           }
1424         lseek(clam_fd, 0, SEEK_SET);
1425
1426         if (!(clamav_fbuf = (uschar *) malloc (fsize_uint)))
1427           {
1428           CLOSE_SOCKDATA; (void)close(clam_fd);
1429           return m_errlog_defer_3(scanent,
1430             string_sprintf("unable to allocate memory %u for file (%s)",
1431               fsize_uint, eml_filename),
1432             sock);
1433           }
1434
1435         if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
1436           {
1437           int err = errno;
1438           free(clamav_fbuf); CLOSE_SOCKDATA; (void)close(clam_fd);
1439           return m_errlog_defer_3(scanent,
1440             string_sprintf("can't read spool file %s: %s",
1441               eml_filename, strerror(err)),
1442             sock);
1443           }
1444         (void)close(clam_fd);
1445
1446         /* send file body to socket */
1447 #ifdef WITH_OLD_CLAMAV_STREAM
1448         if (send(sockData, clamav_fbuf, fsize_uint, 0) < 0)
1449           {
1450           free(clamav_fbuf); CLOSE_SOCKDATA;
1451           return m_errlog_defer_3(scanent,
1452             string_sprintf("unable to send file body to socket (%s:%u)",
1453               hostname, port),
1454             sock);
1455           }
1456 #else
1457         send_size = htonl(fsize_uint);
1458         send_final_zeroblock = 0;
1459         if ((send(sock, &send_size, sizeof(send_size), 0) < 0) ||
1460             (send(sock, clamav_fbuf, fsize_uint, 0) < 0) ||
1461             (send(sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
1462           {
1463           free(clamav_fbuf);
1464           return m_errlog_defer_3(scanent,
1465             string_sprintf("unable to send file body to socket (%s)", hostname),
1466             sock);
1467           }
1468 #endif
1469
1470         free(clamav_fbuf);
1471
1472         CLOSE_SOCKDATA;
1473 #undef CLOSE_SOCKDATA
1474         }
1475       else
1476         { /* use scan command */
1477         /* Send a SCAN command pointing to a filename; then in the then in the
1478          * scan-method-neutral part, read the response back */
1479
1480 /* ================================================================= */
1481
1482         /* Prior to the reworking post-Exim-4.72, this scanned a directory,
1483         which dates to when ClamAV needed us to break apart the email into the
1484         MIME parts (eg, with the now deprecated demime condition coming first).
1485         Some time back, ClamAV gained the ability to deconstruct the emails, so
1486         doing this would actually have resulted in the mail attachments being
1487         scanned twice, in the broken out files and from the original .eml.
1488         Since ClamAV now handles emails (and has for quite some time) we can
1489         just use the email file itself. */
1490         /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
1491         file_name = string_sprintf("SCAN %s\n", eml_filename);
1492
1493         DEBUG(D_acl) debug_printf(
1494             "Malware scan: issuing %s local-path scan [%s]\n",
1495             scanner_name, scanner_options);
1496
1497         if (send(sock, file_name, Ustrlen(file_name), 0) < 0)
1498           return m_errlog_defer_3(scanent,
1499             string_sprintf("unable to write to socket (%s)", strerror(errno)),
1500             sock);
1501
1502         /* Do not shut down the socket for writing; a user report noted that
1503          * clamd 0.70 does not react well to this. */
1504         }
1505       /* Commands have been sent, no matter which scan method or connection
1506        * type we're using; now just read the result, independent of method. */
1507
1508       /* Read the result */
1509       memset(av_buffer, 0, sizeof(av_buffer));
1510       bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL));
1511       (void)close(sock);
1512       sock = -1;
1513
1514       if (bread <= 0)
1515         return m_errlog_defer(scanent,
1516           string_sprintf("unable to read from socket (%s)",
1517           errno == 0 ? "EOF" : strerror(errno)));
1518
1519       if (bread == sizeof(av_buffer))
1520         return m_errlog_defer(scanent, US"buffer too small");
1521       /* We're now assured of a NULL at the end of av_buffer */
1522
1523       /* Check the result. ClamAV returns one of two result formats.
1524       In the basic mode, the response is of the form:
1525         infected: -> "<filename>: <virusname> FOUND"
1526         not-infected: -> "<filename>: OK"
1527         error: -> "<filename>: <errcode> ERROR
1528       If the ExtendedDetectionInfo option has been turned on, then we get:
1529         "<filename>: <virusname>(<virushash>:<virussize>) FOUND"
1530       for the infected case.  Compare:
1531 /tmp/eicar.com: Eicar-Test-Signature FOUND
1532 /tmp/eicar.com: Eicar-Test-Signature(44d88612fea8a8f36de82e1278abb02f:68) FOUND
1533
1534       In the streaming case, clamd uses the filename "stream" which you should
1535       be able to verify with { ktrace clamdscan --stream /tmp/eicar.com }.  (The
1536       client app will replace "stream" with the original filename before returning
1537       results to stdout, but the trace shows the data).
1538
1539       We will assume that the pathname passed to clamd from Exim does not contain
1540       a colon.  We will have whined loudly above if the eml_filename does (and we're
1541       passing a filename to clamd). */
1542
1543       if (!(*av_buffer))
1544         return m_errlog_defer(scanent, US"ClamAV returned null");
1545
1546       /* strip newline at the end (won't be present for zINSTREAM)
1547       (also any trailing whitespace, which shouldn't exist, but we depend upon
1548       this below, so double-check) */
1549       p = av_buffer + Ustrlen(av_buffer) - 1;
1550       if (*p == '\n') *p = '\0';
1551
1552       DEBUG(D_acl) debug_printf("Malware response: %s\n", av_buffer);
1553
1554       while (isspace(*--p) && (p > av_buffer))
1555         *p = '\0';
1556       if (*p) ++p;
1557       response_end = p;
1558
1559       /* colon in returned output? */
1560       if((p = Ustrchr(av_buffer,':')) == NULL)
1561         return m_errlog_defer(scanent, string_sprintf(
1562                   "ClamAV returned malformed result (missing colon): %s",
1563                   av_buffer));
1564
1565       /* strip filename */
1566       while (*p && isspace(*++p)) /**/;
1567       vname = p;
1568
1569       /* It would be bad to encounter a virus with "FOUND" in part of the name,
1570       but we should at least be resistant to it. */
1571       p = Ustrrchr(vname, ' ');
1572       result_tag = p ? p+1 : vname;
1573
1574       if (Ustrcmp(result_tag, "FOUND") == 0)
1575         {
1576         /* p should still be the whitespace before the result_tag */
1577         while (isspace(*p)) --p;
1578         *++p = '\0';
1579         /* Strip off the extended information too, which will be in parens
1580         after the virus name, with no intervening whitespace. */
1581         if (*--p == ')')
1582           {
1583           /* "(hash:size)", so previous '(' will do; if not found, we have
1584           a curious virus name, but not an error. */
1585           p = Ustrrchr(vname, '(');
1586           if (p)
1587             *p = '\0';
1588           }
1589         malware_name = string_copy(vname);
1590         DEBUG(D_acl) debug_printf("Malware found, name \"%s\"\n", malware_name);
1591
1592         }
1593       else if (Ustrcmp(result_tag, "ERROR") == 0)
1594         return m_errlog_defer(scanent,
1595           string_sprintf("ClamAV returned: %s", av_buffer));
1596
1597       else if (Ustrcmp(result_tag, "OK") == 0)
1598         {
1599         /* Everything should be OK */
1600         malware_name = NULL;
1601         DEBUG(D_acl) debug_printf("Malware not found\n");
1602
1603         }
1604       else
1605         return m_errlog_defer(scanent,
1606           string_sprintf("unparseable response from ClamAV: {%s}", av_buffer));
1607
1608       break;
1609       } /* clamd */
1610
1611     case M_SOCK: /* "sock" scanner type ------------------------------------- */
1612     /* This code was derived by Martin Poole from the clamd code contributed
1613        by David Saez and the cmdline code
1614     */
1615       {
1616       int bread;
1617       uschar * commandline;
1618       uschar av_buffer[1024];
1619       uschar * linebuffer;
1620       uschar * sockline_scanner;
1621       uschar sockline_scanner_default[] = "%s\n";
1622       const pcre *sockline_trig_re;
1623       const pcre *sockline_name_re;
1624
1625       /* find scanner command line */
1626       if ((sockline_scanner = string_nextinlist(&av_scanner_work, &sep,
1627                                           NULL, 0)))
1628       { /* check for no expansions apart from one %s */
1629         uschar * s = Ustrchr(sockline_scanner, '%');
1630         if (s++)
1631           if ((*s != 's' && *s != '%') || Ustrchr(s+1, '%'))
1632             return m_errlog_defer_3(scanent,
1633                                   US"unsafe sock scanner call spec", sock);
1634       }
1635       else
1636         sockline_scanner = sockline_scanner_default;
1637
1638       /* find scanner output trigger */
1639       sockline_trig_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1640                                 "missing trigger specification", &errstr);
1641       if (!sockline_trig_re)
1642         return m_errlog_defer_3(scanent, errstr, sock);
1643
1644       /* find virus name regex */
1645       sockline_name_re = m_pcre_nextinlist(&av_scanner_work, &sep,
1646                           "missing virus name regex specification", &errstr);
1647       if (!sockline_name_re)
1648         return m_errlog_defer_3(scanent, errstr, sock);
1649
1650       /* prepare scanner call - security depends on expansions check above */
1651       commandline = string_sprintf("%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
1652       commandline = string_sprintf( CS sockline_scanner, CS commandline);
1653
1654
1655       /* Pass the command string to the socket */
1656       if (m_sock_send(sock, commandline, Ustrlen(commandline), &errstr) < 0)
1657         return m_errlog_defer(scanent, errstr);
1658
1659       /* Read the result */
1660       bread = ip_recv(sock, av_buffer, sizeof(av_buffer), tmo-time(NULL));
1661
1662       if (bread <= 0)
1663         return m_errlog_defer_3(scanent,
1664           string_sprintf("unable to read from socket (%s)", strerror(errno)),
1665           sock);
1666
1667       if (bread == sizeof(av_buffer))
1668         return m_errlog_defer_3(scanent, US"buffer too small", sock);
1669       av_buffer[bread] = '\0';
1670       linebuffer = string_copy(av_buffer);
1671
1672       /* try trigger match */
1673       if (regex_match_and_setup(sockline_trig_re, linebuffer, 0, -1))
1674         {
1675         if (!(malware_name = m_pcre_exec(sockline_name_re, av_buffer)))
1676           malware_name = US "unknown";
1677         }
1678       else /* no virus found */
1679         malware_name = NULL;
1680       break;
1681       }
1682
1683     case M_MKSD: /* "mksd" scanner type ------------------------------------- */
1684       {
1685       char *mksd_options_end;
1686       int mksd_maxproc = 1;  /* default, if no option supplied */
1687       int retval;
1688
1689       if (scanner_options)
1690         {
1691         mksd_maxproc = (int)strtol(CS scanner_options, &mksd_options_end, 10);
1692         if (  *scanner_options == '\0'
1693            || *mksd_options_end != '\0'
1694            || mksd_maxproc < 1
1695            || mksd_maxproc > 32
1696            )
1697           return m_errlog_defer(scanent,
1698             string_sprintf("invalid option '%s'", scanner_options));
1699         }
1700
1701       if((sock = ip_unixsocket(US "/var/run/mksd/socket", &errstr)) < 0)
1702         return m_errlog_defer(scanent, errstr);
1703
1704       malware_name = NULL;
1705
1706       DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan\n", scanner_name);
1707
1708       if ((retval = mksd_scan_packed(scanent, sock, eml_filename, tmo)) != OK)
1709         {
1710         close (sock);
1711         return retval;
1712         }
1713       break;
1714       }
1715
1716     case M_AVAST: /* "avast" scanner type ----------------------------------- */
1717       {
1718       int ovector[1*3];
1719       uschar buf[1024];
1720       uschar * scanrequest;
1721       enum {AVA_HELO, AVA_OPT, AVA_RSP, AVA_DONE} avast_stage;
1722       int nread;
1723
1724       /* According to Martin Tuma @avast the protocol uses "escaped
1725       whitespace", that is, every embedded whitespace is backslash
1726       escaped, as well as backslash is protected by backslash.
1727       The returned lines contain the name of the scanned file, a tab
1728       and the [ ] marker.
1729       [+] - not infected
1730       [L] - infected
1731       [E] - some error occured
1732       Such marker follows the first non-escaped TAB.  */
1733       if (  (  !ava_re_clean
1734             && !(ava_re_clean = m_pcre_compile(ava_re_clean_str, &errstr)))
1735          || (  !ava_re_virus
1736             && !(ava_re_virus = m_pcre_compile(ava_re_virus_str, &errstr)))
1737          )
1738         return malware_errlog_defer(errstr);
1739
1740       /* wait for result */
1741       for (avast_stage = AVA_HELO;
1742            (nread = recv_line(sock, buf, sizeof(buf), tmo)) > 0;
1743           )
1744         {
1745         int slen = Ustrlen(buf);
1746         if (slen >= 1) 
1747           {
1748           DEBUG(D_acl) debug_printf("got from avast: %s\n", buf);
1749           switch (avast_stage)
1750             {
1751             case AVA_HELO:
1752               if (Ustrncmp(buf, "220", 3) != 0)
1753                 goto endloop;                   /* require a 220 */
1754               goto sendreq;
1755
1756             case AVA_OPT:
1757               if (Ustrncmp(buf, "210", 3) == 0)
1758                 break;                          /* ignore 210 responses */
1759               if (Ustrncmp(buf, "200", 3) != 0)
1760                 goto endloop;                   /* require a 200 */
1761
1762             sendreq:
1763               {
1764               int len;
1765               /* Check for another option to send. Newline-terminate it. */
1766               if ((scanrequest = string_nextinlist(&av_scanner_work, &sep,
1767                                 NULL, 0)))
1768                 {
1769                 scanrequest = string_sprintf("%s\n", scanrequest);
1770                 avast_stage = AVA_OPT;          /* just sent option */
1771                 }
1772               else
1773                 {
1774                 scanrequest = string_sprintf("SCAN %s/scan/%s\n",
1775                     spool_directory, message_id);
1776                 avast_stage = AVA_RSP;          /* just sent command */
1777                 }
1778
1779               /* send config-cmd or scan-request to socket */
1780               len = Ustrlen(scanrequest);
1781               if (send(sock, scanrequest, len, 0) < 0)
1782                 {
1783                 scanrequest[len-1] = '\0';
1784                 return m_errlog_defer_3(scanent, string_sprintf(
1785                       "unable to send request '%s' to socket (%s): %s",
1786                       scanrequest, scanner_options, strerror(errno)), sock);
1787                 }
1788               break;
1789               }
1790
1791             case AVA_RSP:
1792               if (Ustrncmp(buf, "210", 3) == 0)
1793                 break;  /* ignore the "210 SCAN DATA" message */
1794
1795               if (pcre_exec(ava_re_clean, NULL, CS buf, slen,
1796                     0, 0, ovector, nelements(ovector)) > 0)
1797                 break;
1798
1799               if ((malware_name = m_pcre_exec(ava_re_virus, buf)))
1800                 { /* remove backslash in front of [whitespace|backslash] */
1801                 uschar * p, * p0;
1802                 for (p = malware_name; *p; ++p) 
1803                   if (*p == '\\' && (isspace(p[1]) || p[1] == '\\'))
1804                     for (p0 = p; *p0; ++p0) *p0 = p0[1];
1805                 
1806                 avast_stage = AVA_DONE;
1807                 goto endloop;
1808                 }
1809
1810               if (Ustrncmp(buf, "200 SCAN OK", 11) == 0) 
1811                 { /* we're done finally */
1812                 if (send(sock, "QUIT\n", 5, 0) < 0) /* courtesy */
1813                   return m_errlog_defer_3(scanent, string_sprintf(
1814                               "unable to send quit request to socket (%s): %s",
1815                               scanner_options, strerror(errno)),
1816                               sock);
1817                 malware_name = NULL;
1818                 avast_stage = AVA_DONE;
1819                 goto endloop;
1820                 }
1821
1822               /* here for any unexpected response from the scanner */
1823               goto endloop;
1824             }
1825           }
1826         }
1827       endloop:
1828
1829       switch(avast_stage)
1830         {
1831         case AVA_HELO:  
1832         case AVA_OPT:
1833         case AVA_RSP:   return m_errlog_defer_3(scanent,
1834                             nread >= 0
1835                             ? string_sprintf(
1836                                 "invalid response from scanner: '%s'", buf)
1837                             : nread == -1
1838                             ? US"EOF from scanner"
1839                             : US"timeout from scanner",
1840                           sock);
1841         default:        break;
1842         }
1843       }
1844       break;
1845   }     /* scanner type switch */
1846
1847   if (sock >= 0)
1848     (void) close (sock);
1849   malware_ok = TRUE;                    /* set "been here, done that" marker */
1850   }
1851
1852 /* match virus name against pattern (caseless ------->----------v) */
1853 if (malware_name && regex_match_and_setup(re, malware_name, 0, -1))
1854   {
1855   DEBUG(D_acl) debug_printf(
1856       "Matched regex to malware [%s] [%s]\n", malware_re, malware_name);
1857   return OK;
1858   }
1859 else
1860   return FAIL;
1861 }
1862
1863
1864 /*************************************************
1865 *          Scan an email for malware             *
1866 *************************************************/
1867
1868 /* This is the normal interface for scanning an email, which doesn't need a
1869 filename; it's a wrapper around the malware_file function.
1870
1871 Arguments:
1872   malware_re  match condition for "malware="
1873   timeout     if nonzero, timeout in seconds
1874
1875 Returns:      Exim message processing code (OK, FAIL, DEFER, ...)
1876               where true means malware was found (condition applies)
1877 */
1878 int
1879 malware(const uschar * malware_re, int timeout)
1880 {
1881   uschar * scan_filename;
1882   int ret;
1883
1884   scan_filename = string_sprintf("%s/scan/%s/%s.eml",
1885                     spool_directory, message_id, message_id);
1886   ret = malware_internal(malware_re, scan_filename, timeout, FALSE);
1887   if (ret == DEFER) av_failed = TRUE;
1888
1889   return ret;
1890 }
1891
1892
1893 /*************************************************
1894 *          Scan a file for malware               *
1895 *************************************************/
1896
1897 /* This is a test wrapper for scanning an email, which is not used in
1898 normal processing.  Scan any file, using the Exim scanning interface.
1899 This function tampers with various global variables so is unsafe to use
1900 in any other context.
1901
1902 Arguments:
1903   eml_filename  a file holding the message to be scanned
1904
1905 Returns:        Exim message processing code (OK, FAIL, DEFER, ...)
1906                 where true means malware was found (condition applies)
1907 */
1908 int
1909 malware_in_file(uschar *eml_filename)
1910 {
1911   uschar message_id_buf[64];
1912   int ret;
1913
1914   /* spool_mbox() assumes various parameters exist, when creating
1915   the relevant directory and the email within */
1916   (void) string_format(message_id_buf, sizeof(message_id_buf),
1917       "dummy-%d", vaguely_random_number(INT_MAX));
1918   message_id = message_id_buf;
1919   sender_address = US"malware-sender@example.net";
1920   return_path = US"";
1921   recipients_list = NULL;
1922   receive_add_recipient(US"malware-victim@example.net", -1);
1923   enable_dollar_recipients = TRUE;
1924
1925   ret = malware_internal(US"*", eml_filename, 0,  TRUE);
1926
1927   Ustrncpy(spooled_message_id, message_id, sizeof(spooled_message_id));
1928   spool_mbox_ok = 1;
1929   /* don't set no_mbox_unspool; at present, there's no way for it to become
1930   set, but if that changes, then it should apply to these tests too */
1931   unspool_mbox();
1932
1933   /* silence static analysis tools */
1934   message_id = NULL;
1935
1936   return ret;
1937 }
1938
1939
1940 void
1941 malware_init(void)
1942 {
1943 if (!malware_default_re)
1944   malware_default_re = regex_must_compile(malware_regex_default, FALSE, TRUE);
1945 if (!drweb_re)
1946   drweb_re = regex_must_compile(drweb_re_str, FALSE, TRUE);
1947 if (!fsec_re)
1948   fsec_re = regex_must_compile(fsec_re_str, FALSE, TRUE);
1949 if (!kav_re_sus)
1950   kav_re_sus = regex_must_compile(kav_re_sus_str, FALSE, TRUE);
1951 if (!kav_re_inf)
1952   kav_re_inf = regex_must_compile(kav_re_inf_str, FALSE, TRUE);
1953 if (!ava_re_clean)
1954   ava_re_clean = regex_must_compile(ava_re_clean_str, FALSE, TRUE);
1955 if (!ava_re_virus)
1956   ava_re_virus = regex_must_compile(ava_re_virus_str, FALSE, TRUE);
1957 }
1958
1959 #endif /*WITH_CONTENT_SCAN*/
1960 /*
1961  * vi: aw ai sw=2
1962  */