diff options
| author | Bruce Momjian | 1999-09-27 03:13:16 +0000 |
|---|---|---|
| committer | Bruce Momjian | 1999-09-27 03:13:16 +0000 |
| commit | e0e7daef6daf9a760c9c90bc7fe5b9ba4349267f (patch) | |
| tree | 37489845f4c86ef613737986142354fd8562c0d9 /src/interfaces | |
| parent | 3114f92122d3aa3588e89c166f69b44204d5b3db (diff) | |
Lots of patches coming in from me today :-)
When drawing up a very simple "text-drawing" of how the negotiation is done,
I realised I had done this last part (fallback) in a very stupid way. Patch
#4 fixes this, and does it in a much better way.
Included is also the simple text-drawing of how the negotiation is done.
//Magnus
Diffstat (limited to 'src/interfaces')
| -rw-r--r-- | src/interfaces/libpq/fe-connect.c | 80 | ||||
| -rw-r--r-- | src/interfaces/libpq/fe-misc.c | 26 | ||||
| -rw-r--r-- | src/interfaces/libpq/libpq-int.h | 11 |
3 files changed, 111 insertions, 6 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); diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 85879847e6e..9c87a930186 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -24,7 +24,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.30 1999/09/13 03:00:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.31 1999/09/27 03:13:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -351,7 +351,13 @@ pqReadData(PGconn *conn) /* OK, try to read some data */ tryAgain: - nread = recv(conn->sock, conn->inBuffer + conn->inEnd, +#ifdef USE_SSL + if (conn->ssl) + nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); + else +#endif + nread = recv(conn->sock, conn->inBuffer + conn->inEnd, conn->inBufSize - conn->inEnd, 0); if (nread < 0) { @@ -420,7 +426,13 @@ tryAgain: * arrived. */ tryAgain2: - nread = recv(conn->sock, conn->inBuffer + conn->inEnd, +#ifdef USE_SSL + if (conn->ssl) + nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); + else +#endif + nread = recv(conn->sock, conn->inBuffer + conn->inEnd, conn->inBufSize - conn->inEnd, 0); if (nread < 0) { @@ -494,7 +506,13 @@ pqFlush(PGconn *conn) pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN); #endif - int sent = send(conn->sock, ptr, len, 0); + int sent; +#ifdef USE_SSL + if (conn->ssl) + sent = SSL_write(conn->ssl, ptr, len); + else +#endif + sent = send(conn->sock, ptr, len, 0); #ifndef WIN32 pqsignal(SIGPIPE, oldsighandler); diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index d22d403e016..2b3db3fe7fd 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -11,7 +11,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-int.h,v 1.11 1999/08/31 01:37:37 tgl Exp $ + * $Id: libpq-int.h,v 1.12 1999/09/27 03:13:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,11 @@ #include "pqexpbuffer.h" +#ifdef USE_SSL +#include "openssl/ssl.h" +#include "openssl/err.h" +#endif + /* libpq supports this version of the frontend/backend protocol. * * NB: we used to use PG_PROTOCOL_LATEST from the backend pqcomm.h file, @@ -215,6 +220,10 @@ struct pg_conn PGresult *result; /* result being constructed */ PGresAttValue *curTuple; /* tuple currently being read */ +#ifdef USE_SSL + SSL *ssl; +#endif + /* Buffer for current error message */ PQExpBufferData errorMessage; /* expansible string */ |
