1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-24 01:29:19 +03:00

libpq: Add support for dumping SSL key material to file

This adds a new connection parameter which instructs libpq to
write out keymaterial clientside into a file in order to make
connection debugging with Wireshark and similar tools possible.
The file format used is the standardized NSS format.

Author: Abhishek Chanda <abhishek.becs@gmail.com>
Co-authored-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Discussion: https://postgr.es/m/CAKiP-K85C8uQbzXKWf5wHQPkuygGUGcufke713iHmYWOe9q2dA@mail.gmail.com
This commit is contained in:
Daniel Gustafsson
2025-04-03 13:16:43 +02:00
parent e4309f73f6
commit 2da74d8d64
9 changed files with 120 additions and 2 deletions

View File

@@ -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