From 07197e9aba2715e6d864a95d09b06c3486e4cbca Mon Sep 17 00:00:00 2001 From: Greg Stark Date: Fri, 31 Mar 2023 02:31:31 -0400 Subject: [PATCH v5 5/6] Allow pipelining data after ssl request --- src/backend/postmaster/postmaster.c | 54 ++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 9b4b37b997..33b317f98b 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -2001,13 +2001,14 @@ ProcessSSLStartup(Port *port) if (port->raw_buf_remaining > 0) { - /* This shouldn't be possible -- it would mean the client sent - * encrypted data before we established a session key... - */ - elog(LOG, "Buffered unencrypted data remains after negotiating native SSL connection"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("received unencrypted data after SSL request"), + errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack."))); return STATUS_ERROR; } - pfree(port->raw_buf); + if (port->raw_buf) + pfree(port->raw_buf); if (port->ssl_alpn_protocol == NULL) { @@ -2158,15 +2159,44 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) } #ifdef USE_SSL - if (SSLok == 'S' && secure_open_server(port) == -1) - return STATUS_ERROR; + if (SSLok == 'S') + { + /* push unencrypted buffered data back through SSL setup */ + len = pq_buffer_has_data(); + if (len > 0) + { + buf = palloc(len); + if (pq_getbytes(buf, len) == EOF) + return STATUS_ERROR; /* shouldn't be possible */ + port->raw_buf = buf; + port->raw_buf_remaining = len; + port->raw_buf_consumed = 0; + } + Assert(pq_buffer_has_data() == 0); + + if (secure_open_server(port) == -1) + return STATUS_ERROR; + + /* + * At this point we should have no data already buffered. If we do, + * it was received before we performed the SSL handshake, so it wasn't + * encrypted and indeed may have been injected by a man-in-the-middle. + * We report this case to the client. + */ + if (port->raw_buf_remaining > 0) + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("received unencrypted data after SSL request"), + errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack."))); + if (port->raw_buf) + pfree(port->raw_buf); + } #endif - /* - * At this point we should have no data already buffered. If we do, - * it was received before we performed the SSL handshake, so it wasn't - * encrypted and indeed may have been injected by a man-in-the-middle. - * We report this case to the client. + /* This can only really occur now if there was data pipelined after + * the SSL Request but we have refused to do SSL. In that case we need + * to give up because the client has presumably assumed the SSL + * request would be accepted. */ if (pq_buffer_has_data()) ereport(FATAL, -- 2.40.0