diff options
Diffstat (limited to 'src/interfaces/libpq/fe-secure-openssl.c')
-rw-r--r-- | src/interfaces/libpq/fe-secure-openssl.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index 5bb9d9779d8..4bfd8e0447c 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -57,6 +57,7 @@ * include <wincrypt.h>, but some other Windows headers do.) */ #include "common/openssl.h" +#include <openssl/ssl.h> #include <openssl/conf.h> #ifdef USE_SSL_ENGINE #include <openssl/engine.h> @@ -684,6 +685,49 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn, /* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; +#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK +/* + * SSL Key Logging callback + * + * This callback lets the user store all key material to a file for debugging + * purposes. The file will be written using the NSS keylog format. LibreSSL + * 3.5 introduced stub function to set the callback for OpenSSL compatibility + * but the callback is never invoked. + */ +static void +SSL_CTX_keylog_cb(const SSL *ssl, const char *line) +{ + int fd; + mode_t old_umask; + ssize_t rc; + PGconn *conn = SSL_get_app_data(ssl); + + if (conn == NULL) + return; + + old_umask = umask(077); + fd = open(conn->sslkeylogfile, O_WRONLY | O_APPEND | O_CREAT, 0600); + umask(old_umask); + + if (fd == -1) + { + libpq_append_conn_error(conn, "could not open ssl keylog file %s: %s", + conn->sslkeylogfile, pg_strerror(errno)); + return; + } + + /* line is guaranteed by OpenSSL to be NUL terminated */ + rc = write(fd, line, strlen(line)); + if (rc < 0) + libpq_append_conn_error(conn, "could not write to ssl keylog file %s: %s", + conn->sslkeylogfile, pg_strerror(errno)); + else + rc = write(fd, "\n", 1); + (void) rc; /* silence compiler warnings */ + close(fd); +} +#endif + /* * Create per-connection SSL object, and load the client certificate, * private key, and trusted CA certs. @@ -1000,6 +1044,20 @@ initialize_SSL(PGconn *conn) } conn->ssl_in_use = true; + if (conn->sslkeylogfile && strlen(conn->sslkeylogfile) > 0) + { +#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK + SSL_CTX_set_keylog_callback(SSL_context, SSL_CTX_keylog_cb); +#else +#ifdef LIBRESSL_VERSION_NUMBER + fprintf(stderr, libpq_gettext("WARNING: sslkeylogfile support requires OpenSSL\n")); +#else + fprintf(stderr, libpq_gettext("WARNING: libpq was not built with sslkeylogfile support\n")); +#endif +#endif + } + + /* * SSL contexts are reference counted by OpenSSL. We can free it as soon * as we have created the SSL object, and it will stick around for as long |