diff options
-rw-r--r-- | doc/src/sgml/libpq.sgml | 155 | ||||
-rw-r--r-- | src/bin/psql/command.c | 35 | ||||
-rw-r--r-- | src/interfaces/libpq/exports.txt | 4 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure-openssl.c | 68 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure.c | 20 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-fe.h | 6 |
6 files changed, 251 insertions, 37 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 75a4d518f26..39aede4b7b7 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1848,33 +1848,127 @@ int PQconnectionUsedPassword(const PGconn *conn); </para> </listitem> </varlistentry> + </variablelist> + </para> - <varlistentry id="libpq-pqgetssl"> - <term><function>PQgetssl</function><indexterm><primary>PQgetssl</></></term> + <para> + The following functions return information related to SSL. This information + usually doesn't change after a connection is established. + + <variablelist> + <varlistentry id="libpq-pqsslinuse"> + <term><function>PQsslInUse</function><indexterm><primary>PQsslInUse</></></term> <listitem> <para> - <indexterm><primary>SSL</><secondary sortas="libpq">in libpq</secondary></indexterm> - Returns the SSL structure used in the connection, or null - if SSL is not in use. + Returns true (1) if the connection uses SSL, false (0) if not. <synopsis> -void *PQgetssl(const PGconn *conn); +int PQsslInUse(const PGconn *conn); </synopsis> </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqsslAttribute"> + <term><function>PQsslAttribute</function><indexterm><primary>PQsslAttribute</></></term> + <listitem> <para> - This structure can be used to verify encryption levels, check server - certificates, and more. Refer to the <productname>OpenSSL</> - documentation for information about this structure. + Returns SSL-related information about the connection. + +<synopsis> +const char *PQsslAttribute(const PGconn *conn, const char *attribute_name); +</synopsis> + </para> + + <para> + 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. + </para> + + <para> + The following attributes are commonly available: + <variablelist> + <varlistentry> + <term><literal>library</literal></term> + <listitem> + <para> + Name of the SSL implementation in use. (Currently, only + <literal>"OpenSSL"</literal> is implemented) + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>protocol</literal></term> + <listitem> + <para> + 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. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>key_bits</literal></term> + <listitem> + <para> + Number of key bits used by the encryption algorithm. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>cipher</literal></term> + <listitem> + <para> + A short name of the ciphersuite used, e.g. + <literal>"DHE-RSA-DES-CBC3-SHA"</literal>. The names are specific + to each SSL implementation. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>compression</literal></term> + <listitem> + <para> + 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". + </para> + </listitem> + </varlistentry> + </variablelist> </para> + </listitem> + </varlistentry> + <varlistentry id="libpq-pqsslattributes"> + <term><function>PQsslAttributes</function><indexterm><primary>PQsslAttributes</></></term> + <listitem> + <para> + Return an array of SSL attribute names available. The array is terminated by a NULL pointer. +<synopsis> +const char **PQsslAttributes(const PGconn *conn); +</synopsis> + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqsslstruct"> + <term><function>PQsslStruct</function><indexterm><primary>PQsslStruct</></></term> + <listitem> + <para> + Return a pointer to an SSL-implementation specific object describing + the connection. +<synopsis> +void *PQsslStruct(const PGconn *conn, const char *struct_name); +</synopsis> + </para> <para> - The actual return value is of type <type>SSL *</type>, - where <type>SSL</type> is a type defined by - the <productname>OpenSSL</productname> library, but it is not declared - this way to avoid requiring the <productname>OpenSSL</productname> - header files. To use this function, code along the following lines - could be used: + 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 <literal>SSL</literal> struct. + To use this function, code along the following lines could be used: <programlisting><![CDATA[ #include <libpq-fe.h> #include <openssl/ssl.h> @@ -1886,13 +1980,42 @@ void *PQgetssl(const PGconn *conn); dbconn = PQconnectdb(...); ... - ssl = PQgetssl(dbconn); + ssl = PQsslStruct(dbconn, "OpenSSL"); if (ssl) { /* use OpenSSL functions to access ssl */ } ]]></programlisting> </para> + <para> + This structure can be used to verify encryption levels, check server + certificates, and more. Refer to the <productname>OpenSSL</> + documentation for information about this structure. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqgetssl"> + <term><function>PQgetssl</function><indexterm><primary>PQgetssl</></></term> + <listitem> + <para> + <indexterm><primary>SSL</><secondary sortas="libpq">in libpq</secondary></indexterm> + Returns the SSL structure used in the connection, or null + if SSL is not in use. + +<synopsis> +void *PQgetssl(const PGconn *conn); +</synopsis> + </para> + + <para> + 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 + <function>PQsslInUse</> instead, and for more details about the + connection, use <function>PQsslAttribute</>. + </para> </listitem> </varlistentry> diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 4ac21f20bf4..7c9f28dee06 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -30,9 +30,6 @@ #include <sys/types.h> /* for umask() */ #include <sys/stat.h> /* for stat() */ #endif -#ifdef USE_OPENSSL -#include <openssl/ssl.h> -#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 93da50df311..4a21bf1d2cf 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 8cdf53ec7f8..a32af343a50 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 3b79c6bbe7b..b43f9fe155d 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 c402119fd46..a73eae2087a 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); |