From 9c8b3f8e9ec52cf730b64eebb80f7b240584866d Mon Sep 17 00:00:00 2001
From: Abhishek Chanda <abhishek.becs@gmail.com>
Date: Tue, 7 Jan 2025 21:54:08 -0600
Subject: [PATCH] Add support for dumping SSL keylog to a file

---
 src/interfaces/libpq/fe-secure-openssl.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index 5bb9d9779d..e0d4f5befd 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -86,6 +86,7 @@ static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static PQsslKeyPassHook_OpenSSL_type PQsslKeyPassHook = NULL;
 static int	ssl_protocol_version_to_openssl(const char *protocol);
+static void SSL_CTX_keylog_cb(const SSL *ssl, const char *line);
 
 /* ------------------------------------------------------------ */
 /*			 Procedures common to all secure sessions			*/
@@ -684,6 +685,22 @@ 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;
 
+/* This is a callback that writes to a given SSLKEYLOGFILE file */
+static void SSL_CTX_keylog_cb(const SSL *ssl, const char *line) {
+    FILE *log_file;
+    char *keylog_path = getenv("SSLKEYLOGFILE");
+    if (keylog_path == NULL || strlen(keylog_path) == 0)
+           return;
+
+    log_file = fopen(keylog_path, "a");
+    if (log_file != NULL) {
+        fprintf(log_file, "%s\n", line);
+        fclose(log_file);
+    } else {
+        perror("Unable to open key log file");
+    }
+}
+
 /*
  *	Create per-connection SSL object, and load the client certificate,
  *	private key, and trusted CA certs.
@@ -733,6 +750,7 @@ initialize_SSL(PGconn *conn)
 		return -1;
 	}
 
+    SSL_CTX_set_keylog_callback(SSL_context, SSL_CTX_keylog_cb);
 	/*
 	 * Delegate the client cert password prompt to the libpq wrapper callback
 	 * if any is defined.
-- 
2.47.1

