This is an automated email from the ASF dual-hosted git repository.

cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit b99e662cc9f1173bbc14540449c1be5925f2e102
Author: Bryan Call <[email protected]>
AuthorDate: Fri Feb 13 15:33:13 2026 -0800

    Check Curl support for TLS 1.0 and 1.1  (#12887)
    
    Skip TLSv1/TLSv1.1 subtests when curl cannot negotiate those protocols.
    Adds a curl-based capability probe alongside the existing OpenSSL check.
    
    (cherry picked from commit 8def184a6fca011141ee5470e78608ae31e24f9c)
---
 tests/gold_tests/autest-site/conditions.test.ext   | 62 ++++++++++++++++++++++
 tests/gold_tests/tls/tls_client_versions.test.py   | 31 ++++++-----
 .../tls/tls_client_versions_minmax.test.py         | 47 ++++++++--------
 3 files changed, 105 insertions(+), 35 deletions(-)

diff --git a/tests/gold_tests/autest-site/conditions.test.ext 
b/tests/gold_tests/autest-site/conditions.test.ext
index e01fecdb85..e228b19fae 100644
--- a/tests/gold_tests/autest-site/conditions.test.ext
+++ b/tests/gold_tests/autest-site/conditions.test.ext
@@ -146,6 +146,67 @@ def HasCurlOption(self, option):
     return self.CheckOutput(['curl', '--help', 'all'], default, "Curl needs to 
support option: {option}".format(option=option))
 
 
+def HasCurlTLSVersionSupport(self, tls_version):
+    """Check whether curl can attempt a given TLS version.
+
+    This probes curl directly because OpenSSL capability checks do not always
+    reflect curl runtime policy behavior on hardened systems.
+    """
+
+    def check_curl_tls_support():
+        # Map semantic versions used by tests to curl flags.
+        version_map = {
+            "1.0": ("--tlsv1", "1.0"),
+            "1.1": ("--tlsv1.1", "1.1"),
+            "1.2": ("--tlsv1.2", "1.2"),
+            "1.3": ("--tlsv1.3", "1.3"),
+        }
+        if tls_version not in version_map:
+            return False
+
+        tls_flag, tls_max = version_map[tls_version]
+        try:
+            # Connect to localhost closed port to avoid network dependencies.
+            # "connection refused" means curl accepted the TLS flags and tried.
+            result = subprocess.run(
+                [
+                    "curl",
+                    "-svk",
+                    "--connect-timeout",
+                    "2",
+                    "--max-time",
+                    "3",
+                    tls_flag,
+                    "--tls-max",
+                    tls_max,
+                    "https://127.0.0.1:1";,
+                ],
+                capture_output=True,
+                text=True,
+                timeout=5,
+            )
+            output = (result.stdout + result.stderr).lower()
+            unsupported_markers = [
+                "unsupported protocol",
+                "no protocols available",
+                "option --tlsv",
+                "unknown option",
+                "is unknown",
+            ]
+            if any(marker in output for marker in unsupported_markers):
+                return False
+
+            # Any attempt to connect implies curl accepted the TLS setting.
+            return True
+        except subprocess.TimeoutExpired:
+            return False
+        except Exception:
+            return False
+
+    return self.Condition(
+        check_curl_tls_support, "Curl does not support TLSv{version} in this 
environment".format(version=tls_version))
+
+
 def HasATSFeature(self, feature):
 
     val = self.Variables.get(feature, None)
@@ -175,5 +236,6 @@ ExtendCondition(HasATSFeature)
 ExtendCondition(HasCurlVersion)
 ExtendCondition(HasCurlFeature)
 ExtendCondition(HasCurlOption)
+ExtendCondition(HasCurlTLSVersionSupport)
 ExtendCondition(PluginExists)
 ExtendCondition(CurlUsingUnixDomainSocket)
diff --git a/tests/gold_tests/tls/tls_client_versions.test.py 
b/tests/gold_tests/tls/tls_client_versions.test.py
index 1f0343d9cd..134124eabf 100644
--- a/tests/gold_tests/tls/tls_client_versions.test.py
+++ b/tests/gold_tests/tls/tls_client_versions.test.py
@@ -25,6 +25,7 @@ Test TLS protocol offering  based on SNI
 
 Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
 Test.SkipUnless(Condition.HasLegacyTLSSupport())
+has_curl_tlsv1 = Condition.HasCurlTLSVersionSupport("1.0")
 
 # Define default ATS
 ts = Test.MakeATSProcess("ts", enable_tls=True)
@@ -85,22 +86,24 @@ tr.ReturnCode = 35
 tr.StillRunningAfter = ts
 
 # Target foo.com for TLSv1.  Should succeed
-tr = Test.AddTestRun("foo.com TLSv1")
-tr.MakeCurlCommand(
-    "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
-        ts.Variables.ssl_port),
-    ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+    tr = Test.AddTestRun("foo.com TLSv1")
+    tr.MakeCurlCommand(
+        "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
+            ts.Variables.ssl_port),
+        ts=ts)
+    tr.ReturnCode = 0
+    tr.StillRunningAfter = ts
 
 # Target bar.com for TLSv1.  Should fail
-tr = Test.AddTestRun("bar.com TLSv1")
-tr.MakeCurlCommand(
-    "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'bar.com:{0}:127.0.0.1' -k  https://bar.com:{0}".format(
-        ts.Variables.ssl_port),
-    ts=ts)
-tr.ReturnCode = 35
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+    tr = Test.AddTestRun("bar.com TLSv1")
+    tr.MakeCurlCommand(
+        "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'bar.com:{0}:127.0.0.1' -k  https://bar.com:{0}".format(
+            ts.Variables.ssl_port),
+        ts=ts)
+    tr.ReturnCode = 35
+    tr.StillRunningAfter = ts
 
 # Target bar.com for TLSv1_2.  Should succeed
 tr = Test.AddTestRun("bar.com TLSv1_2")
diff --git a/tests/gold_tests/tls/tls_client_versions_minmax.test.py 
b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
index 9c63d0700d..4c0d1742e8 100644
--- a/tests/gold_tests/tls/tls_client_versions_minmax.test.py
+++ b/tests/gold_tests/tls/tls_client_versions_minmax.test.py
@@ -25,6 +25,8 @@ Test TLS protocol offering  based on SNI
 
 Test.SkipUnless(Condition.HasOpenSSLVersion("1.1.1"))
 Test.SkipUnless(Condition.HasLegacyTLSSupport())
+has_curl_tlsv1 = Condition.HasCurlTLSVersionSupport("1.0")
+has_curl_tlsv1_1 = Condition.HasCurlTLSVersionSupport("1.1")
 
 # Define default ATS
 ts = Test.MakeATSProcess("ts", enable_tls=True)
@@ -90,31 +92,34 @@ tr.ReturnCode = 35
 tr.StillRunningAfter = ts
 
 # Target foo.com for TLSv1.  Should succeed
-tr = Test.AddTestRun("foo.com TLSv1")
-tr.MakeCurlCommand(
-    "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
-        ts.Variables.ssl_port),
-    ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+    tr = Test.AddTestRun("foo.com TLSv1")
+    tr.MakeCurlCommand(
+        "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
+            ts.Variables.ssl_port),
+        ts=ts)
+    tr.ReturnCode = 0
+    tr.StillRunningAfter = ts
 
 # Target foo.com for TLSv1_1.  Should succeed
-tr = Test.AddTestRun("foo.com TLSv1_1")
-tr.MakeCurlCommand(
-    "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.1 --tlsv1.1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
-        ts.Variables.ssl_port),
-    ts=ts)
-tr.ReturnCode = 0
-tr.StillRunningAfter = ts
+if has_curl_tlsv1_1:
+    tr = Test.AddTestRun("foo.com TLSv1_1")
+    tr.MakeCurlCommand(
+        "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.1 --tlsv1.1 --resolve 
'foo.com:{0}:127.0.0.1' -k  https://foo.com:{0}".format(
+            ts.Variables.ssl_port),
+        ts=ts)
+    tr.ReturnCode = 0
+    tr.StillRunningAfter = ts
 
 # Target bar.com for TLSv1.  Should fail
-tr = Test.AddTestRun("bar.com TLSv1")
-tr.MakeCurlCommand(
-    "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'bar.com:{0}:127.0.0.1' -k  https://bar.com:{0}".format(
-        ts.Variables.ssl_port),
-    ts=ts)
-tr.ReturnCode = 35
-tr.StillRunningAfter = ts
+if has_curl_tlsv1:
+    tr = Test.AddTestRun("bar.com TLSv1")
+    tr.MakeCurlCommand(
+        "-v --ciphers DEFAULT@SECLEVEL=0 --tls-max 1.0 --tlsv1 --resolve 
'bar.com:{0}:127.0.0.1' -k  https://bar.com:{0}".format(
+            ts.Variables.ssl_port),
+        ts=ts)
+    tr.ReturnCode = 35
+    tr.StillRunningAfter = ts
 
 # Target bar.com for TLSv1_2.  Should succeed
 tr = Test.AddTestRun("bar.com TLSv1_2")

Reply via email to