diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 75a4d518f2..39aede4b7b 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1848,6 +1848,152 @@ int PQconnectionUsedPassword(const PGconn *conn);
+
+
+
+
+ The following functions return information related to SSL. This information
+ usually doesn't change after a connection is established.
+
+
+
+ PQsslInUsePQsslInUse>>
+
+
+ Returns true (1) if the connection uses SSL, false (0) if not.
+
+
+int PQsslInUse(const PGconn *conn);
+
+
+
+
+
+
+
+ PQsslAttributePQsslAttribute>>
+
+
+ Returns SSL-related information about the connection.
+
+
+const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
+
+
+
+
+ The list of available attributes varies depending on the SSL library
+ being used, and the type of connection. If an attribute is not
+ available, returns NULL.
+
+
+
+ The following attributes are commonly available:
+
+
+ library
+
+
+ Name of the SSL implementation in use. (Currently, only
+ "OpenSSL" is implemented)
+
+
+
+
+ protocol
+
+
+ SSL/TLS version in use. Common values are "SSLv2", "SSLv3",
+ "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may
+ return other strings if some other protocol is used.
+
+
+
+
+ key_bits
+
+
+ Number of key bits used by the encryption algorithm.
+
+
+
+
+ cipher
+
+
+ A short name of the ciphersuite used, e.g.
+ "DHE-RSA-DES-CBC3-SHA". The names are specific
+ to each SSL implementation.
+
+
+
+
+ compression
+
+
+ If SSL compression is in use, returns the name of the compression
+ algorithm, or "on" if compression is used but the algorithm is
+ not known. If compression is not in use, returns "off".
+
+
+
+
+
+
+
+
+
+ PQsslAttributesPQsslAttributes>>
+
+
+ Return an array of SSL attribute names available. The array is terminated by a NULL pointer.
+
+const char **PQsslAttributes(const PGconn *conn);
+
+
+
+
+
+
+ PQsslStructPQsslStruct>>
+
+
+ Return a pointer to an SSL-implementation specific object describing
+ the connection.
+
+void *PQsslStruct(const PGconn *conn, const char *struct_name);
+
+
+
+ The structs available depends on the SSL implementation in use.
+ For OpenSSL, there is one struct, under the name "OpenSSL",
+ and it returns a pointer to the OpenSSL SSL struct.
+ To use this function, code along the following lines could be used:
+
+#include
+
+...
+
+ SSL *ssl;
+
+ dbconn = PQconnectdb(...);
+ ...
+
+ ssl = PQsslStruct(dbconn, "OpenSSL");
+ if (ssl)
+ {
+ /* use OpenSSL functions to access ssl */
+ }
+]]>
+
+
+ This structure can be used to verify encryption levels, check server
+ certificates, and more. Refer to the OpenSSL>
+ documentation for information about this structure.
+
+
+
PQgetsslPQgetssl>>
@@ -1863,35 +2009,12 @@ void *PQgetssl(const PGconn *conn);
- This structure can be used to verify encryption levels, check server
- certificates, and more. Refer to the OpenSSL>
- documentation for information about this structure.
-
-
-
- The actual return value is of type SSL *,
- where SSL is a type defined by
- the OpenSSL library, but it is not declared
- this way to avoid requiring the OpenSSL
- header files. To use this function, code along the following lines
- could be used:
-
-#include
-
-...
-
- SSL *ssl;
-
- dbconn = PQconnectdb(...);
- ...
-
- ssl = PQgetssl(dbconn);
- if (ssl)
- {
- /* use OpenSSL functions to access ssl */
- }
-]]>
+ This function is equivalent to PQsslStruct(conn, "OpenSSL"). It should
+ not be used in new applications, because the returned struct is
+ specific to OpenSSL and will not be available if another SSL
+ implementation is used. To check if a connection uses SSL, call
+ PQsslInUse> instead, and for more details about the
+ connection, use PQsslAttribute>.
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 4ac21f20bf..7c9f28dee0 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -30,9 +30,6 @@
#include /* for umask() */
#include /* for stat() */
#endif
-#ifdef USE_OPENSSL
-#include
-#endif
#include "portability/instr_time.h"
@@ -1815,28 +1812,24 @@ connection_warnings(bool in_startup)
static void
printSSLInfo(void)
{
-#ifdef USE_OPENSSL
- int sslbits = -1;
- SSL *ssl;
+ const char *protocol;
+ const char *cipher;
+ const char *bits;
+ const char *compression;
- ssl = PQgetssl(pset.db);
- if (!ssl)
+ if (!PQsslInUse(pset.db))
return; /* no SSL */
- SSL_get_cipher_bits(ssl, &sslbits);
- printf(_("SSL connection (protocol: %s, cipher: %s, bits: %d, compression: %s)\n"),
- SSL_get_version(ssl), SSL_get_cipher(ssl), sslbits,
- SSL_get_current_compression(ssl) ? _("on") : _("off"));
-#else
+ protocol = PQsslAttribute(pset.db, "protocol");
+ cipher = PQsslAttribute(pset.db, "cipher");
+ bits = PQsslAttribute(pset.db, "key_bits");
+ compression = PQsslAttribute(pset.db, "compression");
- /*
- * If psql is compiled without SSL but is using a libpq with SSL, we
- * cannot figure out the specifics about the connection. But we know it's
- * SSL secured.
- */
- if (PQgetssl(pset.db))
- printf(_("SSL connection (unknown cipher)\n"));
-#endif
+ printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
+ protocol ? protocol : _("unknown"),
+ cipher ? cipher : _("unknown"),
+ bits ? bits : _("unknown"),
+ (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
}
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 93da50df31..4a21bf1d2c 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -165,3 +165,7 @@ lo_lseek64 162
lo_tell64 163
lo_truncate64 164
PQconninfo 165
+PQsslInUse 166
+PQsslStruct 167
+PQsslAttributes 168
+PQsslAttribute 169
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 8cdf53ec7f..a32af343a5 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1488,6 +1488,18 @@ SSLerrfree(char *buf)
free(buf);
}
+/* ------------------------------------------------------------ */
+/* SSL information functions */
+/* ------------------------------------------------------------ */
+
+int
+PQsslInUse(PGconn *conn)
+{
+ if (!conn)
+ return 0;
+ return conn->ssl_in_use;
+}
+
/*
* Return pointer to OpenSSL object.
*/
@@ -1499,6 +1511,62 @@ PQgetssl(PGconn *conn)
return conn->ssl;
}
+void *
+PQsslStruct(PGconn *conn, const char *struct_name)
+{
+ if (!conn)
+ return NULL;
+ if (strcmp(struct_name, "OpenSSL") == 0)
+ return conn->ssl;
+ return NULL;
+}
+
+const char **
+PQsslAttributes(PGconn *conn)
+{
+ static const char *result[] = {
+ "library",
+ "key_bits",
+ "cipher",
+ "compression",
+ "protocol",
+ NULL
+ };
+ return result;
+}
+
+const char *
+PQsslAttribute(PGconn *conn, const char *attribute_name)
+{
+ if (!conn)
+ return NULL;
+ if (conn->ssl == NULL)
+ return NULL;
+
+ if (strcmp(attribute_name, "library") == 0)
+ return "OpenSSL";
+
+ if (strcmp(attribute_name, "key_bits") == 0)
+ {
+ static char sslbits_str[10];
+ int sslbits;
+
+ SSL_get_cipher_bits(conn->ssl, &sslbits);
+ snprintf(sslbits_str, sizeof(sslbits_str), "%d", sslbits);
+ return sslbits_str;
+ }
+
+ if (strcmp(attribute_name, "cipher") == 0)
+ return SSL_get_cipher(conn->ssl);
+
+ if (strcmp(attribute_name, "compression") == 0)
+ return SSL_get_current_compression(conn->ssl) ? "on" : "off";
+
+ if (strcmp(attribute_name, "protocol") == 0)
+ return SSL_get_version(conn->ssl);
+
+ return NULL; /* unknown attribute */
+}
/*
* Private substitute BIO: this does the sending and receiving using send() and
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 3b79c6bbe7..b43f9fe155 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -381,12 +381,32 @@ retry_masked:
return n;
}
+/* Dummy versions of SSL info functions, when built without SSL support */
#ifndef USE_SSL
+
+int
+PQsslInUse(PGconn *conn)
+{
+ return 0;
+}
+
void *
PQgetssl(PGconn *conn)
{
return NULL;
}
+
+void *
+PQsslStruct(PGconn *conn, const char *struct_name)
+{
+ return NULL;
+}
+
+const char *
+PQsslAttribute(PGconn *conn, const char *attribute_name)
+{
+ return NULL;
+}
#endif /* USE_SSL */
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index c402119fd4..a73eae2087 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -318,6 +318,12 @@ extern int PQconnectionUsedPassword(const PGconn *conn);
extern int PQclientEncoding(const PGconn *conn);
extern int PQsetClientEncoding(PGconn *conn, const char *encoding);
+/* SSL information functions */
+extern int PQsslInUse(PGconn *conn);
+extern void *PQsslStruct(PGconn *conn, const char *struct_name);
+extern const char *PQsslAttribute(PGconn *conn, const char *attribute_name);
+extern const char **PQsslAttributes(PGconn *conn);
+
/* Get the OpenSSL structure associated with a connection. Returns NULL for
* unencrypted connections or if any other TLS library is in use. */
extern void *PQgetssl(PGconn *conn);