Commit d8bf6cdd48 for openssl.org

commit d8bf6cdd4849925c30e4f1911c7acb49cb34b702
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date:   Sun Jul 12 15:02:35 2026 +0200

    test: don't depend on DTLS alert delivery in sslrecords test

    The unknown-record-type tests (tests 5 and 6) inferred failure of a DTLS
    connection from TLSProxy's socket-teardown timing ($proxy_start_success == 0).
    This relied on the client's fatal alert reaching the peer before the client
    closes its socket, which is a race: DTLS alerts are best-effort and are never
    retransmitted (RFC 6347 section 4.2.7 / RFC 9147 section 5.10), and after the
    s_client shutdown drain was skipped for datagram protocols the alert can be
    lost during teardown, making the test flaky.

    Verify instead what is actually under test: that the DTLS client rejected the
    unrecognised record type, i.e. that s_client exited with a failure. This is a
    deterministic, local decision that does not depend on the alert being observed
    by the peer. Keep the alert observation as a best-effort diagnostic note.

    Capture the s_client exit status in TLSProxy (previously discarded after
    waitpid) and expose it via a new clientexit accessor.

    Assisted-by: Claude:claude-opus-4-8

    Reviewed-by: Neil Horman <nhorman@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Sat Jul 18 12:53:26 2026
    (Merged from https://github.com/openssl/openssl/pull/31927)

diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t
index a09a818efe..a49e3a256c 100644
--- a/test/recipes/70-test_sslrecords.t
+++ b/test/recipes/70-test_sslrecords.t
@@ -146,7 +146,12 @@ sub run_tests
     $proxy_start_success = $proxy->start();

     if ($run_test_as_dtls == 1) {
-        ok($proxy_start_success == 0, "Unrecognised record type in DTLS1.2");
+        # DTLS alerts are best-effort (RFC 6347 section 4.2.7): the client's
+        # fatal alert may be lost, so we cannot rely on observing it. What we
+        # verify is that the client rejected the connection, i.e. exited with a
+        # failure. Whether we happened to see the alert is only diagnostic.
+        ok($proxy->clientexit != 0, "Unrecognised record type in DTLS1.2");
+        note("client fatal alert observed") if $fatal_alert;
     } else {
         ok($fatal_alert, "Unrecognised record type in TLS1.2");
     }
@@ -166,7 +171,8 @@ sub run_tests
         $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
         $proxy_start_success = $proxy->start();
         if ($run_test_as_dtls == 1) {
-            ok($proxy_start_success == 0, "Unrecognised record type in DTLSv1");
+            ok($proxy->clientexit != 0, "Unrecognised record type in DTLSv1");
+            note("client fatal alert observed") if $fatal_alert;
         } else {
             ok($fatal_alert, "Unrecognised record type in TLSv1.1");
         }
diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm
index 5ba6579ed3..a7fe48e9ce 100644
--- a/util/perl/TLSProxy/Proxy.pm
+++ b/util/perl/TLSProxy/Proxy.pm
@@ -181,6 +181,7 @@ sub init
         server_port => 0,
         serverpid => 0,
         clientpid => 0,
+        clientexit => 0,
         execute => $execute,
         cert => $cert,
         debug => $debug,
@@ -219,6 +220,7 @@ sub clearClient
     $self->{clientflags} = "";
     $self->{sessionfile} = undef;
     $self->{clientpid} = 0;
+    $self->{clientexit} = 0;
     $is_tls13 = 0;
     $ciphersuite = undef;

@@ -604,6 +606,7 @@ sub clientstart
     $pid = $self->{clientpid};
     print "Waiting for s_client process to close: $pid...\n";
     waitpid($pid, 0);
+    $self->{clientexit} = $?;

     return $success;
 }
@@ -741,6 +744,11 @@ sub clientpid
     my $self = shift;
     return $self->{clientpid};
 }
+sub clientexit
+{
+    my $self = shift;
+    return $self->{clientexit};
+}

 #Read/write accessors
 sub filter