summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/ChangeLog2
-rw-r--r--src/src/daemon.c5
-rw-r--r--src/src/transports/smtp.c5
-rw-r--r--test/log/05027
-rw-r--r--test/scripts/0000-Basic/050218
-rw-r--r--test/src/client.c29
-rw-r--r--test/src/server.c2
-rw-r--r--test/stderr/05022
-rw-r--r--test/stdout/050220
9 files changed, 78 insertions, 12 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index e9b0705f4..d4d091ed2 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -129,6 +129,8 @@ JH/32 Bug 1909: Fix OCSP proof verification for cases where the proof is
signed directly by the cert-signing cert, rather than an intermediate
OCSP-signing cert. This is the model used by LetsEncrypt.
+JH/33 Bug 1914: Ensure socket is nonblocking before draining after SMTP QUIT.
+
Exim version 4.87
-----------------
diff --git a/src/src/daemon.c b/src/src/daemon.c
index 35e61dbfd..bc33aec45 100644
--- a/src/src/daemon.c
+++ b/src/src/daemon.c
@@ -520,12 +520,13 @@ if (pid == 0)
{
if (smtp_out)
{
- int i;
+ int i, fd = fileno(smtp_in);
uschar buf[128];
mac_smtp_fflush();
/* drain socket, for clean TCP FINs */
- for(i = 16; read(fileno(smtp_in), buf, sizeof(buf)) > 0 && i > 0; ) i--;
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == 0)
+ for(i = 16; read(fd, buf, sizeof(buf)) > 0 && i > 0; ) i--;
}
search_tidyup();
smtp_log_no_mail(); /* Log no mail if configured */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index 6c6a10266..d6ef34eff 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -3168,8 +3168,9 @@ HDEBUG(D_transport|D_acl|D_v) debug_printf(" SMTP(close)>>\n");
if (lflags.send_quit)
{
shutdown(outblock.sock, SHUT_WR);
- for (rc = 16; read(inblock.sock, inbuffer, sizeof(inbuffer)) > 0 && rc > 0;)
- rc--; /* drain socket */
+ if (fcntl(inblock.sock, F_SETFL, O_NONBLOCK) == 0)
+ for (rc = 16; read(inblock.sock, inbuffer, sizeof(inbuffer)) > 0 && rc > 0;)
+ rc--; /* drain socket */
}
(void)close(inblock.sock);
diff --git a/test/log/0502 b/test/log/0502
index 37d82e43b..93673ff90 100644
--- a/test/log/0502
+++ b/test/log/0502
@@ -13,3 +13,10 @@
1999-03-02 09:44:33 Messages accepted:
1999-03-02 09:44:33 Recipients:
1999-03-02 09:44:33 Accepted:
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 Messages received:
+1999-03-02 09:44:33 Messages accepted:
+1999-03-02 09:44:33 Recipients:
+1999-03-02 09:44:33 Accepted:
diff --git a/test/scripts/0000-Basic/0502 b/test/scripts/0000-Basic/0502
index d4b8f0fdb..c22205ca7 100644
--- a/test/scripts/0000-Basic/0502
+++ b/test/scripts/0000-Basic/0502
@@ -23,3 +23,21 @@ exim -bs -DLAST=''
mail from:<a@b>
quit
****
+#
+# Check the server closes conn after a quit-response
+exim -DSERVER=server -DLAST=accept -bd -oX PORT_D
+****
+client 127.0.0.1 PORT_D
+??? 220
+EHLO test.ex
+??? 250-
+??? 250-
+??? 250-
+??? 250-
+??? 250 HELP
+QUIT
+??? 221
+???*eof
+****
+#
+killdaemon
diff --git a/test/src/client.c b/test/src/client.c
index 5e6b6472a..2b73098f5 100644
--- a/test/src/client.c
+++ b/test/src/client.c
@@ -24,6 +24,7 @@ ripped from the openssl ocsp and s_client utilities. */
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
+#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
@@ -897,9 +898,13 @@ while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL)
/* Expect incoming */
- if (strncmp(CS outbuffer, "??? ", 4) == 0)
+ if ( strncmp(CS outbuffer, "???", 3) == 0
+ && (outbuffer[3] == ' ' || outbuffer[3] == '*')
+ )
{
unsigned char *lineptr;
+ unsigned exp_eof = outbuffer[3] == '*';
+
printf("%s\n", outbuffer);
if (*inptr == 0) /* Refill input buffer */
@@ -921,15 +926,27 @@ while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL)
}
if (rc < 0)
- {
+ {
printf("Read error %s\n", strerror(errno));
- exit(81) ;
- }
+ exit(81);
+ }
else if (rc == 0)
+ if (exp_eof)
+ {
+ printf("Expected EOF read\n");
+ continue;
+ }
+ else
+ {
+ printf("Enexpected EOF read\n");
+ close(sock);
+ exit(80);
+ }
+ else if (exp_eof)
{
- printf("Unexpected EOF read\n");
+ printf("Expected EOF not read\n");
close(sock);
- exit(80);
+ exit(74);
}
else
{
diff --git a/test/src/server.c b/test/src/server.c
index 4a48965e2..26fcaf070 100644
--- a/test/src/server.c
+++ b/test/src/server.c
@@ -397,7 +397,6 @@ else
sin4.sin_addr.s_addr = (S_ADDR_TYPE)INADDR_ANY;
sin4.sin_port = htons(port);
if (bind(listen_socket[i], (struct sockaddr *)&sin4, sizeof(sin4)) < 0)
- {
if (listen_socket[v6n] < 0 || errno != EADDRINUSE)
{
printf("IPv4 socket bind() failed: %s\n", strerror(errno));
@@ -408,7 +407,6 @@ else
close(listen_socket[i]);
listen_socket[i] = -1;
}
- }
}
}
}
diff --git a/test/stderr/0502 b/test/stderr/0502
index 71afc025b..a3b308501 100644
--- a/test/stderr/0502
+++ b/test/stderr/0502
@@ -1 +1,3 @@
1999-03-02 09:44:33 ACL for QUIT returned ERROR: QUIT or not-QUIT teplevel ACL may not fail ('deny' verb used incorrectly)
+
+******** SERVER ********
diff --git a/test/stdout/0502 b/test/stdout/0502
index a0fbe6b00..edb6d3156 100644
--- a/test/stdout/0502
+++ b/test/stdout/0502
@@ -19,3 +19,23 @@
220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
250 OK
221 myhost.test.ex closing connection
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> EHLO test.ex
+??? 250-
+<<< 250-myhost.test.ex Hello test.ex [127.0.0.1]
+??? 250-
+<<< 250-SIZE 52428800
+??? 250-
+<<< 250-8BITMIME
+??? 250-
+<<< 250-PIPELINING
+??? 250 HELP
+<<< 250 HELP
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+???*eof
+Expected EOF read
+End of script