diff options
Diffstat (limited to 'src/interfaces')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 4 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-secure-openssl.c | 58 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-int.h | 1 |
3 files changed, 63 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 715b5d5aff4..0258d9ace3c 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -401,6 +401,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = { "OAuth-Scope", "", 15, offsetof(struct pg_conn, oauth_scope)}, + {"sslkeylogfile", NULL, NULL, NULL, + "SSL-Key-Log-File", "", 0, /* sizeof("") = 0 */ + offsetof(struct pg_conn, sslkeylogfile)}, + /* Terminating entry --- MUST BE LAST */ {NULL, NULL, NULL, NULL, NULL, NULL, 0} 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 diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 25de3e95055..9369c217fb5 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -426,6 +426,7 @@ struct pg_conn char *load_balance_hosts; /* load balance over hosts */ char *scram_client_key; /* base64-encoded SCRAM client key */ char *scram_server_key; /* base64-encoded SCRAM server key */ + char *sslkeylogfile; /* where should the client write ssl keylogs */ bool cancelRequest; /* true if this connection is used to send a * cancel request, instead of being a normal |