summaryrefslogtreecommitdiff
path: root/src/backend/libpq
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq')
-rw-r--r--src/backend/libpq/be-secure.c52
-rw-r--r--src/backend/libpq/pqcomm.c12
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);
}