diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 54db2b7b8962b61c3512d8e04c9230b633d33d2f..3a1465457e08f2e3c7c326a1ed7f0f8d3ddf8bc4 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.392 2010/04/30 17:09:13 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.393 2010/05/26 21:39:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1623,7 +1623,7 @@ keep_going:						/* We will come back to here until there is
 					if (SSLok == 'S')
 					{
 						/* Set up global SSL state if required */
-						if (pqsecure_initialize(conn) == -1)
+						if (pqsecure_initialize(conn) != 0)
 							goto error_return;
 					}
 					else if (SSLok == 'N')
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 23ac0f3893b854bd79a2fea70e78a5d9269fb03c..a8acf4e5cb176743abed7126798f3edf693e8293 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,13 +11,13 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.133 2010/05/25 22:03:27 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.134 2010/05/26 21:39:27 tgl Exp $
  *
  * NOTES
  *
  *	  We don't provide informational callbacks here (like
- *	  info_cb() in be-secure.c), since there's mechanism to
- *	  display that information to the client.
+ *	  info_cb() in be-secure.c), since there's no good mechanism to
+ *	  display such information to the user.
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,6 @@
 #ifdef USE_SSL
 
 #include <openssl/ssl.h>
-#include <openssl/bio.h>
 #if (SSLEAY_VERSION_NUMBER >= 0x00907000L)
 #include <openssl/conf.h>
 #endif
@@ -81,18 +80,11 @@
 #define ROOT_CRL_FILE		"root.crl"
 #endif
 
-#ifndef HAVE_ERR_SET_MARK
-/* These don't exist in OpenSSL before 0.9.8 */
-#define ERR_set_mark()		((void) 0)
-#define ERR_pop_to_mark()	((void) 0)
-#endif
-
 static bool verify_peer_name_matches_certificate(PGconn *);
 static int	verify_cb(int ok, X509_STORE_CTX *ctx);
-static int	client_cert_cb(SSL *, X509 **, EVP_PKEY **);
 static int	init_ssl_system(PGconn *conn);
 static void destroy_ssl_system(void);
-static int	initialize_SSL(PGconn *);
+static int	initialize_SSL(PGconn *conn);
 static void destroySSL(void);
 static PostgresPollingStatusType open_client_SSL(PGconn *);
 static void close_SSL(PGconn *);
@@ -224,7 +216,7 @@ PQinitOpenSSL(int do_ssl, int do_crypto)
 }
 
 /*
- *	Initialize global context
+ *	Initialize global SSL context
  */
 int
 pqsecure_initialize(PGconn *conn)
@@ -232,7 +224,7 @@ pqsecure_initialize(PGconn *conn)
 	int			r = 0;
 
 #ifdef USE_SSL
-	r = initialize_SSL(conn);
+	r = init_ssl_system(conn);
 #endif
 
 	return r;
@@ -250,7 +242,7 @@ pqsecure_destroy(void)
 }
 
 /*
- *	Attempt to negotiate secure session.
+ *	Begin or continue negotiating a secure session.
  */
 PostgresPollingStatusType
 pqsecure_open_client(PGconn *conn)
@@ -262,6 +254,7 @@ pqsecure_open_client(PGconn *conn)
 		/* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
 		conn->sigpipe_flag = false;
 
+		/* Create a connection-specific SSL object */
 		if (!(conn->ssl = SSL_new(SSL_context)) ||
 			!SSL_set_app_data(conn->ssl, conn) ||
 			!SSL_set_fd(conn->ssl, conn->sock))
@@ -277,11 +270,16 @@ pqsecure_open_client(PGconn *conn)
 		}
 
 		/*
-		 * Initialize errorMessage to empty.  This allows open_client_SSL() to
-		 * detect whether client_cert_cb() has stored a message.
+		 * Load client certificate, private key, and trusted CA certs.
 		 */
-		resetPQExpBuffer(&conn->errorMessage);
+		if (initialize_SSL(conn) != 0)
+		{
+			/* initialize_SSL already put a message in conn->errorMessage */
+			close_SSL(conn);
+			return PGRES_POLLING_FAILED;
+		}
 	}
+
 	/* Begin or continue the actual handshake */
 	return open_client_SSL(conn);
 #else
@@ -545,7 +543,7 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
  * This is roughly in line with RFC2818, but contrary to what most browsers
  * appear to be implementing (point 3 being the difference)
  *
- * Matching is always cone case-insensitive, since DNS is case insensitive.
+ * Matching is always case-insensitive, since DNS is case insensitive.
  */
 static int
 wildcard_certificate_match(const char *pattern, const char *string)
@@ -606,7 +604,7 @@ verify_peer_name_matches_certificate(PGconn *conn)
 	else
 	{
 		/*
-		 * Connect by hostname.
+		 * Compare CN to originally given hostname.
 		 *
 		 * XXX: Should support alternate names here
 		 */
@@ -626,264 +624,6 @@ verify_peer_name_matches_certificate(PGconn *conn)
 	}
 }
 
-/*
- *	Callback used by SSL to load client cert and key.
- *	This callback is only called when the server wants a
- *	client cert.
- *
- *	Since BIO functions can set OpenSSL error codes, we must
- *	reset the OpenSSL error stack on *every* exit from this
- *	function once we've started using BIO.
- *
- *	Must return 1 on success, 0 on no data or error.
- */
-static int
-client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
-{
-	char		homedir[MAXPGPATH];
-	struct stat buf;
-
-#ifndef WIN32
-	struct stat buf2;
-	FILE	   *fp;
-#endif
-	char		fnbuf[MAXPGPATH];
-	BIO		   *bio;
-	PGconn	   *conn = (PGconn *) SSL_get_app_data(ssl);
-	char		sebuf[256];
-
-	/*
-	 * If conn->sslcert  or conn->sslkey is not set, we don't need the home
-	 * directory to find the required files.
-	 */
-	if (!conn->sslcert || !conn->sslkey)
-	{
-		if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-							  libpq_gettext("could not get home directory to locate client certificate files\n"));
-			return 0;
-		}
-	}
-
-	/* read the user certificate */
-	if (conn->sslcert)
-		strncpy(fnbuf, conn->sslcert, sizeof(fnbuf));
-	else
-		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
-
-	/*
-	 * OpenSSL <= 0.9.8 lacks error stack handling, which means it's likely to
-	 * report wrong error messages if access to the cert file fails. Do our
-	 * own check for the readability of the file to catch the majority of such
-	 * problems before OpenSSL gets involved.
-	 */
-#ifndef HAVE_ERR_SET_MARK
-	{
-		FILE	   *fp2;
-
-		if ((fp2 = fopen(fnbuf, "r")) == NULL)
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-			   libpq_gettext("could not open certificate file \"%s\": %s\n"),
-							  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
-			return 0;
-		}
-		fclose(fp2);
-	}
-#endif
-
-	/* save OpenSSL error stack */
-	ERR_set_mark();
-
-	if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
-	{
-		printfPQExpBuffer(&conn->errorMessage,
-			   libpq_gettext("could not open certificate file \"%s\": %s\n"),
-						  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
-		ERR_pop_to_mark();
-		return 0;
-	}
-
-	if (PEM_read_bio_X509(bio, x509, NULL, NULL) == NULL)
-	{
-		char	   *err = SSLerrmessage();
-
-		printfPQExpBuffer(&conn->errorMessage,
-			   libpq_gettext("could not read certificate file \"%s\": %s\n"),
-						  fnbuf, err);
-		SSLerrfree(err);
-		BIO_free(bio);
-		ERR_pop_to_mark();
-		return 0;
-	}
-
-	BIO_free(bio);
-
-	/*
-	 * Read the SSL key. If a key is specified, treat it as an engine:key
-	 * combination if there is colon present - we don't support files with
-	 * colon in the name. The exception is if the second character is a colon,
-	 * in which case it can be a Windows filename with drive specification.
-	 */
-	if (conn->sslkey && strlen(conn->sslkey) > 0)
-	{
-#ifdef USE_SSL_ENGINE
-		if (strchr(conn->sslkey, ':')
-#ifdef WIN32
-			&& conn->sslkey[1] != ':'
-#endif
-			)
-		{
-			/* Colon, but not in second character, treat as engine:key */
-			char	   *engine_str = strdup(conn->sslkey);
-			char	   *engine_colon = strchr(engine_str, ':');
-
-			*engine_colon = '\0';		/* engine_str now has engine name */
-			engine_colon++;		/* engine_colon now has key name */
-
-			conn->engine = ENGINE_by_id(engine_str);
-			if (conn->engine == NULL)
-			{
-				char	   *err = SSLerrmessage();
-
-				printfPQExpBuffer(&conn->errorMessage,
-					 libpq_gettext("could not load SSL engine \"%s\": %s\n"),
-								  engine_str, err);
-				SSLerrfree(err);
-				free(engine_str);
-				ERR_pop_to_mark();
-				return 0;
-			}
-
-			if (ENGINE_init(conn->engine) == 0)
-			{
-				char	   *err = SSLerrmessage();
-
-				printfPQExpBuffer(&conn->errorMessage,
-				libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
-								  engine_str, err);
-				SSLerrfree(err);
-				ENGINE_free(conn->engine);
-				conn->engine = NULL;
-				free(engine_str);
-				ERR_pop_to_mark();
-				return 0;
-			}
-
-			*pkey = ENGINE_load_private_key(conn->engine, engine_colon,
-											NULL, NULL);
-			if (*pkey == NULL)
-			{
-				char	   *err = SSLerrmessage();
-
-				printfPQExpBuffer(&conn->errorMessage,
-								  libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
-								  engine_colon, engine_str, err);
-				SSLerrfree(err);
-				ENGINE_finish(conn->engine);
-				ENGINE_free(conn->engine);
-				conn->engine = NULL;
-				free(engine_str);
-				ERR_pop_to_mark();
-				return 0;
-			}
-			free(engine_str);
-
-			fnbuf[0] = '\0';	/* indicate we're not going to load from a
-								 * file */
-		}
-		else
-#endif   /* support for SSL engines */
-		{
-			/* PGSSLKEY is not an engine, treat it as a filename */
-			strncpy(fnbuf, conn->sslkey, sizeof(fnbuf));
-		}
-	}
-	else
-	{
-		/* No PGSSLKEY specified, load default file */
-		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
-	}
-
-	if (fnbuf[0] != '\0')
-	{
-		/* read the user key from file */
-
-		if (stat(fnbuf, &buf) != 0)
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-							  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
-							  fnbuf);
-			ERR_pop_to_mark();
-			return 0;
-		}
-#ifndef WIN32
-		if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-							  libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
-							  fnbuf);
-			ERR_pop_to_mark();
-			return 0;
-		}
-#endif
-
-		if ((bio = BIO_new_file(fnbuf, "r")) == NULL)
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-			   libpq_gettext("could not open private key file \"%s\": %s\n"),
-							  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
-			ERR_pop_to_mark();
-			return 0;
-		}
-#ifndef WIN32
-		BIO_get_fp(bio, &fp);
-		if (fstat(fileno(fp), &buf2) == -1 ||
-			buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino)
-		{
-			printfPQExpBuffer(&conn->errorMessage,
-							  libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf);
-			ERR_pop_to_mark();
-			return 0;
-		}
-#endif
-
-		if (PEM_read_bio_PrivateKey(bio, pkey, NULL, NULL) == NULL)
-		{
-			char	   *err = SSLerrmessage();
-
-			printfPQExpBuffer(&conn->errorMessage,
-			   libpq_gettext("could not read private key file \"%s\": %s\n"),
-							  fnbuf, err);
-			SSLerrfree(err);
-
-			BIO_free(bio);
-			ERR_pop_to_mark();
-			return 0;
-		}
-
-		BIO_free(bio);
-	}
-
-	/* verify that the cert and key go together */
-	if (X509_check_private_key(*x509, *pkey) != 1)
-	{
-		char	   *err = SSLerrmessage();
-
-		printfPQExpBuffer(&conn->errorMessage,
-						  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
-						  fnbuf, err);
-		SSLerrfree(err);
-		ERR_pop_to_mark();
-		return 0;
-	}
-
-	ERR_pop_to_mark();
-
-	return 1;
-}
-
 #ifdef ENABLE_THREAD_SAFETY
 /*
  *	Callback functions for OpenSSL internal locking
@@ -919,15 +659,20 @@ pq_lockingcallback(int mode, int n, const char *file, int line)
 #endif   /* ENABLE_THREAD_SAFETY */
 
 /*
- * Initialize SSL system. In threadsafe mode, this includes setting
- * up libcrypto callback functions to do thread locking.
+ * Initialize SSL system, in particular creating the SSL_context object
+ * that will be shared by all SSL-using connections in this process.
+ *
+ * In threadsafe mode, this includes setting up libcrypto callback functions
+ * to do thread locking.
  *
  * If the caller has told us (through PQinitOpenSSL) that he's taking care
  * of libcrypto, we expect that callbacks are already set, and won't try to
  * override it.
  *
  * The conn parameter is only used to be able to pass back an error
- * message - no connection local setup is made.
+ * message - no connection-local setup is made here.
+ *
+ * Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
  */
 static int
 init_ssl_system(PGconn *conn)
@@ -997,6 +742,7 @@ init_ssl_system(PGconn *conn)
 			SSL_library_init();
 			SSL_load_error_strings();
 		}
+
 		SSL_context = SSL_CTX_new(TLSv1_method());
 		if (!SSL_context)
 		{
@@ -1058,11 +804,19 @@ destroy_ssl_system(void)
 
 	pthread_mutex_unlock(&ssl_config_mutex);
 #endif
-	return;
 }
 
 /*
- *	Initialize SSL context.
+ *	Initialize (potentially) per-connection SSL data, namely the
+ *	client certificate, private key, and trusted CA certs.
+ *
+ *	conn->ssl must already be created.  It receives the connection's client
+ *	certificate and private key.  Note however that certificates also get
+ *	loaded into the SSL_context object, and are therefore accessible to all
+ *	connections in this process.  This should be OK as long as there aren't
+ *	any hash collisions among the certs.
+ *
+ *	Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
  */
 static int
 initialize_SSL(PGconn *conn)
@@ -1070,38 +824,240 @@ initialize_SSL(PGconn *conn)
 	struct stat buf;
 	char		homedir[MAXPGPATH];
 	char		fnbuf[MAXPGPATH];
-
-	if (init_ssl_system(conn))
-		return -1;
+	char		sebuf[256];
+	bool		have_cert;
+	EVP_PKEY   *pkey = NULL;
 
 	/*
-	 * If sslmode is set to one of the verify options, perform certificate
-	 * verification. If set to "verify-full" we will also do further
-	 * verification after the connection has been completed.
-	 *
-	 * If we are going to look for either root certificate or CRL in the home
-	 * directory, we need pqGetHomeDirectory() to succeed. In other cases, we
-	 * don't need to get the home directory explicitly.
+	 * We'll need the home directory if any of the relevant parameters are
+	 * defaulted.
 	 */
-	if (!conn->sslrootcert || !conn->sslcrl)
+	if (!(conn->sslcert && strlen(conn->sslcert) > 0) ||
+		!(conn->sslkey && strlen(conn->sslkey) > 0) ||
+		!(conn->sslrootcert && strlen(conn->sslrootcert) > 0) ||
+		!(conn->sslcrl && strlen(conn->sslcrl) > 0))
 	{
 		if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
 		{
-			if (conn->sslmode[0] == 'v')		/* "verify-ca" or
-												 * "verify-full" */
+			printfPQExpBuffer(&conn->errorMessage,
+							  libpq_gettext("could not get home directory to locate client certificate files\n"));
+			return -1;
+		}
+	}
+	else
+	{
+		homedir[0] = '\0';
+	}
+
+	/* Read the client certificate file */
+	if (conn->sslcert && strlen(conn->sslcert) > 0)
+		strncpy(fnbuf, conn->sslcert, sizeof(fnbuf));
+	else
+		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE);
+
+	if (stat(fnbuf, &buf) != 0)
+	{
+		/*
+		 * If file is not present, just go on without a client cert; server
+		 * might or might not accept the connection.  Any other error, however,
+		 * is grounds for complaint.
+		 */
+		if (errno != ENOENT)
+		{
+			printfPQExpBuffer(&conn->errorMessage,
+			   libpq_gettext("could not open certificate file \"%s\": %s\n"),
+							  fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
+			return -1;
+		}
+		have_cert = false;
+	}
+	else
+	{
+		/*
+		 * Cert file exists, so load it.  Since OpenSSL doesn't provide the
+		 * equivalent of "SSL_use_certificate_chain_file", we actually have
+		 * to load the file twice.  The first call loads any extra certs
+		 * after the first one into chain-cert storage associated with the
+		 * SSL_context.  The second call loads the first cert (only) into
+		 * the SSL object, where it will be correctly paired with the private
+		 * key we load below.  We do it this way so that each connection
+		 * understands which subject cert to present, in case different sslcert
+		 * settings are used for different connections in the same process.
+		 */
+		if (SSL_CTX_use_certificate_chain_file(SSL_context, fnbuf) != 1)
+		{
+			char	   *err = SSLerrmessage();
+
+			printfPQExpBuffer(&conn->errorMessage,
+			   libpq_gettext("could not read certificate file \"%s\": %s\n"),
+							  fnbuf, err);
+			SSLerrfree(err);
+			return -1;
+		}
+		if (SSL_use_certificate_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
+		{
+			char	   *err = SSLerrmessage();
+
+			printfPQExpBuffer(&conn->errorMessage,
+			   libpq_gettext("could not read certificate file \"%s\": %s\n"),
+							  fnbuf, err);
+			SSLerrfree(err);
+			return -1;
+		}
+		/* need to load the associated private key, too */
+		have_cert = true;
+	}
+
+	/*
+	 * Read the SSL key. If a key is specified, treat it as an engine:key
+	 * combination if there is colon present - we don't support files with
+	 * colon in the name. The exception is if the second character is a colon,
+	 * in which case it can be a Windows filename with drive specification.
+	 */
+	if (have_cert && conn->sslkey && strlen(conn->sslkey) > 0)
+	{
+#ifdef USE_SSL_ENGINE
+		if (strchr(conn->sslkey, ':')
+#ifdef WIN32
+			&& conn->sslkey[1] != ':'
+#endif
+			)
+		{
+			/* Colon, but not in second character, treat as engine:key */
+			char	   *engine_str = strdup(conn->sslkey);
+			char	   *engine_colon = strchr(engine_str, ':');
+
+			*engine_colon = '\0';		/* engine_str now has engine name */
+			engine_colon++;		/* engine_colon now has key name */
+
+			conn->engine = ENGINE_by_id(engine_str);
+			if (conn->engine == NULL)
+			{
+				char	   *err = SSLerrmessage();
+
+				printfPQExpBuffer(&conn->errorMessage,
+					 libpq_gettext("could not load SSL engine \"%s\": %s\n"),
+								  engine_str, err);
+				SSLerrfree(err);
+				free(engine_str);
+				return -1;
+			}
+
+			if (ENGINE_init(conn->engine) == 0)
 			{
+				char	   *err = SSLerrmessage();
+
 				printfPQExpBuffer(&conn->errorMessage,
-								  libpq_gettext("could not get home directory to locate root certificate file\n"));
+				libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
+								  engine_str, err);
+				SSLerrfree(err);
+				ENGINE_free(conn->engine);
+				conn->engine = NULL;
+				free(engine_str);
 				return -1;
 			}
+
+			pkey = ENGINE_load_private_key(conn->engine, engine_colon,
+										   NULL, NULL);
+			if (pkey == NULL)
+			{
+				char	   *err = SSLerrmessage();
+
+				printfPQExpBuffer(&conn->errorMessage,
+								  libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
+								  engine_colon, engine_str, err);
+				SSLerrfree(err);
+				ENGINE_finish(conn->engine);
+				ENGINE_free(conn->engine);
+				conn->engine = NULL;
+				free(engine_str);
+				return -1;
+			}
+			if (SSL_use_PrivateKey(conn->ssl, pkey) != 1)
+			{
+				char	   *err = SSLerrmessage();
+
+				printfPQExpBuffer(&conn->errorMessage,
+								  libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
+								  engine_colon, engine_str, err);
+				SSLerrfree(err);
+				ENGINE_finish(conn->engine);
+				ENGINE_free(conn->engine);
+				conn->engine = NULL;
+				free(engine_str);
+				return -1;
+			}
+
+			free(engine_str);
+
+			fnbuf[0] = '\0';	/* indicate we're not going to load from a
+								 * file */
+		}
+		else
+#endif /* USE_SSL_ENGINE */
+		{
+			/* PGSSLKEY is not an engine, treat it as a filename */
+			strncpy(fnbuf, conn->sslkey, sizeof(fnbuf));
 		}
 	}
 	else
 	{
-		homedir[0] = '\0';
+		/* No PGSSLKEY specified, load default file */
+		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE);
 	}
 
-	if (conn->sslrootcert)
+	if (have_cert && fnbuf[0] != '\0')
+	{
+		/* read the client key from file */
+
+		if (stat(fnbuf, &buf) != 0)
+		{
+			printfPQExpBuffer(&conn->errorMessage,
+							  libpq_gettext("certificate present, but not private key file \"%s\"\n"),
+							  fnbuf);
+			return -1;
+		}
+#ifndef WIN32
+		if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
+		{
+			printfPQExpBuffer(&conn->errorMessage,
+							  libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
+							  fnbuf);
+			return -1;
+		}
+#endif
+
+		if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_PEM) != 1)
+		{
+			char	   *err = SSLerrmessage();
+
+			printfPQExpBuffer(&conn->errorMessage,
+			   libpq_gettext("could not load private key file \"%s\": %s\n"),
+							  fnbuf, err);
+			SSLerrfree(err);
+			return -1;
+		}
+	}
+
+	/* verify that the cert and key go together */
+	if (have_cert &&
+		SSL_check_private_key(conn->ssl) != 1)
+	{
+		char	   *err = SSLerrmessage();
+
+		printfPQExpBuffer(&conn->errorMessage,
+						  libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
+						  fnbuf, err);
+		SSLerrfree(err);
+		return -1;
+	}
+
+	/*
+	 * If the root cert file exists, load it so we can perform certificate
+	 * verification. If sslmode is "verify-full" we will also do further
+	 * verification after the connection has been completed.
+	 */
+	if (conn->sslrootcert && strlen(conn->sslrootcert) > 0)
 		strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf));
 	else
 		snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE);
@@ -1123,20 +1079,19 @@ initialize_SSL(PGconn *conn)
 
 		if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL)
 		{
-			if (conn->sslcrl)
+			if (conn->sslcrl && strlen(conn->sslcrl) > 0)
 				strncpy(fnbuf, conn->sslcrl, sizeof(fnbuf));
 			else
 				snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE);
 
-			/* setting the flags to check against the complete CRL chain */
+			/* Set the flags to check against the complete CRL chain */
 			if (X509_STORE_load_locations(cvstore, fnbuf, NULL) == 1)
-/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
+			{
+				/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
 #ifdef X509_V_FLAG_CRL_CHECK
 				X509_STORE_set_flags(cvstore,
 						  X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
-			/* if not found, silently ignore;  we do not require CRL */
 #else
-			{
 				char	   *err = SSLerrmessage();
 
 				printfPQExpBuffer(&conn->errorMessage,
@@ -1144,15 +1099,20 @@ initialize_SSL(PGconn *conn)
 								  fnbuf);
 				SSLerrfree(err);
 				return -1;
-			}
 #endif
+			}
+			/* if not found, silently ignore;  we do not require CRL */
 		}
 
-		SSL_CTX_set_verify(SSL_context, SSL_VERIFY_PEER, verify_cb);
+		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, verify_cb);
 	}
 	else
 	{
-		/* stat() failed; assume cert file doesn't exist */
+		/*
+		 * stat() failed; assume root file doesn't exist.  If sslmode is
+		 * verify-ca or verify-full, this is an error.  Otherwise, continue
+		 * without performing any server cert verification.
+		 */
 		if (conn->sslmode[0] == 'v')	/* "verify-ca" or "verify-full" */
 		{
 			printfPQExpBuffer(&conn->errorMessage,
@@ -1162,9 +1122,6 @@ initialize_SSL(PGconn *conn)
 		}
 	}
 
-	/* set up mechanism to provide client certificate, if available */
-	SSL_CTX_set_client_cert_cb(SSL_context, client_cert_cb);
-
 	return 0;
 }
 
@@ -1211,23 +1168,12 @@ open_client_SSL(PGconn *conn)
 				}
 			case SSL_ERROR_SSL:
 				{
-					/*
-					 * If there are problems with the local certificate files,
-					 * these will be detected by client_cert_cb() which is
-					 * called from SSL_connect().  We want to return that
-					 * error message and not the rather unhelpful error that
-					 * OpenSSL itself returns.	So check to see if an error
-					 * message was already stored.
-					 */
-					if (conn->errorMessage.len == 0)
-					{
-						char	   *err = SSLerrmessage();
+					char	   *err = SSLerrmessage();
 
-						printfPQExpBuffer(&conn->errorMessage,
-										  libpq_gettext("SSL error: %s\n"),
-										  err);
-						SSLerrfree(err);
-					}
+					printfPQExpBuffer(&conn->errorMessage,
+									  libpq_gettext("SSL error: %s\n"),
+									  err);
+					SSLerrfree(err);
 					close_SSL(conn);
 					return PGRES_POLLING_FAILED;
 				}
@@ -1243,7 +1189,7 @@ open_client_SSL(PGconn *conn)
 
 	/*
 	 * We already checked the server certificate in initialize_SSL() using
-	 * SSL_CTX_set_verify() if root.crt exists.
+	 * SSL_CTX_set_verify(), if root.crt exists.
 	 */
 
 	/* pull out server distinguished and common names */