Code review for sslmode patch: eliminate memory leak, avoid giving a

completely useless error message in 'allow' case, don't retry connection
at the sendauth stage (by then the server will either let us in or not,
no point in wasting cycles on another try in the other SSL state).
This commit is contained in:
Tom Lane 2003-08-01 21:27:27 +00:00
parent 13ac54d1ca
commit 57c08791d1
2 changed files with 43 additions and 101 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.256 2003/07/28 00:09:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.257 2003/08/01 21:27:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -366,7 +366,7 @@ connectOptions1(PGconn *conn, const char *conninfo)
/* here warn that the requiressl option is deprecated? */ /* here warn that the requiressl option is deprecated? */
if (conn->sslmode) if (conn->sslmode)
free(conn->sslmode); free(conn->sslmode);
conn->sslmode = "require"; conn->sslmode = strdup("require");
} }
#endif #endif
@ -466,15 +466,14 @@ connectOptions2(PGconn *conn)
case 'r': /* "require" */ case 'r': /* "require" */
conn->status = CONNECTION_BAD; conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("sslmode \"%s\" invalid when SSL " libpq_gettext("sslmode \"%s\" invalid when SSL support is not compiled in\n"),
"support is not compiled in\n"),
conn->sslmode); conn->sslmode);
return false; return false;
} }
#endif #endif
} }
else else
conn->sslmode = DefaultSSLMode; conn->sslmode = strdup(DefaultSSLMode);
return true; return true;
} }
@ -1351,7 +1350,8 @@ retry_connect:
/* Don't bother requesting SSL over a Unix socket */ /* Don't bother requesting SSL over a Unix socket */
conn->allow_ssl_try = false; conn->allow_ssl_try = false;
} }
if (conn->allow_ssl_try && !conn->wait_ssl_try && conn->ssl == NULL) if (conn->allow_ssl_try && !conn->wait_ssl_try &&
conn->ssl == NULL)
{ {
ProtocolVersion pv; ProtocolVersion pv;
@ -1455,22 +1455,13 @@ retry_ssl_read:
} }
else if (SSLok == 'N') else if (SSLok == 'N')
{ {
switch (conn->sslmode[0]) { if (conn->sslmode[0] == 'r') /* "require" */
case 'r': /* "require" */ {
/* Require SSL, but server does not want it */ /* Require SSL, but server does not want it */
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server does not support SSL, but SSL was required\n")); libpq_gettext("server does not support SSL, but SSL was required\n"));
goto error_return; goto error_return;
case 'a': /* "allow" */
/*
* normal startup already failed,
* so SSL failure means the end
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server does not support SSL, and previous non-SSL attempt failed\n"));
goto error_return;
} }
/* Otherwise, proceed with normal startup */ /* Otherwise, proceed with normal startup */
conn->allow_ssl_try = false; conn->allow_ssl_try = false;
conn->status = CONNECTION_MADE; conn->status = CONNECTION_MADE;
@ -1481,22 +1472,13 @@ retry_ssl_read:
/* Received error - probably protocol mismatch */ /* Received error - probably protocol mismatch */
if (conn->Pfdebug) if (conn->Pfdebug)
fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n"); fprintf(conn->Pfdebug, "Postmaster reports error, attempting fallback to pre-7.0.\n");
switch (conn->sslmode[0]) { if (conn->sslmode[0] == 'r') /* "require" */
case 'r': /* "require" */ {
/* Require SSL, but server is too old */ /* Require SSL, but server is too old */
printfPQExpBuffer(&conn->errorMessage, printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server does not support SSL, but SSL was required\n")); libpq_gettext("server does not support SSL, but SSL was required\n"));
goto error_return; goto error_return;
case 'a': /* "allow" */
/*
* normal startup already failed,
* so SSL failure means the end
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server does not support SSL, and previous non-SSL attempt failed\n"));
goto error_return;
} }
/* Otherwise, try again without SSL */ /* Otherwise, try again without SSL */
conn->allow_ssl_try = false; conn->allow_ssl_try = false;
/* Assume it ain't gonna handle protocol 3, either */ /* Assume it ain't gonna handle protocol 3, either */
@ -1686,13 +1668,15 @@ retry_ssl_read:
#ifdef USE_SSL #ifdef USE_SSL
/* /*
* if sslmode is "allow" and we haven't tried an * if sslmode is "allow" and we haven't tried an SSL
* SSL connection already, then retry with an SSL connection * connection already, then retry with an SSL connection
*/ */
if (conn->wait_ssl_try if (conn->sslmode[0] == 'a' /* "allow" */
&& conn->ssl == NULL && conn->ssl == NULL
&& conn->allow_ssl_try) && conn->allow_ssl_try
&& conn->wait_ssl_try)
{ {
/* only retry once */
conn->wait_ssl_try = false; conn->wait_ssl_try = false;
/* Must drop the old connection */ /* Must drop the old connection */
closesocket(conn->sock); closesocket(conn->sock);
@ -1703,20 +1687,19 @@ retry_ssl_read:
/* /*
* if sslmode is "prefer" and we're in an SSL * if sslmode is "prefer" and we're in an SSL
* connection and we haven't already tried a non-SSL * connection, then do a non-SSL retry
* for "allow", then do a non-SSL retry
*/ */
if (!conn->wait_ssl_try if (conn->sslmode[0] == 'p' /* "prefer" */
&& conn->ssl && conn->ssl
&& conn->allow_ssl_try && conn->allow_ssl_try /* redundant? */
&& conn->sslmode[0] == 'p') /* "prefer" */ && !conn->wait_ssl_try) /* redundant? */
{ {
/* only retry once */
conn->allow_ssl_try = false; conn->allow_ssl_try = false;
/* Must drop the old connection */ /* Must drop the old connection */
pqsecure_close(conn); pqsecure_close(conn);
closesocket(conn->sock); closesocket(conn->sock);
conn->sock = -1; conn->sock = -1;
free(conn->ssl);
conn->status = CONNECTION_NEEDED; conn->status = CONNECTION_NEEDED;
goto keep_going; goto keep_going;
} }
@ -1773,44 +1756,6 @@ retry_ssl_read:
if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass, if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass,
conn->errorMessage.data) != STATUS_OK) conn->errorMessage.data) != STATUS_OK)
{ {
#ifdef USE_SSL
/*
* if sslmode is "allow" and we haven't tried an
* SSL connection already, then retry with an SSL connection
*/
if (conn->wait_ssl_try
&& conn->ssl == NULL
&& conn->allow_ssl_try)
{
conn->wait_ssl_try = false;
/* Must drop the old connection */
closesocket(conn->sock);
conn->sock = -1;
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
/*
* if sslmode is "prefer" and we're in an SSL
* connection and we haven't already tried a non-SSL
* for "allow", then do a non-SSL retry
*/
if (!conn->wait_ssl_try
&& conn->ssl
&& conn->allow_ssl_try
&& conn->sslmode[0] == 'p') /* "prefer" */
{
conn->allow_ssl_try = false;
/* Must drop the old connection */
pqsecure_close(conn);
closesocket(conn->sock);
conn->sock = -1;
free(conn->ssl);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
#endif
conn->errorMessage.len = strlen(conn->errorMessage.data); conn->errorMessage.len = strlen(conn->errorMessage.data);
goto error_return; goto error_return;
} }
@ -1968,27 +1913,21 @@ error_return:
static PGconn * static PGconn *
makeEmptyPGconn(void) makeEmptyPGconn(void)
{ {
PGconn *conn = (PGconn *) malloc(sizeof(PGconn)); PGconn *conn;
/* needed to use the static libpq under windows as well */
#ifdef WIN32 #ifdef WIN32
/* needed to use the static libpq under windows as well */
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData))
return (PGconn*) NULL;
WSASetLastError(0);
#endif #endif
conn = (PGconn *) malloc(sizeof(PGconn));
if (conn == NULL) if (conn == NULL)
return conn; return conn;
#ifdef WIN32
if (WSAStartup(MAKEWORD(1, 1), &wsaData))
{
free(conn);
return (PGconn*) NULL;
}
WSASetLastError(0);
#endif
/* Zero all pointers and booleans */ /* Zero all pointers and booleans */
MemSet((char *) conn, 0, sizeof(PGconn)); MemSet((char *) conn, 0, sizeof(PGconn));
@ -2003,7 +1942,8 @@ makeEmptyPGconn(void)
conn->notifyList = DLNewList(); conn->notifyList = DLNewList();
conn->sock = -1; conn->sock = -1;
#ifdef USE_SSL #ifdef USE_SSL
conn->allow_ssl_try = TRUE; conn->allow_ssl_try = true;
conn->wait_ssl_try = false;
#endif #endif
/* /*
@ -2073,6 +2013,8 @@ freePGconn(PGconn *conn)
free(conn->pguser); free(conn->pguser);
if (conn->pgpass) if (conn->pgpass)
free(conn->pgpass); free(conn->pgpass);
if (conn->sslmode)
free(conn->sslmode);
/* Note that conn->Pfdebug is not ours to close or free */ /* Note that conn->Pfdebug is not ours to close or free */
if (conn->notifyList) if (conn->notifyList)
DLFreeList(conn->notifyList); DLFreeList(conn->notifyList);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq-int.h,v 1.77 2003/07/26 13:50:02 momjian Exp $ * $Id: libpq-int.h,v 1.78 2003/08/01 21:27:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -249,6 +249,7 @@ struct pg_conn
char *dbName; /* database name */ char *dbName; /* database name */
char *pguser; /* Postgres username and password, if any */ char *pguser; /* Postgres username and password, if any */
char *pgpass; char *pgpass;
char *sslmode; /* SSL mode (require,prefer,allow,disable) */
/* Optional file to write trace info to */ /* Optional file to write trace info to */
FILE *Pfdebug; FILE *Pfdebug;
@ -316,11 +317,10 @@ struct pg_conn
PGresult *result; /* result being constructed */ PGresult *result; /* result being constructed */
PGresAttValue *curTuple; /* tuple currently being read */ PGresAttValue *curTuple; /* tuple currently being read */
char *sslmode; /* SSL mode option string */
#ifdef USE_SSL #ifdef USE_SSL
bool allow_ssl_try; /* Allowed to try SSL negotiation */ bool allow_ssl_try; /* Allowed to try SSL negotiation */
bool wait_ssl_try; /* Delay SSL negotiation until after bool wait_ssl_try; /* Delay SSL negotiation until after
attempting normal connection */ * attempting normal connection */
SSL *ssl; /* SSL status, if have SSL connection */ SSL *ssl; /* SSL status, if have SSL connection */
X509 *peer; /* X509 cert of server */ X509 *peer; /* X509 cert of server */
char peer_dn[256 + 1]; /* peer distinguished name */ char peer_dn[256 + 1]; /* peer distinguished name */