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