From 7aec324c254c834008bbcd94b23fc4eba4977512 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 10 Jan 2024 09:04:45 +0200 Subject: [PATCH v7 04/12] WIP: refactorings to backend support --- src/backend/libpq/be-secure.c | 38 +++++++++++++++++++++-- src/backend/libpq/pqcomm.c | 4 +-- src/backend/postmaster/postmaster.c | 47 ++++++----------------------- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 0e4786cb2b6..8c770ba5afb 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -112,18 +112,50 @@ secure_loaded_verify_locations(void) int secure_open_server(Port *port) { +#ifdef USE_SSL int r = 0; + ssize_t len; + + /* push unencrypted buffered data back through SSL setup */ + len = pq_buffer_has_data(); + if (len > 0) + { + char *buf = palloc(len); + + pq_startmsgread(); + if (pq_getbytes(buf, len) == EOF) + return STATUS_ERROR; /* shouldn't be possible */ + pq_endmsgread(); + port->raw_buf = buf; + port->raw_buf_remaining = len; + port->raw_buf_consumed = 0; + } + Assert(pq_buffer_has_data() == 0); -#ifdef USE_SSL r = be_tls_open_server(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"); + return STATUS_ERROR; + } + if (port->raw_buf != NULL) + { + pfree(port->raw_buf); + port->raw_buf = NULL; + } + ereport(DEBUG2, (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"", port->peer_dn ? port->peer_dn : "(anonymous)", port->peer_cn ? port->peer_cn : "(anonymous)"))); -#endif - return r; +#else + return 0; +#endif } /* diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index ff3a03a2428..caa502b6373 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -1134,9 +1134,7 @@ pq_discardbytes(size_t len) } /* -------------------------------- - * pq_buffer_has_data - is any buffered data available to read? - * - * Actually returns the number of bytes in the buffer... + * pq_buffer_has_data - return number of bytes in receive buffer * * This will *not* attempt to read more data. And reading up to that number of * bytes should not cause reading any more data either. diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 085c940aec5..b70e41c9e26 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -1933,13 +1933,10 @@ ServerLoop(void) * This happens before startup packets so we are careful not to actual read * any bytes from the stream if it's not a direct SSL connection. */ - static int ProcessSSLStartup(Port *port) { - int firstbyte; - - pq_startmsgread(); + int firstbyte; pq_startmsgread(); firstbyte = pq_peekbyte(); @@ -1956,7 +1953,9 @@ ProcessSSLStartup(Port *port) * scanners, which may be less benign, but it's not really our job to * notice those.) */ - return STATUS_ERROR; + // XXX: this is OK as far as this function is concerned. Let ProcessStartupPacket + // handle it + return STATUS_OK; } /* @@ -1967,51 +1966,25 @@ ProcessSSLStartup(Port *port) */ if (firstbyte == 0x16) { -#ifdef USE_SSL - ssize_t len; - char *buf = NULL; elog(LOG, "Detected direct SSL handshake"); - /* 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) +#ifdef USE_SSL + if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use) { - ereport(COMMERROR, - (errcode(ERRCODE_PROTOCOL_VIOLATION), - errmsg("SSL Protocol Error during direct SSL connection initiation"))); + // XXX: Send TLS alert ? return STATUS_ERROR; } - - if (port->raw_buf_remaining > 0) + else if (secure_open_server(port) == -1) { - /* 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"); + /* we assume secure_open_server() sent an appropriate TLS alert already */ return STATUS_ERROR; } - pfree(port->raw_buf); #else - ereport(COMMERROR, - (errcode(ERRCODE_PROTOCOL_VIOLATION), - errmsg("Received direct SSL connection request with no SSL support"))); + // XXX: Send TLS alert ? return STATUS_ERROR; #endif } - pq_endmsgread(); - if (port->ssl_in_use) ereport(DEBUG2, (errmsg_internal("Direct SSL connection established"))); -- 2.39.2