diff options
Diffstat (limited to 'src/backend/libpq')
| -rw-r--r-- | src/backend/libpq/be-secure.c | 52 | ||||
| -rw-r--r-- | src/backend/libpq/pqcomm.c | 12 |
2 files changed, 56 insertions, 8 deletions
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 5612c29f8b2..1663f36b6b8 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -109,18 +109,51 @@ 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_remaining_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_remaining_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 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 } /* @@ -232,6 +265,19 @@ secure_raw_read(Port *port, void *ptr, size_t len) { ssize_t n; + /* Read from the "unread" buffered data first. c.f. libpq-be.h */ + if (port->raw_buf_remaining > 0) + { + /* consume up to len bytes from the raw_buf */ + if (len > port->raw_buf_remaining) + len = port->raw_buf_remaining; + Assert(port->raw_buf); + memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len); + port->raw_buf_consumed += len; + port->raw_buf_remaining -= len; + return len; + } + /* * Try to read from the socket without blocking. If it succeeds we're * done, otherwise we'll wait for the socket using the latch mechanism. diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index dcea5648acd..2cee49a2085 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -1116,15 +1116,17 @@ pq_discardbytes(size_t len) } /* -------------------------------- - * pq_buffer_has_data - is any buffered data available to read? + * pq_buffer_remaining_data - return number of bytes in receive buffer * - * This will *not* attempt to read more data. + * This will *not* attempt to read more data. And reading up to that number of + * bytes should not cause reading any more data either. * -------------------------------- */ -bool -pq_buffer_has_data(void) +ssize_t +pq_buffer_remaining_data(void) { - return (PqRecvPointer < PqRecvLength); + Assert(PqRecvLength >= PqRecvPointer); + return (PqRecvLength - PqRecvPointer); } |
