@ -1366,6 +1366,17 @@ static int pq_discardbytes(size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_buffer_has_data - is any buffered data available to read?
|
||||
*
|
||||
* This will *not* attempt to read more data.
|
||||
* --------------------------------
|
||||
*/
|
||||
bool pq_buffer_has_data(void)
|
||||
{
|
||||
return (t_thrd.libpq_cxt.PqRecvPointer < t_thrd.libpq_cxt.PqRecvLength);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getstring - get a null terminated string from connection
|
||||
*
|
||||
|
||||
@ -2610,6 +2610,18 @@ keep_going: /* We will come back to here until there is
|
||||
*/
|
||||
pollres = pqsecure_open_client(conn);
|
||||
if (pollres == PGRES_POLLING_OK) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (conn->inCursor != conn->inEnd) {
|
||||
appendPQExpBufferStr(&conn->errorMessage,
|
||||
libpq_gettext("received unencrypted data after SSL response\n"));
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* SSL handshake done, ready to send startup packet */
|
||||
conn->status = CONNECTION_MADE;
|
||||
return PGRES_POLLING_WRITING;
|
||||
|
||||
@ -3584,6 +3584,18 @@ int ProcessStartupPacket(Port* port, bool SSLdone)
|
||||
}
|
||||
|
||||
#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.
|
||||
*/
|
||||
if (pq_buffer_has_data()) {
|
||||
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.")));
|
||||
}
|
||||
|
||||
/* regular startup packet, cancel, etc packet should follow... */
|
||||
/* but not another SSL negotiation request */
|
||||
return ProcessStartupPacket(port, true);
|
||||
|
||||
@ -56,6 +56,7 @@ extern int pq_getmessage(StringInfo s, int maxlen);
|
||||
extern int pq_getbyte(void);
|
||||
extern int pq_peekbyte(void);
|
||||
extern int pq_getbyte_if_available(unsigned char* c);
|
||||
extern bool pq_buffer_has_data(void);
|
||||
extern int pq_putbytes(const char* s, size_t len);
|
||||
extern int pq_flush(void);
|
||||
extern int pq_flush_if_writable(void);
|
||||
|
||||
Reference in New Issue
Block a user