summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2017-10-21 18:36:31 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2017-10-21 18:51:55 +0100
commitd097cc730a1ab358bad80338b30b49287d1274c3 (patch)
treed84b16fd24be703e53d39bc195e8d957149b7d94 /src
parente5ab0ba9eb0f4424dfa31128f36b27b6769d7795 (diff)
Testsuite: make debug output for proxied TLS less indeterminate
Diffstat (limited to 'src')
-rw-r--r--src/src/deliver.c10
-rw-r--r--src/src/functions.h2
-rw-r--r--src/src/transports/smtp.c72
3 files changed, 44 insertions, 40 deletions
diff --git a/src/src/deliver.c b/src/src/deliver.c
index 89ad7e5ea..295ae42c4 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -8507,14 +8507,10 @@ if (cutthrough.fd >= 0 && cutthrough.callout_hold_only)
goto fail;
else if (pid == 0) /* child: fork again to totally disconnect */
- {
- close(pfd[1]);
- if ((pid = fork()))
- _exit(pid < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
- smtp_proxy_tls(big_buffer, big_buffer_size, pfd[0], 5*60);
- exim_exit(0, US"TLS proxy");
- }
+ /* does not return */
+ smtp_proxy_tls(big_buffer, big_buffer_size, pfd, 5*60);
+ DEBUG(D_transport) debug_printf("proxy-proc inter-pid %d\n", pid);
close(pfd[0]);
waitpid(pid, NULL, 0);
(void) close(channel_fd); /* release the client socket */
diff --git a/src/src/functions.h b/src/src/functions.h
index 760a9f52b..1fe561f56 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -412,7 +412,7 @@ extern void smtp_get_cache(void);
extern int smtp_handle_acl_fail(int, int, uschar *, uschar *);
extern void smtp_log_no_mail(void);
extern void smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
-extern void smtp_proxy_tls(uschar *, size_t, int, int);
+extern void smtp_proxy_tls(uschar *, size_t, int *, int);
extern BOOL smtp_read_response(smtp_inblock *, uschar *, int, int, int);
extern void smtp_respond(uschar *, int, BOOL, uschar *);
extern void smtp_notquit_exit(uschar *, uschar *, uschar *, ...);
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index ca06bf6bd..5f9d4313c 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -2580,29 +2580,37 @@ return 0;
* Proxy TLS connection for another transport process *
******************************************************/
/*
-Use the given buffer as a staging area, and select on both the given fd
-and the TLS'd client-fd for data to read (per the coding in ip_recv() and
-fd_ready() this is legitimate). Do blocking full-size writes, and reads
-under a timeout.
+Close the unused end of the pipe, fork once more, then use the given buffer
+as a staging area, and select on both the given fd and the TLS'd client-fd for
+data to read (per the coding in ip_recv() and fd_ready() this is legitimate).
+Do blocking full-size writes, and reads under a timeout. Once both input
+channels are closed, exit the process.
Arguments:
buf space to use for buffering
bufsiz size of buffer
- proxy_fd comms to proxied process
+ pfd pipe filedescriptor array; [0] is comms to proxied process
timeout per-read timeout, seconds
*/
void
-smtp_proxy_tls(uschar * buf, size_t bsize, int proxy_fd, int timeout)
+smtp_proxy_tls(uschar * buf, size_t bsize, int * pfd, int timeout)
{
fd_set rfds, efds;
-int max_fd = MAX(proxy_fd, tls_out.active) + 1;
+int max_fd = MAX(pfd[0], tls_out.active) + 1;
int rc, i, fd_bits, nbytes;
+close(pfd[1]);
+if ((rc = fork()))
+ {
+ DEBUG(D_transport) debug_printf("proxy-proc final-pid %d\n", rc);
+ _exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+ }
+
set_process_info("proxying TLS connection for continued transport");
FD_ZERO(&rfds);
FD_SET(tls_out.active, &rfds);
-FD_SET(proxy_fd, &rfds);
+FD_SET(pfd[0], &rfds);
for (fd_bits = 3; fd_bits; )
{
@@ -2624,17 +2632,17 @@ for (fd_bits = 3; fd_bits; )
if (rc <= 0)
{
DEBUG(D_transport) if (rc == 0) debug_printf("%s: timed out\n", __FUNCTION__);
- return;
+ goto done;
}
- if (FD_ISSET(tls_out.active, &efds) || FD_ISSET(proxy_fd, &efds))
+ if (FD_ISSET(tls_out.active, &efds) || FD_ISSET(pfd[0], &efds))
{
DEBUG(D_transport) debug_printf("select: exceptional cond on %s fd\n",
- FD_ISSET(proxy_fd, &efds) ? "proxy" : "tls");
- return;
+ FD_ISSET(pfd[0], &efds) ? "proxy" : "tls");
+ goto done;
}
}
- while (rc < 0 || !(FD_ISSET(tls_out.active, &rfds) || FD_ISSET(proxy_fd, &rfds)));
+ while (rc < 0 || !(FD_ISSET(tls_out.active, &rfds) || FD_ISSET(pfd[0], &rfds)));
/* handle inbound data */
if (FD_ISSET(tls_out.active, &rfds))
@@ -2642,20 +2650,20 @@ for (fd_bits = 3; fd_bits; )
{
fd_bits &= ~1;
FD_CLR(tls_out.active, &rfds);
- shutdown(proxy_fd, SHUT_WR);
+ shutdown(pfd[0], SHUT_WR);
timeout = 5;
}
else
{
for (nbytes = 0; rc - nbytes > 0; nbytes += i)
- if ((i = write(proxy_fd, buf + nbytes, rc - nbytes)) < 0) return;
+ if ((i = write(pfd[0], buf + nbytes, rc - nbytes)) < 0) goto done;
}
else if (fd_bits & 1)
FD_SET(tls_out.active, &rfds);
/* handle outbound data */
- if (FD_ISSET(proxy_fd, &rfds))
- if ((rc = read(proxy_fd, buf, bsize)) <= 0)
+ if (FD_ISSET(pfd[0], &rfds))
+ if ((rc = read(pfd[0], buf, bsize)) <= 0)
{
fd_bits = 0;
tls_close(FALSE, TRUE);
@@ -2664,11 +2672,15 @@ for (fd_bits = 3; fd_bits; )
{
for (nbytes = 0; rc - nbytes > 0; nbytes += i)
if ((i = tls_write(FALSE, buf + nbytes, rc - nbytes, FALSE)) < 0)
- return;
+ goto done;
}
else if (fd_bits & 2)
- FD_SET(proxy_fd, &rfds);
+ FD_SET(pfd[0], &rfds);
}
+
+done:
+ if (running_in_test_harness) millisleep(100); /* let logging complete */
+ exim_exit(0, US"TLS proxy");
}
#endif
@@ -3485,7 +3497,8 @@ propagate it from the initial
{
sx.send_quit = FALSE;
- /* If TLS is still active, we need to proxy it for the transport we
+ /* We have passed the client socket to a fresh transport process.
+ If TLS is still active, we need to proxy it for the transport we
just passed the baton to. Fork a child to to do it, and return to
get logging done asap. Which way to place the work makes assumptions
about post-fork prioritisation which may not hold on all platforms. */
@@ -3493,10 +3506,16 @@ propagate it from the initial
if (tls_out.active >= 0)
{
int pid = fork();
+ if (pid == 0) /* child; fork again to disconnect totally */
+ /* does not return */
+ smtp_proxy_tls(sx.buffer, sizeof(sx.buffer), pfd,
+ sx.ob->command_timeout);
+
if (pid > 0) /* parent */
{
DEBUG(D_transport) debug_printf("proxy-proc inter-pid %d\n", pid);
close(pfd[0]);
+ /* tidy the inter-proc to disconn the proxy proc */
waitpid(pid, NULL, 0);
tls_close(FALSE, FALSE);
(void)close(sx.inblock.sock);
@@ -3504,18 +3523,7 @@ propagate it from the initial
continue_hostname = NULL;
return yield;
}
- else if (pid == 0) /* child; fork again to disconnect totally */
- {
- close(pfd[1]);
- if ((pid = fork()))
- {
- DEBUG(D_transport) debug_printf("proxy-prox final-pid %d\n", pid);
- _exit(pid < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
- }
- smtp_proxy_tls(sx.buffer, sizeof(sx.buffer), pfd[0], sx.ob->command_timeout);
- if (running_in_test_harness) millisleep(100); /* let logging complete */
- exim_exit(0, US"TLS proxy");
- }
+ log_write(0, LOG_PANIC_DIE, "fork failed");
}
#endif
}