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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user