Commit e7e7950998 for openssl.org

commit e7e79509986a3b6134ce3bbf30d7afcfd117c7eb
Author: Dmitry Belyavskiy <beldmit@gmail.com>
Date:   Wed Jun 25 16:41:30 2025 +0200

    Enforce permissions 0600 for SSLKEYLOGFILE

    Fixes #27890

    Reviewed-by: Neil Horman <nhorman@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/27893)

diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 34cde49496..9696a4c55f 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -33,6 +33,11 @@
 #include "internal/ssl_unwrap.h"
 #include "quic/quic_local.h"

+#ifndef OPENSSL_NO_SSLKEYLOG
+# include <sys/stat.h>
+# include <fcntl.h>
+#endif
+
 static int ssl_undefined_function_3(SSL_CONNECTION *sc, unsigned char *r,
                                     unsigned char *s, size_t t, size_t *u)
 {
@@ -3983,6 +3988,33 @@ static void do_sslkeylogfile(const SSL *ssl, const char *line)
  * via ssl.h.
  */

+#ifndef OPENSSL_NO_SSLKEYLOG
+static BIO *get_sslkeylog_bio(const char *keylogfile)
+{
+# ifdef _POSIX_C_SOURCE
+    BIO *b;
+    int fdno = -1;
+    FILE *fp = NULL;
+
+    fdno = open(keylogfile, O_WRONLY | O_CREAT | O_APPEND,  0600);
+    if (fdno < 0)
+        return NULL;
+
+    fp = fdopen(fdno, "a");
+    if (fp == NULL) {
+        close(fdno);
+        return NULL;
+    }
+
+    if ((b = BIO_new_fp(fp, BIO_CLOSE)) == NULL)
+        fclose(fp);
+    return b;
+# else
+    return BIO_new_file(keylogfile, "a");
+# endif
+}
+#endif
+
 SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
                         const SSL_METHOD *meth)
 {
@@ -4295,7 +4327,7 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
              * if its already there.
              */
             if (keylog_bio == NULL) {
-                keylog_bio = BIO_new_file(keylogfile, "a");
+                keylog_bio = get_sslkeylog_bio(keylogfile);
                 if (keylog_bio == NULL) {
                     OSSL_TRACE(TLS, "Unable to create keylog bio\n");
                     goto out;
diff --git a/test/recipes/70-test_sslkeylogfile.t b/test/recipes/70-test_sslkeylogfile.t
index acff862229..99ff83e112 100644
--- a/test/recipes/70-test_sslkeylogfile.t
+++ b/test/recipes/70-test_sslkeylogfile.t
@@ -19,7 +19,12 @@ setup($test_name);
 plan skip_all => "$test_name requires SSLKEYLOGFILE support"
     if disabled("sslkeylog");

-plan tests => 1;
+my $tests = 1;
+if ($^O =~ /^(linux)$/) {
+    $tests = 2;
+}
+
+plan tests => $tests;


 my $shlib_wrap   = srctop_file("util", "wrap.pl");
@@ -75,3 +80,9 @@ kill 'HUP', $s_server_pid;
 # Test 1: Compare the output of -keylogfile  and SSLKEYLOGFILE, and make sure they match
 # Note, the former adds a comment, that the latter does not, so ignore comments with -I in diff
 ok(run(cmd(["diff", "-I" ,"^#.*\$", $sslkeylogfile, $trace_file])));
+
+# Test 2, linux-specific: the keylog file should have permission 0600
+if ($^O =~ /^(linux)$/) {
+    my $mode = sprintf("%04o", (stat($sslkeylogfile))[2] & 07777);
+    ok($mode eq "0600");
+}