
--- 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))
