aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r--src/interfaces/libpq/fe-connect.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 4e86a8db91e..bb61cdfd5bd 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.102 1999/08/31 01:37:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.103 1999/09/27 03:13:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,6 +40,10 @@
#include "mb/pg_wchar.h"
#endif
+#ifdef USE_SSL
+static SSL_CTX *SSL_context = NULL;
+#endif
+
static ConnStatusType connectDB(PGconn *conn);
static PGconn *makeEmptyPGconn(void);
static void freePGconn(PGconn *conn);
@@ -508,6 +512,12 @@ connectDB(PGconn *conn)
family;
char beresp;
int on = 1;
+#ifdef USE_SSL
+ StartupPacket np; /* Used to negotiate SSL connection */
+ char SSLok;
+ static int allow_ssl_try = 1; /* Allowed to do SSL negotiation */
+ int tried_ssl = 0; /* Set if SSL negotiation was tried */
+#endif
/*
* parse dbName to get all additional info in it, if any
@@ -591,6 +601,70 @@ connectDB(PGconn *conn)
goto connect_errReturn;
}
+ /* This needs to be done before we set into nonblocking, since SSL negotiation
+ * does not like that mode */
+
+#ifdef USE_SSL
+ /* Attempt to negotiate SSL usage */
+ if (allow_ssl_try) {
+ tried_ssl = 1;
+ memset((char *)&np, 0, sizeof(np));
+ np.protoVersion = htonl(NEGOTIATE_SSL_CODE);
+ if (pqPacketSend(conn, (char *) &np, sizeof(StartupPacket)) != STATUS_OK)
+ {
+ sprintf(conn->errorMessage,
+ "connectDB() -- couldn't send SSL negotiation packet: errno=%d\n%s\n",
+ errno, strerror(errno));
+ goto connect_errReturn;
+ }
+ /* Now receive the backends response */
+ if (recv(conn->sock, &SSLok, 1, 0) != 1) {
+ sprintf(conn->errorMessage, "PQconnectDB() -- couldn't read backend response: errno=%d\n%s\n",
+ errno, strerror(errno));
+ goto connect_errReturn;
+ }
+ if (SSLok == 'S') {
+ if (!SSL_context)
+ {
+ SSL_load_error_strings();
+ SSL_library_init();
+ SSL_context = SSL_CTX_new(SSLv23_method());
+ if (!SSL_context) {
+ sprintf(conn->errorMessage,
+ "connectDB() -- couldn't create SSL context: %s\n",
+ ERR_reason_error_string(ERR_get_error()));
+ goto connect_errReturn;
+ }
+ }
+ if (!(conn->ssl = SSL_new(SSL_context)) ||
+ !SSL_set_fd(conn->ssl, conn->sock) ||
+ SSL_connect(conn->ssl) <= 0)
+ {
+ sprintf(conn->errorMessage,
+ "connectDB() -- couldn't establish SSL connection: %s\n",
+ ERR_reason_error_string(ERR_get_error()));
+ goto connect_errReturn;
+ }
+ /* SSL connection finished. Continue to send startup packet */
+ }
+ else if (SSLok == 'E') {
+ /* Received error - probably protocol mismatch */
+ if (conn->Pfdebug)
+ fprintf(conn->Pfdebug, "Backend reports error, attempting fallback to pre-6.6.\n");
+ close(conn->sock);
+ allow_ssl_try = 0;
+ return connectDB(conn);
+ }
+ else if (SSLok != 'N') {
+ strcpy(conn->errorMessage,
+ "Received invalid negotiation response.\n");
+ goto connect_errReturn;
+ }
+ }
+ else
+ allow_ssl_try = 1; /* We'll allow an attempt to use SSL next time */
+#endif
+
/*
* Set the right options. We need nonblocking I/O, and we don't want
* delay of outgoing data.
@@ -896,6 +970,10 @@ freePGconn(PGconn *conn)
if (!conn)
return;
pqClearAsyncResult(conn); /* deallocate result and curTuple */
+#ifdef USE_SSL
+ if (conn->ssl)
+ SSL_free(conn->ssl);
+#endif
if (conn->sock >= 0)
#ifdef WIN32
closesocket(conn->sock);