--- postgresql-7.2.1.orig/src/include/libpq/libpq-be.h Sun Nov 11 22:43:25 2001 +++ postgresql-7.2.1/src/include/libpq/libpq-be.h Sun May 19 18:14:13 2002 @@ -70,6 +70,7 @@ */ #ifdef USE_SSL SSL *ssl; + X509 *peer; #endif } Port; --- postgresql-7.2.1.orig/src/interfaces/libpq/libpq-int.h Mon Nov 5 10:46:38 2001 +++ postgresql-7.2.1/src/interfaces/libpq/libpq-int.h Sun May 19 20:56:25 2002 @@ -270,6 +270,7 @@ bool allow_ssl_try; /* Allowed to try SSL negotiation */ bool require_ssl; /* Require SSL to make connection */ SSL *ssl; /* SSL status, if have SSL connection */ + X509 *peer; /* server certificate */ #endif /* Buffer for current error message */ --- postgresql-7.2.1.orig/src/backend/libpq/pqcomm.c Tue Dec 4 13:57:22 2001 +++ postgresql-7.2.1/src/backend/libpq/pqcomm.c Sun May 19 22:25:27 2002 @@ -80,6 +80,14 @@ #include "libpq/libpq.h" #include "miscadmin.h" +/* these functions are misnamed - they handle both SSL and non-SSL case */ +extern ssize_t read_SSL(Port *, void *ptr, size_t len); +extern ssize_t write_SSL(Port *, const void *ptr, size_t len); + +#ifdef USE_SSL +extern void close_SSL(Port *); +#endif /* USE_SSL */ + static void pq_close(void); @@ -137,6 +145,9 @@ { if (MyProcPort != NULL) { +#ifdef USE_SSL + close_SSL(MyProcPort); +#endif /* USE_SSL */ close(MyProcPort->sock); /* make sure any subsequent attempts to do I/O fail cleanly */ MyProcPort->sock = -1; @@ -448,6 +459,7 @@ void StreamClose(int sock) { + /* FIXME - what about closing SSL connections? */ close(sock); } @@ -489,14 +501,8 @@ { int r; -#ifdef USE_SSL - if (MyProcPort->ssl) - r = SSL_read(MyProcPort->ssl, PqRecvBuffer + PqRecvLength, - PQ_BUFFER_SIZE - PqRecvLength); - else -#endif - r = recv(MyProcPort->sock, PqRecvBuffer + PqRecvLength, - PQ_BUFFER_SIZE - PqRecvLength, 0); + r = read_SSL(MyProcPort, PqRecvBuffer + PqRecvLength, + PQ_BUFFER_SIZE - PqRecvLength); if (r < 0) { @@ -512,7 +518,11 @@ elog(DEBUG, "pq_recvbuf: recv() failed: %m"); return EOF; } +#ifdef USE_SSL + if (r == 0 && !MyProcPort->ssl) +#else /* USE_SSL */ if (r == 0) +#endif /* USE_SSL */ { /* as above, only write to postmaster log */ elog(DEBUG, "pq_recvbuf: unexpected EOF on client connection"); @@ -664,14 +674,13 @@ { int r; -#ifdef USE_SSL - if (MyProcPort->ssl) - r = SSL_write(MyProcPort->ssl, bufptr, bufend - bufptr); - else -#endif - r = send(MyProcPort->sock, bufptr, bufend - bufptr, 0); + r = write_SSL(MyProcPort, bufptr, bufend - bufptr); +#ifdef USE_SSL + if (r < 0 || (r == 0 && !MyProcPort->ssl)) +#else /* USE_SSL */ if (r <= 0) +#endif /* USE_SSL */ { if (errno == EINTR) continue; /* Ok if we were interrupted */ @@ -716,8 +725,9 @@ pq_eof(void) { char x; - int res; + int res = 1; +#ifndef USE_SSL /* not a good solution, but better than nothing */ res = recv(MyProcPort->sock, &x, 1, MSG_PEEK); if (res < 0) @@ -726,6 +736,8 @@ elog(DEBUG, "pq_eof: recv() failed: %m"); return EOF; } +#endif /* USE_SSL */ + if (res == 0) return EOF; else --- postgresql-7.2.1.orig/src/backend/postmaster/postmaster.c Fri Mar 15 12:20:47 2002 +++ postgresql-7.2.1/src/backend/postmaster/postmaster.c Mon May 20 00:25:36 2002 @@ -165,10 +165,6 @@ static int ServerSock_UNIX = INVALID_SOCK; /* stream socket server */ #endif -#ifdef USE_SSL -static SSL_CTX *SSL_context = NULL; /* Global SSL context */ -#endif - /* * Set by the -o option */ @@ -271,8 +267,10 @@ #define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN) #ifdef USE_SSL -static void InitSSL(void); -static const char *SSLerrmessage(void); +extern int initialize_ctx(const char *, void (*err)(const char *fmt,...)); +extern void destroy_ctx(void); +extern int open_SSL_server(Port *); +extern void close_SSL(Port *); #endif @@ -642,7 +640,10 @@ ExitPostmaster(1); } if (EnableSSL) - InitSSL(); + { + if (initialize_ctx(NULL, postmaster_error) == -1) + ExitPostmaster(1); + } #endif /* @@ -1116,12 +1117,8 @@ #ifdef USE_SSL if (SSLok == 'S') { - if (!(port->ssl = SSL_new(SSL_context)) || - !SSL_set_fd(port->ssl, port->sock) || - SSL_accept(port->ssl) <= 0) + if (open_SSL_server(port) != STATUS_OK) { - elog(DEBUG, "failed to initialize SSL connection: %s (%m)", - SSLerrmessage()); return STATUS_ERROR; } } @@ -1329,9 +1326,10 @@ ConnFree(Port *conn) { #ifdef USE_SSL - if (conn->ssl) - SSL_free(conn->ssl); + close_SSL(conn); #endif + if (conn->sock != -1) + close(conn->sock); free(conn); } @@ -2426,72 +2424,6 @@ return cnt; } -#ifdef USE_SSL - -/* - * Initialize SSL library and structures - */ -static void -InitSSL(void) -{ - char fnbuf[2048]; - - SSL_load_error_strings(); - SSL_library_init(); - SSL_context = SSL_CTX_new(SSLv23_method()); - if (!SSL_context) - { - postmaster_error("failed to create SSL context: %s", - SSLerrmessage()); - ExitPostmaster(1); - } - snprintf(fnbuf, sizeof(fnbuf), "%s/server.crt", DataDir); - if (!SSL_CTX_use_certificate_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) - { - postmaster_error("failed to load server certificate (%s): %s", - fnbuf, SSLerrmessage()); - ExitPostmaster(1); - } - snprintf(fnbuf, sizeof(fnbuf), "%s/server.key", DataDir); - if (!SSL_CTX_use_PrivateKey_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) - { - postmaster_error("failed to load private key file (%s): %s", - fnbuf, SSLerrmessage()); - ExitPostmaster(1); - } - if (!SSL_CTX_check_private_key(SSL_context)) - { - postmaster_error("check of private key failed: %s", - SSLerrmessage()); - ExitPostmaster(1); - } -} - -/* - * Obtain reason string for last SSL error - * - * Some caution is needed here since ERR_reason_error_string will - * return NULL if it doesn't recognize the error code. We don't - * want to return NULL ever. - */ -static const char * -SSLerrmessage(void) -{ - unsigned long errcode; - const char *errreason; - static char errbuf[32]; - - errcode = ERR_get_error(); - if (errcode == 0) - return "No SSL error reported"; - errreason = ERR_reason_error_string(errcode); - if (errreason != NULL) - return errreason; - snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode); - return errbuf; -} - -#endif /* USE_SSL */ /* * Fire off a subprocess for startup/shutdown/checkpoint. --- postgresql-7.2.1.orig/src/bin/psql/startup.c Mon Nov 5 10:46:31 2001 +++ postgresql-7.2.1/src/bin/psql/startup.c Sun May 19 23:23:11 2002 @@ -686,14 +686,33 @@ { int sslbits = -1; SSL *ssl; + X509 *peer; + char sn[256]; + long l; ssl = PQgetssl(pset.db); if (!ssl) return; /* no SSL */ +/* peer = pset.db.peer; */ + if ((peer = SSL_get_peer_certificate(ssl)) != NULL) + { + X509_NAME_oneline(X509_get_subject_name(peer), sn, sizeof sn); + } + else + { + strncpy(sn, "(anonymous)", sizeof sn); + } + printf(gettext("SSL connection\n")); + printf(gettext("(host: %s)\n"), sn); + SSL_get_cipher_bits(ssl, &sslbits); - printf(gettext("SSL connection (cipher: %s, bits: %i)\n\n"), + printf(gettext("(protocol: %s)\n"), SSL_get_version(ssl)), + printf(gettext("(cipher: %s, bits: %i)\n"), SSL_get_cipher(ssl), sslbits); + l = SSL_get_default_timeout(ssl); + printf(gettext("(timeout: %ld:%02ld:%02ld)\n\n"), + l / 3600L, (l / 60L) % 60L, l % 60L); } #endif --- postgresql-7.2.1.orig/src/interfaces/libpq/fe-connect.c Sat Nov 10 19:09:05 2001 +++ postgresql-7.2.1/src/interfaces/libpq/fe-connect.c Mon May 20 00:24:28 2002 @@ -62,10 +62,6 @@ #endif -#ifdef USE_SSL -static SSL_CTX *SSL_context = NULL; -#endif - #define NOTIFYLIST_INITIAL_SIZE 10 #define NOTIFYLIST_GROWBY 10 @@ -186,8 +182,13 @@ static void defaultNoticeProcessor(void *arg, const char *message); static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage); + #ifdef USE_SSL -static const char *SSLerrmessage(void); +extern int initialize_ctx(const char *passwd, void (*err)(const char *fmt,...), PGconn *); +extern void destroy_ctx(PGconn *); +extern int open_SSL_client(PGconn *); +extern void close_SSL(PGconn *); +extern SSL *PQgetssl(PGconn *); #endif @@ -955,28 +956,10 @@ } if (SSLok == 'S') { - if (!SSL_context) - { - SSL_load_error_strings(); - SSL_library_init(); - SSL_context = SSL_CTX_new(SSLv23_method()); - if (!SSL_context) - { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not create SSL context: %s\n"), - SSLerrmessage()); - goto connect_errReturn; - } - } - if (!(conn->ssl = SSL_new(SSL_context)) || - !SSL_set_fd(conn->ssl, conn->sock) || - SSL_connect(conn->ssl) <= 0) - { - printfPQExpBuffer(&conn->errorMessage, - libpq_gettext("could not establish SSL connection: %s\n"), - SSLerrmessage()); + if (initialize_ctx(NULL, NULL, conn) == -1) + goto connect_errReturn; + if (open_SSL_client(conn) == -1) goto connect_errReturn; - } /* SSL connection finished. Continue to send startup packet */ } else if (SSLok == 'E') @@ -1001,7 +984,7 @@ goto connect_errReturn; } } - if (conn->require_ssl && !conn->ssl) + if (conn->require_ssl && !PQgetssl(conn)) { /* Require SSL, but server does not support/want it */ printfPQExpBuffer(&conn->errorMessage, @@ -1900,8 +1883,7 @@ return; pqClearAsyncResult(conn); /* deallocate result and curTuple */ #ifdef USE_SSL - if (conn->ssl) - SSL_free(conn->ssl); + close_SSL(conn); #endif if (conn->sock >= 0) { @@ -2619,35 +2601,6 @@ } -#ifdef USE_SSL - -/* - * Obtain reason string for last SSL error - * - * Some caution is needed here since ERR_reason_error_string will - * return NULL if it doesn't recognize the error code. We don't - * want to return NULL ever. - */ -static const char * -SSLerrmessage(void) -{ - unsigned long errcode; - const char *errreason; - static char errbuf[32]; - - errcode = ERR_get_error(); - if (errcode == 0) - return "No SSL error reported"; - errreason = ERR_reason_error_string(errcode); - if (errreason != NULL) - return errreason; - snprintf(errbuf, sizeof(errbuf), "SSL error code %lu", errcode); - return errbuf; -} - -#endif /* USE_SSL */ - - /* =========== accessor functions for PGconn ========= */ char * PQdb(const PGconn *conn) @@ -2789,16 +2742,6 @@ PQsetClientEncoding(PGconn *conn, const char *encoding) { return -1; -} -#endif - -#ifdef USE_SSL -SSL * -PQgetssl(PGconn *conn) -{ - if (!conn) - return NULL; - return conn->ssl; } #endif --- postgresql-7.2.1.orig/src/interfaces/libpq/fe-misc.c Sun Dec 2 17:28:24 2001 +++ postgresql-7.2.1/src/interfaces/libpq/fe-misc.c Sun May 19 21:06:10 2002 @@ -57,6 +57,13 @@ #include "mb/pg_wchar.h" #endif +/* these functions are misnamed - they handle both SSL and non-SSL case */ +extern ssize_t read_SSL (PGconn *, void *ptr, size_t); +extern ssize_t write_SSL (PGconn *, const void *ptr, size_t); + +#ifdef USE_SSL +extern ssize_t close_SSL (PGconn *); +#endif #define DONOTICE(conn,message) \ ((*(conn)->noticeHook) ((conn)->noticeArg, (message))) @@ -459,14 +466,8 @@ /* OK, try to read some data */ tryAgain: -#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); + nread = read_SSL(conn, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); if (nread < 0) { if (SOCK_ERRNO == EINTR) @@ -545,14 +546,8 @@ * arrived. */ tryAgain2: -#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); + nread = read_SSL(conn, conn->inBuffer + conn->inEnd, + conn->inBufSize - conn->inEnd); if (nread < 0) { if (SOCK_ERRNO == EINTR) @@ -593,6 +588,9 @@ "\tThis probably means the server terminated abnormally\n" "\tbefore or while processing the request.\n")); conn->status = CONNECTION_BAD; /* No more connection to backend */ +#ifdef USE_SSL + close_SSL(conn); +#endif #ifdef WIN32 closesocket(conn->sock); #else @@ -629,23 +627,9 @@ /* while there's still data to send */ while (len > 0) { - /* Prevent being SIGPIPEd if backend has closed the connection. */ -#ifndef WIN32 - pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN); -#endif - 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); -#endif + sent = write_SSL(conn, ptr, len); if (sent < 0) { @@ -711,7 +695,7 @@ */ #ifdef USE_SSL /* can't do anything for our SSL users yet */ - if (conn->ssl == NULL) + if (PQgetssl(conn) == NULL) { #endif if (pqIsnonblocking(conn))