git://git.exim.org
/
users
/
jgh
/
exim.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
87abcb2
)
Fix smtp response timeout
author
Jeremy Harris
<jgh146exb@wizmail.org>
Mon, 27 May 2019 22:44:31 +0000
(23:44 +0100)
committer
Jeremy Harris
<jgh146exb@wizmail.org>
Wed, 5 Jun 2019 16:20:10 +0000
(17:20 +0100)
doc/doc-txt/ChangeLog
patch
|
blob
|
history
src/src/functions.h
patch
|
blob
|
history
src/src/ip.c
patch
|
blob
|
history
src/src/malware.c
patch
|
blob
|
history
src/src/routers/iplookup.c
patch
|
blob
|
history
src/src/smtp_out.c
patch
|
blob
|
history
src/src/spam.c
patch
|
blob
|
history
src/src/transports/smtp_socks.c
patch
|
blob
|
history
src/src/verify.c
patch
|
blob
|
history
diff --git
a/doc/doc-txt/ChangeLog
b/doc/doc-txt/ChangeLog
index f9a14b678df39b82c4c1ab84a6624023b7ff4f65..d67daa873a4253e473142f5184b503a45763a787 100644
(file)
--- a/
doc/doc-txt/ChangeLog
+++ b/
doc/doc-txt/ChangeLog
@@
-128,10
+128,16
@@
JH/26 The PIPE_CONNECT facility is promoted from experimental status and is now
controlled by the build-time option SUPPORT_PIPE_CONNECT.
PP/01 Unbreak heimdal_gssapi, broken in 4.92.
controlled by the build-time option SUPPORT_PIPE_CONNECT.
PP/01 Unbreak heimdal_gssapi, broken in 4.92.
+
JH/27 Bug 2404: Use the main-section configuration option "dsn_from" for
success-DSN messages. Previously the From: header was always the default
one for these; the option was ignored.
JH/27 Bug 2404: Use the main-section configuration option "dsn_from" for
success-DSN messages. Previously the From: header was always the default
one for these; the option was ignored.
+JH/28 Fix the timeout on smtp response to apply to the whole response.
+ Previously it was reset for every read, so a teergrubing peer sending
+ single bytes within the time limit could extend the connection for a
+ long time. Credit to Qualsys Security Advisory Team for the discovery.
+
Exim version 4.92
-----------------
Exim version 4.92
-----------------
diff --git
a/src/src/functions.h
b/src/src/functions.h
index 33e296c13d62b2960265b326f30d0bd1e44652b0..7b5b00a2ded152ef00a9109ff044e9d116838fe6 100644
(file)
--- a/
src/src/functions.h
+++ b/
src/src/functions.h
@@
-231,7
+231,7
@@
extern uschar *expand_string_copy(const uschar *);
extern int_eximarith_t expand_string_integer(uschar *, BOOL);
extern void modify_variable(uschar *, void *);
extern int_eximarith_t expand_string_integer(uschar *, BOOL);
extern void modify_variable(uschar *, void *);
-extern BOOL fd_ready(int,
in
t);
+extern BOOL fd_ready(int,
time_
t);
extern int filter_interpret(uschar *, int, address_item **, uschar **);
extern BOOL filter_personal(string_item *, BOOL);
extern int filter_interpret(uschar *, int, address_item **, uschar **);
extern BOOL filter_personal(string_item *, BOOL);
@@
-278,7
+278,7
@@
extern int ip_connectedsocket(int, const uschar *, int, int,
int, host_item *, uschar **, const blob *);
extern int ip_get_address_family(int);
extern void ip_keepalive(int, const uschar *, BOOL);
int, host_item *, uschar **, const blob *);
extern int ip_get_address_family(int);
extern void ip_keepalive(int, const uschar *, BOOL);
-extern int ip_recv(client_conn_ctx *, uschar *, int,
in
t);
+extern int ip_recv(client_conn_ctx *, uschar *, int,
time_
t);
extern int ip_socket(int, int);
extern int ip_tcpsocket(const uschar *, uschar **, int);
extern int ip_socket(int, int);
extern int ip_tcpsocket(const uschar *, uschar **, int);
diff --git
a/src/src/ip.c
b/src/src/ip.c
index fb42f005107e442e92545b6bc806c1ec26024c3e..bf13d825c5ef52680cbf117cd38a6603967ffd3a 100644
(file)
--- a/
src/src/ip.c
+++ b/
src/src/ip.c
@@
-568,16
+568,15
@@
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
/*
Arguments:
fd the file descriptor
/*
Arguments:
fd the file descriptor
- time
out the timeout, seconds
+ time
limit the timeout endpoint, seconds-since-epoch
Returns: TRUE => ready for i/o
FALSE => timed out, or other error
*/
BOOL
Returns: TRUE => ready for i/o
FALSE => timed out, or other error
*/
BOOL
-fd_ready(int fd,
int timeou
t)
+fd_ready(int fd,
time_t timelimi
t)
{
fd_set select_inset;
{
fd_set select_inset;
-time_t start_recv = time(NULL);
-int time_left = timeout;
+int time_left = timelimit - time(NULL);
int rc;
if (time_left <= 0)
int rc;
if (time_left <= 0)
@@
-611,8
+610,7
@@
do
DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
/* Watch out, 'continue' jumps to the condition, not to the loops top */
DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
/* Watch out, 'continue' jumps to the condition, not to the loops top */
- time_left = timeout - (time(NULL) - start_recv);
- if (time_left > 0) continue;
+ if ((time_left = timelimit - time(NULL)) > 0) continue;
}
if (rc <= 0)
}
if (rc <= 0)
@@
-636,18
+634,18
@@
Arguments:
cctx the connection context (socket fd, possibly TLS context)
buffer to read into
bufsize the buffer size
cctx the connection context (socket fd, possibly TLS context)
buffer to read into
bufsize the buffer size
- time
out the timeout
+ time
limit the timeout endpoint, seconds-since-epoch
Returns: > 0 => that much data read
<= 0 on error or EOF; errno set - zero for EOF
*/
int
Returns: > 0 => that much data read
<= 0 on error or EOF; errno set - zero for EOF
*/
int
-ip_recv(client_conn_ctx * cctx, uschar * buffer, int buffsize,
int timeou
t)
+ip_recv(client_conn_ctx * cctx, uschar * buffer, int buffsize,
time_t timelimi
t)
{
int rc;
{
int rc;
-if (!fd_ready(cctx->sock, time
ou
t))
+if (!fd_ready(cctx->sock, time
limi
t))
return -1;
/* The socket is ready, read from it (via TLS if it's active). On EOF (i.e.
return -1;
/* The socket is ready, read from it (via TLS if it's active). On EOF (i.e.
diff --git
a/src/src/malware.c
b/src/src/malware.c
index 2e783e398eb9784ae58caddf4c0708a6a9804077..91649cf2022d0d51089e652fceb4a993be35431b 100644
(file)
--- a/
src/src/malware.c
+++ b/
src/src/malware.c
@@
-349,13
+349,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 */
@@
-382,9
+382,9
@@
return p - buffer;
/* return TRUE iff size as requested */
static BOOL
/* return TRUE iff size as requested */
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;
}
@@
-430,7
+430,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;
@@
-438,7
+438,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)");
@@
-497,7
+497,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";
@@
-746,7
+746,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,
@@
-1063,7
+1063,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,
@@
-1095,7
+1095,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);
@@
-1400,7
+1400,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);
@@
-1736,7
+1736,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;
@@
-1894,7
+1894,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,
diff --git
a/src/src/routers/iplookup.c
b/src/src/routers/iplookup.c
index ff67af38dd8b512832ee8c1aca559829533e3379..13849f9f1e48370a7b3a548f0ad5595f809a86f2 100644
(file)
--- a/
src/src/routers/iplookup.c
+++ b/
src/src/routers/iplookup.c
@@
-279,7
+279,7
@@
while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
/* Read the response and close the socket. If the read fails, try the
next IP address. */
/* Read the response and close the socket. If the read fails, try the
next IP address. */
- count = ip_recv(&query_cctx, reply, sizeof(reply) - 1, ob->timeout);
+ count = ip_recv(&query_cctx, reply, sizeof(reply) - 1,
time(NULL) +
ob->timeout);
(void)close(query_cctx.sock);
if (count <= 0)
{
(void)close(query_cctx.sock);
if (count <= 0)
{
diff --git
a/src/src/smtp_out.c
b/src/src/smtp_out.c
index c1cf901dc9f3d174de4d2139e870eb349115a645..c19d12d43599c5baa5d94ffb9ede2a762ceed0cc 100644
(file)
--- a/
src/src/smtp_out.c
+++ b/
src/src/smtp_out.c
@@
-589,14
+589,14
@@
Arguments:
inblock the SMTP input block (contains holding buffer, socket, etc.)
buffer where to put the line
size space available for the line
inblock the SMTP input block (contains holding buffer, socket, etc.)
buffer where to put the line
size space available for the line
- time
out the timeout to use when reading a packet
+ time
limit deadline for reading the lime, seconds past epoch
Returns: length of a line that has been put in the buffer
-1 otherwise, with errno set
*/
static int
Returns: length of a line that has been put in the buffer
-1 otherwise, with errno set
*/
static int
-read_response_line(smtp_inblock *inblock, uschar *buffer, int size,
int timeou
t)
+read_response_line(smtp_inblock *inblock, uschar *buffer, int size,
time_t timelimi
t)
{
uschar *p = buffer;
uschar *ptr = inblock->ptr;
{
uschar *p = buffer;
uschar *ptr = inblock->ptr;
@@
-639,7
+639,7
@@
for (;;)
/* Need to read a new input packet. */
/* Need to read a new input packet. */
- if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, time
ou
t)) <= 0)
+ if((rc = ip_recv(cctx, inblock->buffer, inblock->buffersize, time
limi
t)) <= 0)
{
DEBUG(D_deliver|D_transport|D_acl|D_v)
debug_printf_indent(errno ? " SMTP(%s)<<\n" : " SMTP(closed)<<\n",
{
DEBUG(D_deliver|D_transport|D_acl|D_v)
debug_printf_indent(errno ? " SMTP(%s)<<\n" : " SMTP(closed)<<\n",
@@
-696,6
+696,7
@@
smtp_read_response(void * sx0, uschar * buffer, int size, int okdigit,
smtp_context * sx = sx0;
uschar * ptr = buffer;
int count = 0;
smtp_context * sx = sx0;
uschar * ptr = buffer;
int count = 0;
+time_t timelimit = time(NULL) + timeout;
errno = 0; /* Ensure errno starts out zero */
errno = 0; /* Ensure errno starts out zero */
@@
-718,7
+719,7
@@
response. */
for (;;)
{
for (;;)
{
- if ((count = read_response_line(&sx->inblock, ptr, size, time
ou
t)) < 0)
+ if ((count = read_response_line(&sx->inblock, ptr, size, time
limi
t)) < 0)
return FALSE;
HDEBUG(D_transport|D_acl|D_v)
return FALSE;
HDEBUG(D_transport|D_acl|D_v)
diff --git
a/src/src/spam.c
b/src/src/spam.c
index 3ffc514f09cf13432f38beedc442929dfe9c3dcc..7e334852e53ba4454a50d0bee545112423deb12c 100644
(file)
--- a/
src/src/spam.c
+++ b/
src/src/spam.c
@@
-503,7
+503,7
@@
offset = 0;
while ((i = ip_recv(&spamd_cctx,
spamd_buffer + offset,
sizeof(spamd_buffer) - offset - 1,
while ((i = ip_recv(&spamd_cctx,
spamd_buffer + offset,
sizeof(spamd_buffer) - offset - 1,
- sd->timeout
- time(NULL)
+ start)) > 0)
+ sd->timeout + start)) > 0)
offset += i;
spamd_buffer[offset] = '\0'; /* guard byte */
offset += i;
spamd_buffer[offset] = '\0'; /* guard byte */
diff --git
a/src/src/transports/smtp_socks.c
b/src/src/transports/smtp_socks.c
index 09273c747485c72c57e33ebf8f7f723cd89c6bd2..41dc781473236fa489e1dbf2732b0d5a61addaf6 100644
(file)
--- a/
src/src/transports/smtp_socks.c
+++ b/
src/src/transports/smtp_socks.c
@@
-128,7
+128,7
@@
switch(method)
#ifdef TCP_QUICKACK
(void) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
#endif
#ifdef TCP_QUICKACK
(void) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
#endif
- if (!fd_ready(fd, tmo
-time(NULL)
) || read(fd, s, 2) != 2)
+ if (!fd_ready(fd, tmo) || read(fd, s, 2) != 2)
return FAIL;
HDEBUG(D_transport|D_acl|D_v)
debug_printf_indent(" SOCKS<< %02x %02x\n", s[0], s[1]);
return FAIL;
HDEBUG(D_transport|D_acl|D_v)
debug_printf_indent(" SOCKS<< %02x %02x\n", s[0], s[1]);
@@
-319,7
+319,7
@@
HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SOCKS>> 05 01 %02x\n", sob-
(void) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
#endif
(void) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
#endif
-if ( !fd_ready(fd, tmo
-time(NULL)
)
+if ( !fd_ready(fd, tmo)
|| read(fd, buf, 2) != 2
)
goto rcv_err;
|| read(fd, buf, 2) != 2
)
goto rcv_err;
@@
-368,7
+368,7
@@
if (send(fd, buf, size, 0) < 0)
/* expect conn-reply (success, local(ipver, addr, port))
of same length as conn-request, or non-success fail code */
/* expect conn-reply (success, local(ipver, addr, port))
of same length as conn-request, or non-success fail code */
-if ( !fd_ready(fd, tmo
-time(NULL)
)
+if ( !fd_ready(fd, tmo)
|| (size = read(fd, buf, size)) < 2
)
goto rcv_err;
|| (size = read(fd, buf, size)) < 2
)
goto rcv_err;
diff --git
a/src/src/verify.c
b/src/src/verify.c
index 7125a6da1a309a3fe434a89d31f182fa6cfee760..5026a417cea16d28753b367efc74b22f503d9da4 100644
(file)
--- a/
src/src/verify.c
+++ b/
src/src/verify.c
@@
-2745,7
+2745,7
@@
for (;;)
int size = sizeof(buffer) - (p - buffer);
if (size <= 0) goto END_OFF; /* Buffer filled without seeing \n. */
int size = sizeof(buffer) - (p - buffer);
if (size <= 0) goto END_OFF; /* Buffer filled without seeing \n. */
- count = ip_recv(&ident_conn_ctx, p, size, rfc1413_query_timeout);
+ count = ip_recv(&ident_conn_ctx, p, size,
time(NULL) +
rfc1413_query_timeout);
if (count <= 0) goto END_OFF; /* Read error or EOF */
/* Scan what we just read, to see if we have reached the terminating \r\n. Be
if (count <= 0) goto END_OFF; /* Read error or EOF */
/* Scan what we just read, to see if we have reached the terminating \r\n. Be