Instead of a bare recv() to read the server's response to an SSL

request packet, use pqReadData().  This has the same effect since
conn->ssl isn't set yet and we aren't expecting more than one byte.
The advantage is that we will correctly detect loss-of-connection
instead of going into an infinite loop.  Per report from Hannu Krosing.
This commit is contained in:
Tom Lane 2005-01-06 20:06:58 +00:00
parent a3f98d5795
commit 4717992b4e
1 changed files with 21 additions and 15 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.297 2005/01/06 18:29:10 tgl Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.298 2005/01/06 20:06:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1452,30 +1452,36 @@ keep_going: /* We will come back to here until there
/* /*
* On first time through, get the postmaster's response to * On first time through, get the postmaster's response to
* our SSL negotiation packet. Be careful to read only * our SSL negotiation packet.
* one byte (if there's more, it could be SSL data).
*/ */
if (conn->ssl == NULL) if (conn->ssl == NULL)
{ {
/*
* We use pqReadData here since it has the logic to
* distinguish no-data-yet from connection closure.
* Since conn->ssl isn't set, a plain recv() will occur.
*/
char SSLok; char SSLok;
int nread; int rdresult;
retry_ssl_read: rdresult = pqReadData(conn);
nread = recv(conn->sock, &SSLok, 1, 0); if (rdresult < 0)
if (nread < 0)
{ {
if (SOCK_ERRNO == EINTR) /* errorMessage is already filled in */
/* Interrupted system call - just try again */
goto retry_ssl_read;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return; goto error_return;
} }
if (nread == 0) if (rdresult == 0)
{
/* caller failed to wait for data */ /* caller failed to wait for data */
return PGRES_POLLING_READING; return PGRES_POLLING_READING;
}
if (pqGetc(&SSLok, conn) < 0)
{
/* should not happen really */
return PGRES_POLLING_READING;
}
/* mark byte consumed */
conn->inStart = conn->inCursor;
if (SSLok == 'S') if (SSLok == 'S')
{ {
/* Do one-time setup; this creates conn->ssl */ /* Do one-time setup; this creates conn->ssl */