Copilot commented on code in PR #3173:
URL: https://github.com/apache/brpc/pull/3173#discussion_r2621859021


##########
src/brpc/details/ssl_helper.cpp:
##########
@@ -185,6 +188,43 @@ static void SSLMessageCallback(int write_p, int version, 
int content_type,
 #endif // TLS1_RT_HEARTBEAT
 }
 
+#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static pthread_once_t g_ssl_keylog_once = PTHREAD_ONCE_INIT;
+static FILE* g_ssl_keylog_file = NULL;
+
+static void InitSSLKeyLogFile() {
+    const char* path = getenv("SSLKEYLOGFILE");
+    if (path == NULL || path[0] == '\0') {
+        return;
+    }
+    g_ssl_keylog_file = fopen(path, "a");

Review Comment:
   The file handle opened here is never closed, causing a resource leak. The 
file remains open for the entire lifetime of the process. Consider adding a 
cleanup mechanism, such as registering an atexit handler or using a RAII 
wrapper to ensure the file is properly closed when the program terminates.



##########
src/brpc/details/ssl_helper.cpp:
##########
@@ -185,6 +188,43 @@ static void SSLMessageCallback(int write_p, int version, 
int content_type,
 #endif // TLS1_RT_HEARTBEAT
 }
 
+#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static pthread_once_t g_ssl_keylog_once = PTHREAD_ONCE_INIT;
+static FILE* g_ssl_keylog_file = NULL;
+
+static void InitSSLKeyLogFile() {
+    const char* path = getenv("SSLKEYLOGFILE");
+    if (path == NULL || path[0] == '\0') {
+        return;
+    }
+    g_ssl_keylog_file = fopen(path, "a");
+    if (g_ssl_keylog_file == NULL) {
+        PLOG(WARNING) << "Fail to open SSLKEYLOGFILE=" << path;
+    }
+}
+
+static void SSLKeyLogCallback(const SSL* ssl, const char* line) {
+    (void)ssl;
+    if (line == NULL) {
+        return;
+    }
+    // Write the full key log line with newline in one call to keep output 
atomic.
+    fprintf(g_ssl_keylog_file, "%s\n", line);
+    fflush(g_ssl_keylog_file);
+}
+
+static void MaybeSetKeyLogCallback(SSL_CTX* ctx) {
+    pthread_once(&g_ssl_keylog_once, InitSSLKeyLogFile);
+    if (ctx != NULL && g_ssl_keylog_file != NULL) {
+        SSL_CTX_set_keylog_callback(ctx, SSLKeyLogCallback);
+    }
+}

Review Comment:
   The InitSSLKeyLogFile, SSLKeyLogCallback, and MaybeSetKeyLogCallback 
functions lack documentation explaining their purpose, the SSLKEYLOGFILE format 
expectations, and any security implications of enabling this feature. Adding 
comments would help other developers understand when and how this debugging 
feature should be used, especially since it exposes sensitive cryptographic 
material.



##########
src/brpc/details/ssl_helper.cpp:
##########
@@ -185,6 +188,43 @@ static void SSLMessageCallback(int write_p, int version, 
int content_type,
 #endif // TLS1_RT_HEARTBEAT
 }
 
+#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static pthread_once_t g_ssl_keylog_once = PTHREAD_ONCE_INIT;
+static FILE* g_ssl_keylog_file = NULL;
+
+static void InitSSLKeyLogFile() {
+    const char* path = getenv("SSLKEYLOGFILE");
+    if (path == NULL || path[0] == '\0') {
+        return;
+    }
+    g_ssl_keylog_file = fopen(path, "a");
+    if (g_ssl_keylog_file == NULL) {
+        PLOG(WARNING) << "Fail to open SSLKEYLOGFILE=" << path;
+    }
+}
+
+static void SSLKeyLogCallback(const SSL* ssl, const char* line) {
+    (void)ssl;
+    if (line == NULL) {
+        return;
+    }
+    // Write the full key log line with newline in one call to keep output 
atomic.
+    fprintf(g_ssl_keylog_file, "%s\n", line);
+    fflush(g_ssl_keylog_file);

Review Comment:
   The fprintf and fflush operations on g_ssl_keylog_file are not thread-safe. 
The SSLKeyLogCallback can be invoked concurrently from multiple SSL 
connections, and without synchronization, concurrent writes could interleave or 
corrupt the output. Consider adding a mutex to protect the file write 
operations or use flockfile/funlockfile for atomic writes.



##########
src/brpc/details/ssl_helper.cpp:
##########
@@ -185,6 +188,43 @@ static void SSLMessageCallback(int write_p, int version, 
int content_type,
 #endif // TLS1_RT_HEARTBEAT
 }
 
+#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static pthread_once_t g_ssl_keylog_once = PTHREAD_ONCE_INIT;
+static FILE* g_ssl_keylog_file = NULL;
+
+static void InitSSLKeyLogFile() {
+    const char* path = getenv("SSLKEYLOGFILE");
+    if (path == NULL || path[0] == '\0') {
+        return;
+    }
+    g_ssl_keylog_file = fopen(path, "a");
+    if (g_ssl_keylog_file == NULL) {
+        PLOG(WARNING) << "Fail to open SSLKEYLOGFILE=" << path;

Review Comment:
   The SSLKEYLOGFILE feature exposes TLS master secrets which can be used to 
decrypt all traffic for those sessions. While this is intentional for 
debugging, consider adding a warning log message when the feature is enabled to 
alert users that sensitive cryptographic material is being written to disk, 
helping prevent accidental use in production environments.
   ```suggestion
           PLOG(WARNING) << "Fail to open SSLKEYLOGFILE=" << path;
       } else {
           LOG(WARNING) << "SSLKEYLOGFILE is enabled (path: " << path << "). "
                        << "Sensitive TLS session keys will be written to this 
file. "
                        << "This feature is intended for debugging only and 
should NOT be used in production environments.";
   ```



##########
src/brpc/details/ssl_helper.cpp:
##########
@@ -185,6 +188,43 @@ static void SSLMessageCallback(int write_p, int version, 
int content_type,
 #endif // TLS1_RT_HEARTBEAT
 }
 
+#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10101000L)
+static pthread_once_t g_ssl_keylog_once = PTHREAD_ONCE_INIT;
+static FILE* g_ssl_keylog_file = NULL;
+
+static void InitSSLKeyLogFile() {
+    const char* path = getenv("SSLKEYLOGFILE");
+    if (path == NULL || path[0] == '\0') {
+        return;
+    }
+    g_ssl_keylog_file = fopen(path, "a");
+    if (g_ssl_keylog_file == NULL) {
+        PLOG(WARNING) << "Fail to open SSLKEYLOGFILE=" << path;
+    }
+}
+
+static void SSLKeyLogCallback(const SSL* ssl, const char* line) {
+    (void)ssl;
+    if (line == NULL) {
+        return;
+    }
+    // Write the full key log line with newline in one call to keep output 
atomic.
+    fprintf(g_ssl_keylog_file, "%s\n", line);
+    fflush(g_ssl_keylog_file);

Review Comment:
   The SSLKeyLogCallback function performs file operations without checking if 
g_ssl_keylog_file is NULL. If InitSSLKeyLogFile fails to open the file (line 
200-203), g_ssl_keylog_file remains NULL, which will cause a segmentation fault 
when fprintf and fflush are called with a NULL file pointer. Add a null check 
before accessing g_ssl_keylog_file.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to