In order to support alternatives to OpenSSL, we need to wean off applications from using PQgetssl(). To do that, we have to provide an alternative API to get the same information. PQgetSSL() returns a pointer directly to the OpenSSL private struct, and you can do anything with that. We cannot have a generic interface that exposes everything, so we need to identify the information that people actually want, and expose that.

In the ancient patch that Martijn posted for this back in 2006 (*), he added a new libpq function called PQgettlsinfo, which returned all attributes the SSL implementation exposes as a result set with two columns, key and value. I think that was a bit awkward - a caller that's interested in a specific attribute would need to iterate through the result set to find the one its looking for. And some of the values might be somewhat expensive to calculate - e.g. extracting some attribute of the server certificate - so it would be better to only calculate the attributes that are actually needed.

I propose two functions like this:

-------

const char *
PQsslAttribute(const PGconn *conn, const char *attributeName)

Look up an attribute with the given name. Returns NULL if no attribute with that name is found.

The following common attributes are available:

library: name of the SSL implementation used. Currently always "OpenSSL", or NULL if not compiled with SSL support.

active: Is the current connection using SSL? "yes" or "no" (note that "yes" does not necessarily mean that the connection is secure, e.g. if the null-cipher is used)

server_cert_valid: Did the server present a valid certificate? "yes" or "no"

server_cert_matches_host: Does the Common Name of the certificate match the host connected to? "yes" or "no"

compression: Is SSL compression is in use, returns the name of the compression algorithm, or "yes" if compression is used but the algorithm is not known. If compression is not enabled, returns "no".

The following standard attributes are available to get more information on the ciphersuite. Note that an SSL implementation may not provide all the attributes:

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.

cipher: a short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.

  key_bits: number of key bits used by the encryption algorithm.

An implementation may provide any number of additional, implementation-specific attributes.

Although the returned pointer is declared const, it in fact points to mutable storage associated with the PGconn structure. It is unwise to assume the pointer will remain valid across queries.


const char **
PQsslListAttributes(const PGconn *conn)

Return an array of SSL attribute names available. The array is terminated by a NULL pointer. Use PQsslAttribute to get the value of an attribute.

-------

Exposing the SSL information as generic key/value pairs allows adding more attributes in the future, without breaking the ABI, and it also allows exposing implementation-specific information in a generic way. The attributes listed above cover the needs of psql. What else do we need?

I think it would also be nice to get more information from the server's certificate, like the hostname and the organization its issued to, and expiration date, so that an interactive client like pgAdmin or even psql could display that information like a web browser does. Would it be best to add those as extra attributes in the above list, perhaps with a "server_cert_*" prefix, or add a new function for extracting server cert's attributes?


The other question is: What do we do with PQgetssl()? We should document it as deprecated, but we'll have to keep it around for the foreseeable future for backwards-compatibility. We obviously cannot return a valid OpenSSL struct when using any other implementation, so I think it'll have to just return NULL when not using OpenSSL. Probably the most common use of PQgetssl() is to just check if it returns NULL or not, to determine if SSL is enabled, so a client that does that would incorrectly think that SSL is not used, even when it is. I think we can live with that.

(*) http://www.postgresql.org/message-id/20060504134807.gk4...@svana.org

- Heikki



--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to