File: 87_GnuTLS-avoid-logging-error-on-seeing-TCP-drop-after-.patch

package info (click to toggle)
exim4 4.99-6
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 26,076 kB
  • sloc: ansic: 119,292; sh: 4,071; xml: 2,112; perl: 918; makefile: 532
file content (198 lines) | stat: -rw-r--r-- 6,277 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
From 6d6d322cedd046a058ba0c3a42b2cf54143d2ce5 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
Date: Sun, 26 Oct 2025 18:18:13 +0000
Subject: [PATCH] GnuTLS: avoid logging error on seeing TCP-drop after sending
 QUIT

---
 src/globals.h         |  1 +
 src/tls-gnu.c         | 15 +++++++++++----
 src/transports/smtp.c | 12 ++++++++++++
 test/log/1167             |  2 --
 4 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/globals.h b/src/globals.h
index 401fb794c..392180111 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -115,14 +115,15 @@ typedef struct {
   BOOL	  ticket_received:1;
 #endif
 
   BOOL	  ext_master_secret:1;	/* extended-master-secret was used */
   BOOL	  channelbind_exporter:1; /* channelbinding is EXPORTER not UNIQUE */
   BOOL    on_connect:1;         /* For older MTAs that don't STARTTLS */
   BOOL	  verify_override:1;	/* certificate_verified only due to tls_try_verify_hosts */
+  BOOL	  smtp_quit:1;		/* QUIT has been sent or received */
 } tls_support;
 extern tls_support tls_in;
 extern tls_support tls_out;
 #endif	/*!MACRO_PREDEF*/
 
 #ifndef DISABLE_TLS
 extern BOOL    gnutls_compat_mode;     /* Less security, more compatibility */
diff --git a/src/tls-gnu.c b/src/tls-gnu.c
index a265e9af7..f6be70863 100644
--- a/src/tls-gnu.c
+++ b/src/tls-gnu.c
@@ -574,24 +574,31 @@ msg = rc == GNUTLS_E_FATAL_ALERT_RECEIVED
   : rc == GNUTLS_E_PREMATURE_TERMINATION && errno
   ? string_sprintf("%s: syscall: %s", US gnutls_strerror(rc), strerror(errno))
 #endif
   : US gnutls_strerror(rc);
 
 (void) tls_error(when, msg, state->host, &errstr);
 
-if (state->host)
-  log_write(0, LOG_MAIN, "H=%s [%s] TLS error on connection %s",
-    state->host->name, state->host->address, errstr);
-else
+if (!state->host)
   {
   uschar * conn_info = smtp_get_connection_info();
   if (Ustrncmp(conn_info, US"SMTP ", 5) == 0) conn_info += 5;
   /* I'd like to get separated H= here, but too hard for now */
   log_write(0, LOG_MAIN, "TLS error on %s %s", conn_info, errstr);
   }
+else if (  !tls_out.smtp_quit
+#ifdef GNUTLS_E_PREMATURE_TERMINATION
+	|| rc != GNUTLS_E_PREMATURE_TERMINATION
+#endif
+	)
+  log_write(0, LOG_MAIN, "H=%s [%s] TLS error on connection %s",
+    state->host->name, state->host->address, errstr);
+else DEBUG(D_tls)
+  debug_printf("H=%s [%s] TLS error on connection %s\n",
+    state->host->name, state->host->address, errstr);
 }
 
 
 
 static BOOL
 tls_refill(unsigned lim)
 {
diff --git a/src/transports/smtp.c b/src/transports/smtp.c
index d7cd93d6e..808c1a76d 100644
--- a/src/transports/smtp.c
+++ b/src/transports/smtp.c
@@ -2376,14 +2376,15 @@ if (continue_hostname && continue_proxy_cipher)
 		    "due to SNI mismatch (transport requirement '%s')\n",
 		    continue_proxy_sni, sni);
 
     smtp_debug_cmd(US"QUIT", 0);
     if (write(0, "QUIT\r\n", 6) < 0)
       DEBUG(D_any) debug_printf("stupid compiler\n");
     close(0);
+    tls_out.active.sock = -1;
     continue_hostname = continue_proxy_cipher = NULL;
     f.continue_more = FALSE;
     continue_sequence = 1;	/* Ensure proper logging of non-cont-conn */
     }
   }
 #endif	/*!DISABLE_TLS*/
 
@@ -2877,14 +2878,15 @@ else
       DEBUG(D_transport)
 	debug_printf("Closing continued connection due to port mismatch:"
 	  " %d/%d\n", sx->conn_args.host->port, continue_host_port);
       smtp_debug_cmd(US"QUIT", 0);
       if (write(0, "QUIT\r\n", 6) < 0)
 	DEBUG(D_any) debug_printf("stupid compiler\n");
       close(0);
+      tls_out.active.sock = -1;
       continue_hostname = continue_proxy_cipher = NULL;
       f.continue_more = FALSE;
       continue_sequence = 1;	/* Ensure proper logging of non-cont-conn */
       return smtp_setup_conn(sx, suppress_tls);
       }
     }
 
@@ -3022,14 +3024,15 @@ if (  smtp_peer_options & OPTION_TLS
 # endif
 
       errno = ERRNO_TLSFAILURE;
       message = string_sprintf("TLS session: %s", tls_errstr);
       sx->send_quit = FALSE;
       goto TLS_FAILED;
       }
+    tls_out.smtp_quit = FALSE;
     sx->send_tlsclose = TRUE;
 
 # ifdef TCP_FASTOPEN
     if (sx->smtps) tfo_out_check(sx->cctx.sock);
 # endif
 
     /* TLS session is set up.  Check the inblock fill level.  If there is
@@ -3479,15 +3482,18 @@ FAILED:
 	    &sx->delivery_start);
   }
 
 
 SEND_QUIT:
 
 if (sx->send_quit)
+  {
   (void)smtp_write_command(sx, SCMD_FLUSH, "QUIT\r\n");
+  tls_out.smtp_quit = TRUE;
+  }
 
 #ifndef DISABLE_TLS
 if (sx->cctx.tls_ctx)
   {
   if (sx->send_tlsclose)
     {
     tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
@@ -4471,14 +4477,15 @@ else
 	tls_shutdown_wr(sx->cctx.tls_ctx);
 	sx->send_tlsclose = FALSE;	/* avoid later repeat */
 	}
 #endif
       HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(shutdown)>>\n");
       shutdown(sx->cctx.sock, SHUT_WR);	/* flush output buffer, with TCP FIN */
       }
+    tls_out.smtp_quit = TRUE;
     }
 
   if (smtp_peer_options & OPTION_CHUNKING && sx->cmd_count > 1)
     {
     /* Reap any outstanding MAIL & RCPT commands, but not a DATA-go-ahead */
     switch(sync_responses(sx, sx->cmd_count-1, 0))
       {
@@ -5165,14 +5172,18 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
 been passed to another process. */
 
 SEND_QUIT:
 if (sx->send_quit)
   {			/* Use _MORE to get QUIT in FIN segment */
   (void)smtp_write_command(sx, SCMD_MORE, "QUIT\r\n");
 #ifndef DISABLE_TLS
+  /* This flag is a custom hack to avoid logging, under GnuTLS, Google's
+  habit of just dropping the TCP conn (which violates TLS spec) */
+  tls_out.smtp_quit = TRUE;
+
   if (sx->cctx.tls_ctx && sx->send_tlsclose)
     {
 # ifdef EXIM_TCP_CORK	/* Use _CORK to get TLS Close Notify in FIN segment */
     (void) setsockopt(sx->cctx.sock, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
 # endif
     tls_shutdown_wr(sx->cctx.tls_ctx);
     sx->send_tlsclose = FALSE;
@@ -5352,14 +5363,15 @@ sx.outblock.cctx = &cctx;
 sx.outblock.buffersize = sizeof(outbuffer);
 sx.outblock.buffer = outbuffer;
 sx.outblock.ptr = outbuffer;
 sx.outblock.cmd_count = 0;
 sx.outblock.authenticating = FALSE;
 
 (void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
+tls_out.smtp_quit = TRUE;
 (void)smtp_read_response(&sx, buffer, sizeof(buffer), '2', ob->command_timeout);
 (void)close(cctx.sock);
 }
 
 
 
 
-- 
2.51.0