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