aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-secure-openssl.c
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2025-04-03 13:16:43 +0200
committerDaniel Gustafsson <dgustafsson@postgresql.org>2025-04-03 13:16:43 +0200
commit2da74d8d6400975bf73fb0df97c3943ad3ed9a36 (patch)
tree5f20eb74d2450a87985026348a8f406d438c1a6a /src/interfaces/libpq/fe-secure-openssl.c
parente4309f73f698851a2f7d49ca5e98e3e188400891 (diff)
downloadpostgresql-2da74d8d6400975bf73fb0df97c3943ad3ed9a36.tar.gz
postgresql-2da74d8d6400975bf73fb0df97c3943ad3ed9a36.zip
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
Diffstat (limited to 'src/interfaces/libpq/fe-secure-openssl.c')
-rw-r--r--src/interfaces/libpq/fe-secure-openssl.c58
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