git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Logging: add I= element to transport-defer lines. Bug 2675
[exim.git]
/
src
/
src
/
malware.c
diff --git
a/src/src/malware.c
b/src/src/malware.c
index bb8f2bcc0a95ef2dce6380eb3ef5e1c2394a34e7..03bb832fc0131795bb1cb6858162ba0ba28f5507 100644
(file)
--- a/
src/src/malware.c
+++ b/
src/src/malware.c
@@
-4,7
+4,7
@@
/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003 - 2015
* License: GPL
/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2003 - 2015
* License: GPL
- * Copyright (c) The Exim Maintainers 2015 - 20
18
+ * Copyright (c) The Exim Maintainers 2015 - 20
20
*/
/* Code for calling virus (malware) scanners. Called from acl.c. */
*/
/* Code for calling virus (malware) scanners. Called from acl.c. */
@@
-49,6
+49,7
@@
typedef enum {
#ifndef DISABLE_MAL_CMDLINE
M_CMDL,
#endif
#ifndef DISABLE_MAL_CMDLINE
M_CMDL,
#endif
+ M_DUMMY
} scanner_t;
typedef enum {MC_NONE, MC_TCP, MC_UNIX, MC_STRM} contype_t;
static struct scan
} scanner_t;
typedef enum {MC_NONE, MC_TCP, MC_UNIX, MC_STRM} contype_t;
static struct scan
@@
-219,6
+220,7
@@
extern uschar spooled_message_id[MESSAGE_ID_LENGTH+1];
/* Some (currently avast only) use backslash escaped whitespace,
this function undoes these escapes */
/* Some (currently avast only) use backslash escaped whitespace,
this function undoes these escapes */
+#ifndef DISABLE_MAL_AVAST
static inline void
unescape(uschar *p)
{
static inline void
unescape(uschar *p)
{
@@
-227,6
+229,7
@@
for (; *p; ++p)
if (*p == '\\' && (isspace(p[1]) || p[1] == '\\'))
for (p0 = p; *p0; ++p0) *p0 = p0[1];
}
if (*p == '\\' && (isspace(p[1]) || p[1] == '\\'))
for (p0 = p; *p0; ++p0) *p0 = p0[1];
}
+#endif
/* --- malware_*_defer --- */
static inline int
/* --- malware_*_defer --- */
static inline int
@@
-249,18
+252,12
@@
m_panic_defer(struct scan * scanent, const uschar * hostport,
return malware_panic_defer(string_sprintf("%s %s : %s",
scanent->name, hostport ? hostport : CUS"", str));
}
return malware_panic_defer(string_sprintf("%s %s : %s",
scanent->name, hostport ? hostport : CUS"", str));
}
-static inline int
-m_log_defer(struct scan * scanent, const uschar * hostport,
- const uschar * str)
-{
-return malware_log_defer(string_sprintf("%s %s : %s",
- scanent->name, hostport ? hostport : CUS"", str));
-}
/* --- m_*_defer_3 */
static inline int
m_panic_defer_3(struct scan * scanent, const uschar * hostport,
const uschar * str, int fd_to_close)
{
/* --- m_*_defer_3 */
static inline int
m_panic_defer_3(struct scan * scanent, const uschar * hostport,
const uschar * str, int fd_to_close)
{
+DEBUG(D_acl) debug_print_socket(fd_to_close);
(void) close(fd_to_close);
return m_panic_defer(scanent, hostport, str);
}
(void) close(fd_to_close);
return m_panic_defer(scanent, hostport, str);
}
@@
-301,8
+298,7
@@
const uschar * rerror;
int roffset;
const pcre * cre;
int roffset;
const pcre * cre;
-cre = pcre_compile(CS re, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
-if (!cre)
+if (!(cre = pcre_compile(CS re, PCRE_COPT, CCSS &rerror, &roffset, NULL)))
*errstr= string_sprintf("regular expression error in '%s': %s at offset %d",
re, rerror, roffset);
return cre;
*errstr= string_sprintf("regular expression error in '%s': %s at offset %d",
re, rerror, roffset);
return cre;
@@
-316,7
+312,7
@@
int i = pcre_exec(cre, NULL, CS text, Ustrlen(text), 0, 0,
ovector, nelem(ovector));
uschar * substr = NULL;
if (i >= 2) /* Got it */
ovector, nelem(ovector));
uschar * substr = NULL;
if (i >= 2) /* Got it */
- pcre_get_substring(CS text, ovector, i, 1,
(const char **)
&substr);
+ pcre_get_substring(CS text, ovector, i, 1,
CCSS
&substr);
return substr;
}
return substr;
}
@@
-338,6
+334,7
@@
else
return cre;
}
return cre;
}
+
/*
Simple though inefficient wrapper for reading a line. Drop CRs and the
trailing newline. Can return early on buffer full. Null-terminate.
/*
Simple though inefficient wrapper for reading a line. Drop CRs and the
trailing newline. Can return early on buffer full. Null-terminate.
@@
-348,13
+345,13
@@
return cre;
-2 on timeout or error
*/
static int
-2 on timeout or error
*/
static int
-recv_line(int fd, uschar * buffer, int bsize,
in
t tmo)
+recv_line(int fd, uschar * buffer, int bsize,
time_
t tmo)
{
uschar * p = buffer;
ssize_t rcv;
BOOL ok = FALSE;
{
uschar * p = buffer;
ssize_t rcv;
BOOL ok = FALSE;
-if (!fd_ready(fd, tmo
-time(NULL)
))
+if (!fd_ready(fd, tmo))
return -2;
/*XXX tmo handling assumes we always get a whole line */
return -2;
/*XXX tmo handling assumes we always get a whole line */
@@
-369,8
+366,12
@@
while ((rcv = read(fd, p, 1)) > 0)
}
if (!ok)
{
}
if (!ok)
{
- DEBUG(D_acl) debug_printf_indent("Malware scan: read %s (%s)\n",
+ DEBUG(D_acl)
+ {
+ debug_printf_indent("Malware scan: read %s (%s)\n",
rcv==0 ? "EOF" : "error", strerror(errno));
rcv==0 ? "EOF" : "error", strerror(errno));
+ debug_print_socket(fd);
+ }
return rcv==0 ? -1 : -2;
}
*p = '\0';
return rcv==0 ? -1 : -2;
}
*p = '\0';
@@
-380,13
+381,15
@@
return p - buffer;
}
/* return TRUE iff size as requested */
}
/* return TRUE iff size as requested */
+#ifndef DISABLE_MAL_DRWEB
static BOOL
static BOOL
-recv_len(int sock, void * buf, int size,
in
t tmo)
+recv_len(int sock, void * buf, int size,
time_
t tmo)
{
{
-return fd_ready(sock, tmo
-time(NULL)
)
+return fd_ready(sock, tmo)
? recv(sock, buf, size, 0) == size
: FALSE;
}
? recv(sock, buf, size, 0) == size
: FALSE;
}
+#endif
@@
-429,7
+432,7
@@
for (;;)
}
static inline int
}
static inline int
-mksd_read_lines (int sock, uschar *av_buffer, int av_buffer_size,
in
t tmo)
+mksd_read_lines (int sock, uschar *av_buffer, int av_buffer_size,
time_
t tmo)
{
client_conn_ctx cctx = {.sock = sock};
int offset = 0;
{
client_conn_ctx cctx = {.sock = sock};
int offset = 0;
@@
-437,7
+440,7
@@
int i;
do
{
do
{
- i = ip_recv(&cctx, av_buffer+offset, av_buffer_size-offset, tmo
-time(NULL)
);
+ i = ip_recv(&cctx, av_buffer+offset, av_buffer_size-offset, tmo);
if (i <= 0)
{
(void) malware_panic_defer(US"unable to read from mksd UNIX socket (/var/run/mksd/socket)");
if (i <= 0)
{
(void) malware_panic_defer(US"unable to read from mksd UNIX socket (/var/run/mksd/socket)");
@@
-496,7
+499,7
@@
switch (*line)
static int
mksd_scan_packed(struct scan * scanent, int sock, const uschar * scan_filename,
static int
mksd_scan_packed(struct scan * scanent, int sock, const uschar * scan_filename,
-
in
t tmo)
+
time_
t tmo)
{
struct iovec iov[3];
const char *cmd = "MSQ\n";
{
struct iovec iov[3];
const char *cmd = "MSQ\n";
@@
-654,11
+657,11
@@
if (!malware_ok)
switch(scanent->conn)
{
case MC_TCP:
switch(scanent->conn)
{
case MC_TCP:
- malware_daemon_ctx.sock = ip_tcpsocket(scanner_options, &errstr, 5
);
break;
+ malware_daemon_ctx.sock = ip_tcpsocket(scanner_options, &errstr, 5
, NULL);
break;
case MC_UNIX:
malware_daemon_ctx.sock = ip_unixsocket(scanner_options, &errstr); break;
case MC_STRM:
case MC_UNIX:
malware_daemon_ctx.sock = ip_unixsocket(scanner_options, &errstr); break;
case MC_STRM:
- malware_daemon_ctx.sock = ip_streamsocket(scanner_options, &errstr, 5
);
break;
+ malware_daemon_ctx.sock = ip_streamsocket(scanner_options, &errstr, 5
, NULL);
break;
default:
/* compiler quietening */ break;
}
default:
/* compiler quietening */ break;
}
@@
-745,7
+748,7
@@
if (!malware_ok)
if (m_sock_send(malware_daemon_ctx.sock, scanrequest, Ustrlen(scanrequest), &errstr) < 0)
return m_panic_defer(scanent, CUS callout_address, errstr);
if (m_sock_send(malware_daemon_ctx.sock, scanrequest, Ustrlen(scanrequest), &errstr) < 0)
return m_panic_defer(scanent, CUS callout_address, errstr);
- bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo
-time(NULL)
);
+ bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo);
if (bread <= 0)
return m_panic_defer_3(scanent, CUS callout_address,
if (bread <= 0)
return m_panic_defer_3(scanent, CUS callout_address,
@@
-791,7
+794,7
@@
if (!malware_ok)
if (*scanner_options != '/')
{
/* calc file size */
if (*scanner_options != '/')
{
/* calc file size */
- if ((drweb_fd =
open
(CCS eml_filename, O_RDONLY)) == -1)
+ if ((drweb_fd =
exim_open2
(CCS eml_filename, O_RDONLY)) == -1)
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't open spool file %s: %s",
eml_filename, strerror(errno)),
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't open spool file %s: %s",
eml_filename, strerror(errno)),
@@
-835,7
+838,7
@@
badseek: err = errno;
malware_daemon_ctx.sock);
}
malware_daemon_ctx.sock);
}
- if (!(drweb_fbuf =
US
malloc(fsize_uint)))
+ if (!(drweb_fbuf =
store_
malloc(fsize_uint)))
{
(void)close(drweb_fd);
return m_panic_defer_3(scanent, NULL,
{
(void)close(drweb_fd);
return m_panic_defer_3(scanent, NULL,
@@
-848,7
+851,7
@@
badseek: err = errno;
{
int err = errno;
(void)close(drweb_fd);
{
int err = errno;
(void)close(drweb_fd);
- free(drweb_fbuf);
+
store_
free(drweb_fbuf);
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't read spool file %s: %s",
eml_filename, strerror(err)),
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't read spool file %s: %s",
eml_filename, strerror(err)),
@@
-859,11
+862,12
@@
badseek: err = errno;
/* send file body to socket */
if (send(malware_daemon_ctx.sock, drweb_fbuf, fsize, 0) < 0)
{
/* send file body to socket */
if (send(malware_daemon_ctx.sock, drweb_fbuf, fsize, 0) < 0)
{
- free(drweb_fbuf);
+
store_
free(drweb_fbuf);
return m_panic_defer_3(scanent, CUS callout_address, string_sprintf(
"unable to send file body to socket (%s)", scanner_options),
malware_daemon_ctx.sock);
}
return m_panic_defer_3(scanent, CUS callout_address, string_sprintf(
"unable to send file body to socket (%s)", scanner_options),
malware_daemon_ctx.sock);
}
+ store_free(drweb_fbuf);
}
else
{
}
else
{
@@
-916,7
+920,9
@@
badseek: err = errno;
return m_panic_defer_3(scanent, CUS callout_address,
US"cannot read report size", malware_daemon_ctx.sock);
drweb_slen = ntohl(drweb_slen);
return m_panic_defer_3(scanent, CUS callout_address,
US"cannot read report size", malware_daemon_ctx.sock);
drweb_slen = ntohl(drweb_slen);
- tmpbuf = store_get(drweb_slen);
+
+ /* assume tainted, since it is external input */
+ tmpbuf = store_get(drweb_slen, TRUE);
/* read report body */
if (!recv_len(malware_daemon_ctx.sock, tmpbuf, drweb_slen, tmo))
/* read report body */
if (!recv_len(malware_daemon_ctx.sock, tmpbuf, drweb_slen, tmo))
@@
-1062,7
+1068,7
@@
badseek: err = errno;
if (m_sock_send(malware_daemon_ctx.sock, cmdopt[i], Ustrlen(cmdopt[i]), &errstr) < 0)
return m_panic_defer(scanent, CUS callout_address, errstr);
if (m_sock_send(malware_daemon_ctx.sock, cmdopt[i], Ustrlen(cmdopt[i]), &errstr) < 0)
return m_panic_defer(scanent, CUS callout_address, errstr);
- bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo
-time(NULL)
);
+ bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo);
if (bread > 0) av_buffer[bread]='\0';
if (bread < 0)
return m_panic_defer_3(scanent, CUS callout_address,
if (bread > 0) av_buffer[bread]='\0';
if (bread < 0)
return m_panic_defer_3(scanent, CUS callout_address,
@@
-1094,7
+1100,7
@@
badseek: err = errno;
{
errno = ETIMEDOUT;
i = av_buffer+sizeof(av_buffer)-p;
{
errno = ETIMEDOUT;
i = av_buffer+sizeof(av_buffer)-p;
- if ((bread= ip_recv(&malware_daemon_ctx, p, i-1, tmo
-time(NULL)
)) < 0)
+ if ((bread= ip_recv(&malware_daemon_ctx, p, i-1, tmo)) < 0)
return m_panic_defer_3(scanent, CUS callout_address,
string_sprintf("unable to read result (%s)", strerror(errno)),
malware_daemon_ctx.sock);
return m_panic_defer_3(scanent, CUS callout_address,
string_sprintf("unable to read result (%s)", strerror(errno)),
malware_daemon_ctx.sock);
@@
-1359,13
+1365,10
@@
badseek: err = errno;
malware_name = US"unknown";
/* re-open the scanner output file, look for name match */
malware_name = US"unknown";
/* re-open the scanner output file, look for name match */
- scanner_record = fopen(CS file_name, "rb");
- while (fgets(CS linebuffer, sizeof(linebuffer), scanner_record))
- {
- /* try match */
- if ((s = m_pcre_exec(cmdline_regex_re, linebuffer)))
+ scanner_record = Ufopen(file_name, "rb");
+ while (Ufgets(linebuffer, sizeof(linebuffer), scanner_record))
+ if ((s = m_pcre_exec(cmdline_regex_re, linebuffer))) /* try match */
malware_name = s;
malware_name = s;
- }
(void)fclose(scanner_record);
}
else /* no virus found */
(void)fclose(scanner_record);
}
else /* no virus found */
@@
-1399,7
+1402,7
@@
badseek: err = errno;
/* wait for result */
memset(av_buffer, 0, sizeof(av_buffer));
/* wait for result */
memset(av_buffer, 0, sizeof(av_buffer));
- if ((bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo
-time(NULL)
)) <= 0)
+ if ((bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo)) <= 0)
return m_panic_defer_3(scanent, CUS callout_address,
string_sprintf("unable to read from UNIX socket (%s)", scanner_options),
malware_daemon_ctx.sock);
return m_panic_defer_3(scanent, CUS callout_address,
string_sprintf("unable to read from UNIX socket (%s)", scanner_options),
malware_daemon_ctx.sock);
@@
-1462,7
+1465,7
@@
badseek: err = errno;
/* Local file; so we def want to use_scan_command and don't want to try
* passing IP/port combinations */
use_scan_command = TRUE;
/* Local file; so we def want to use_scan_command and don't want to try
* passing IP/port combinations */
use_scan_command = TRUE;
- cd = (clamd_address *) store_get(sizeof(clamd_address));
+ cd = (clamd_address *) store_get(sizeof(clamd_address)
, FALSE
);
/* extract socket-path part */
sublist = scanner_options;
/* extract socket-path part */
sublist = scanner_options;
@@
-1496,7
+1499,7
@@
badseek: err = errno;
continue;
}
continue;
}
- cd = (clamd_address *) store_get(sizeof(clamd_address));
+ cd = (clamd_address *) store_get(sizeof(clamd_address)
, FALSE
);
/* extract host and port part */
sublist = scanner_options;
/* extract host and port part */
sublist = scanner_options;
@@
-1635,7
+1638,7
@@
badseek: err = errno;
malware_daemon_ctx.sock);
/* calc file size */
malware_daemon_ctx.sock);
/* calc file size */
- if ((clam_fd =
open
(CS eml_filename, O_RDONLY)) < 0)
+ if ((clam_fd =
exim_open2
(CS eml_filename, O_RDONLY)) < 0)
{
int err = errno;
return m_panic_defer_3(scanent, NULL,
{
int err = errno;
return m_panic_defer_3(scanent, NULL,
@@
-1665,7
+1668,7
@@
b_seek: err = errno;
if (lseek(clam_fd, 0, SEEK_SET) < 0)
goto b_seek;
if (lseek(clam_fd, 0, SEEK_SET) < 0)
goto b_seek;
- if (!(clamav_fbuf =
US
malloc(fsize_uint)))
+ if (!(clamav_fbuf =
store_
malloc(fsize_uint)))
{
(void)close(clam_fd);
return m_panic_defer_3(scanent, NULL,
{
(void)close(clam_fd);
return m_panic_defer_3(scanent, NULL,
@@
-1677,7
+1680,7
@@
b_seek: err = errno;
if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
{
int err = errno;
if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
{
int err = errno;
- free(clamav_fbuf); (void)close(clam_fd);
+
store_
free(clamav_fbuf); (void)close(clam_fd);
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't read spool file %s: %s",
eml_filename, strerror(err)),
return m_panic_defer_3(scanent, NULL,
string_sprintf("can't read spool file %s: %s",
eml_filename, strerror(err)),
@@
-1692,13
+1695,12
@@
b_seek: err = errno;
(send(malware_daemon_ctx.sock, clamav_fbuf, fsize_uint, 0) < 0) ||
(send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
{
(send(malware_daemon_ctx.sock, clamav_fbuf, fsize_uint, 0) < 0) ||
(send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
{
- free(clamav_fbuf);
+
store_
free(clamav_fbuf);
return m_panic_defer_3(scanent, NULL,
string_sprintf("unable to send file body to socket (%s)", hostname),
malware_daemon_ctx.sock);
}
return m_panic_defer_3(scanent, NULL,
string_sprintf("unable to send file body to socket (%s)", hostname),
malware_daemon_ctx.sock);
}
-
- free(clamav_fbuf);
+ store_free(clamav_fbuf);
}
else
{ /* use scan command */
}
else
{ /* use scan command */
@@
-1735,7
+1737,7
@@
b_seek: err = errno;
/* Read the result */
memset(av_buffer, 0, sizeof(av_buffer));
/* Read the result */
memset(av_buffer, 0, sizeof(av_buffer));
- bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo
-time(NULL)
);
+ bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo);
(void)close(malware_daemon_ctx.sock);
malware_daemon_ctx.sock = -1;
malware_daemon_ctx.tls_ctx = NULL;
(void)close(malware_daemon_ctx.sock);
malware_daemon_ctx.sock = -1;
malware_daemon_ctx.tls_ctx = NULL;
@@
-1893,7
+1895,7
@@
b_seek: err = errno;
return m_panic_defer(scanent, CUS callout_address, errstr);
/* Read the result */
return m_panic_defer(scanent, CUS callout_address, errstr);
/* Read the result */
- bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo
-time(NULL)
);
+ bread = ip_recv(&malware_daemon_ctx, av_buffer, sizeof(av_buffer), tmo);
if (bread <= 0)
return m_panic_defer_3(scanent, CUS callout_address,
if (bread <= 0)
return m_panic_defer_3(scanent, CUS callout_address,
@@
-1975,7
+1977,7
@@
b_seek: err = errno;
and the [ ] marker.
[+] - not infected
[L] - infected
and the [ ] marker.
[+] - not infected
[L] - infected
- [E] - some error occured
+ [E] - some error occur
r
ed
Such marker follows the first non-escaped TAB. For more information
see avast-protocol(5)
Such marker follows the first non-escaped TAB. For more information
see avast-protocol(5)
@@
-2277,12
+2279,13
@@
if (!fprot6d_re_virus)
}
}
-void
-malware_show_supported(
FILE * f
)
+gstring *
+malware_show_supported(
gstring * g
)
{
{
-fprintf(f, "Malware:");
-for (struct scan * sc = m_scans; sc->scancode != (scanner_t)-1; sc++) fprintf(f, " %s", sc->name);
-fprintf(f, "\n");
+g = string_cat(g, US"Malware:");
+for (struct scan * sc = m_scans; sc->scancode != (scanner_t)-1; sc++)
+ g = string_fmt_append(g, " %s", sc->name);
+return string_cat(g, US"\n");
}
}