]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Arrange pytest to run with mod_ssl, still skipping some tests.
authorJean-Frederic Clere <jfclere@apache.org>
Tue, 16 Apr 2024 15:02:29 +0000 (15:02 +0000)
committerJean-Frederic Clere <jfclere@apache.org>
Tue, 16 Apr 2024 15:02:29 +0000 (15:02 +0000)
this closes #433

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1917039 13f79535-47bb-0310-9956-ffa450edef68

test/modules/md/conftest.py
test/modules/tls/conf.py
test/modules/tls/env.py
test/modules/tls/test_02_conf.py
test/modules/tls/test_06_ciphers.py
test/modules/tls/test_08_vars.py
test/modules/tls/test_14_proxy_ssl.py
test/modules/tls/test_15_proxy_tls.py
test/modules/tls/test_16_proxy_mixed.py
test/modules/tls/test_17_proxy_machine_cert.py
test/pyhttpd/conf.py

index 0118de5e1339705855a28f157082af4637b3dab5..0f9e4a9f490df87285feea6c0d3ec25313fac2bc 100755 (executable)
@@ -39,7 +39,9 @@ def env(pytestconfig) -> MDTestEnv:
 @pytest.fixture(autouse=True, scope="package")
 def _md_package_scope(env):
     env.httpd_error_log.add_ignored_lognos([
-        "AH10085"   # There are no SSL certificates configured and no other module contributed any
+        "AH10085",   # There are no SSL certificates configured and no other module contributed any
+        "AH10045",   # No VirtualHost matches Managed Domain
+        "AH10105",   # MDomain does not match any VirtualHost with 'SSLEngine on'
     ])
 
 
index ddeb91f99a894c40c79b92e2c823bc05b63c6dc9..b34f746004cf04f6e0a43ebfafc3b230d9745a89 100644 (file)
@@ -13,7 +13,10 @@ class TlsTestConf(HttpdConf):
 
     def start_tls_vhost(self, domains: List[str], port=None, ssl_module=None):
         if ssl_module is None:
-            ssl_module = 'mod_tls'
+            if not self.env.has_shared_module("tls"):
+                ssl_module = "mod_ssl"
+            else:
+                ssl_module = 'mod_tls'
         super().start_vhost(domains=domains, port=port, doc_root=f"htdocs/{domains[0]}", ssl_module=ssl_module)
 
     def end_tls_vhost(self):
@@ -39,8 +42,12 @@ class TlsTestConf(HttpdConf):
                     f"    MDCertificateKeyFile {pkey_file}",
                     ])
             self.add("</MDomain>")
+            if self.env.has_shared_module("tls"):
+                ssl_module= "mod_tls"
+            else:
+                ssl_module= "mod_ssl"
             super().add_vhost(domains=[domain], port=port, doc_root=f"htdocs/{domain}",
-                              with_ssl=True, with_certificates=False, ssl_module='mod_tls')
+                              with_ssl=True, with_certificates=False, ssl_module=ssl_module)
 
     def add_md_base(self, domain: str):
         self.add([
index 0e457bf13763e7765e1181e52551410b8f987b5f..6afc472cb082fe7047f892b76929d10c6f6f1fad 100644 (file)
@@ -129,7 +129,10 @@ class TlsTestEnv(HttpdTestEnv):
             ]),
             CertificateSpec(name="user1", client=True, single_file=True),
         ])
-        self.add_httpd_log_modules(['tls'])
+        if not HttpdTestEnv.has_shared_module("tls"):
+            self.add_httpd_log_modules(['ssl'])
+        else:
+            self.add_httpd_log_modules(['tls'])
 
 
     def setup_httpd(self, setup: TlsTestSetup = None):
index 4d6aa60200a3f302668db04f8385ed5b36019640..88be80c3a673194a11eee311810a606fcd1c3826 100644 (file)
@@ -64,9 +64,15 @@ class TestConf:
     ])
     def test_tls_02_conf_cert_listen_valid(self, env, listen: str):
         conf = TlsTestConf(env=env)
-        conf.add("TLSEngine {listen}".format(listen=listen))
-        conf.install()
-        assert env.apache_restart() == 0
+        if not env.has_shared_module("tls"):
+            # Without cert/key openssl will complain
+            conf.add("SSLEngine on");
+            conf.install()
+            assert env.apache_restart() == 1
+        else:
+            conf.add("TLSEngine {listen}".format(listen=listen))
+            conf.install()
+            assert env.apache_restart() == 0
 
     def test_tls_02_conf_cert_listen_cert(self, env):
         domain = env.domain_a
index 6f515e4d77736eedd3ea14a5800f1160f1ce811b..4bedd692ceb4571716fea545bb85be67186bc563 100644 (file)
@@ -181,7 +181,10 @@ class TestCiphers:
         })
         conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b])
         conf.install()
-        assert env.apache_restart() == 0
+        if not conf.env.has_shared_module("tls"):
+            assert env.apache_restart() != 0
+        else:
+            assert env.apache_restart() == 0
         #
         env.httpd_error_log.ignore_recent(
             lognos = [
@@ -204,4 +207,6 @@ class TestCiphers:
         })
         conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b])
         conf.install()
+        if not conf.env.has_shared_module("tls"):
+            return
         assert env.apache_restart() == 0
index f1bd9b418a27d1492bf2f9f0814117e4d40a665d..ad764a7985ac6cffa6039c2e3e2fb7ae871cf0af 100644 (file)
@@ -23,7 +23,10 @@ class TestVars:
     def test_tls_08_vars_root(self, env):
         # in domain_b root, the StdEnvVars is switch on
         exp_proto = "TLSv1.2"
-        exp_cipher = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
+        if env.has_shared_module("tls"):
+            exp_cipher = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
+        else:
+            exp_cipher = "ECDHE-ECDSA-AES256-GCM-SHA384"
         options = [ '--tls-max', '1.2']
         r = env.tls_get(env.domain_b, "/vars.py", options=options)
         assert r.exit_code == 0, r.stderr
@@ -47,7 +50,12 @@ class TestVars:
     def test_tls_08_vars_const(self, env, name: str, value: str):
         r = env.tls_get(env.domain_b, f"/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
-        assert r.json == {name: value}, r.stdout
+        if env.has_shared_module("tls"):
+            assert r.json == {name: value}, r.stdout
+        else:
+            if name == "SSL_SECURE_RENEG":
+                value = "true"
+            assert r.json == {name: value}, r.stdout
 
     @pytest.mark.parametrize("name, pattern", [
         ("SSL_VERSION_INTERFACE", r'mod_tls/\d+\.\d+\.\d+'),
@@ -57,4 +65,11 @@ class TestVars:
         r = env.tls_get(env.domain_b, f"/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert name in r.json
-        assert re.match(pattern, r.json[name]), r.json
+        if env.has_shared_module("tls"):
+            assert re.match(pattern, r.json[name]), r.json
+        else:
+            if name == "SSL_VERSION_INTERFACE":
+                pattern = r'mod_ssl/\d+\.\d+\.\d+'
+            else:
+                pattern = r'OpenSSL/\d+\.\d+\.\d+'
+            assert re.match(pattern, r.json[name]), r.json
index 3118b4dda1e10278dbf523702332748f53c3bfea..2f46c64f710f26b917d9c9e79fcadd26b5c43dde 100644 (file)
@@ -2,6 +2,7 @@ import re
 import pytest
 
 from .conf import TlsTestConf
+from pyhttpd.env import HttpdTestEnv
 
 
 class TestProxySSL:
@@ -9,6 +10,12 @@ class TestProxySSL:
     @pytest.fixture(autouse=True, scope='class')
     def _class_scope(self, env):
         # add vhosts a+b and a ssl proxy from a to b
+        if not HttpdTestEnv.has_shared_module("tls"):
+            myoptions="SSLOptions +StdEnvVars"
+            myssl="mod_ssl"
+        else:
+            myoptions="TLSOptions +StdEnvVars"
+            myssl="mod_tls"
         conf = TlsTestConf(env=env, extras={
             'base': [
                 "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace1 proxy_http2:trace1",
@@ -33,10 +40,10 @@ class TestProxySSL:
                 f'ProxyPass /proxy-ssl/ https://127.0.0.1:{env.https_port}/',
                 f'ProxyPass /proxy-local/ https://localhost:{env.https_port}/',
                 f'ProxyPass /proxy-h2-ssl/ h2://127.0.0.1:{env.https_port}/',
-                "TLSOptions +StdEnvVars",
+                myoptions,
             ],
         })
-        conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b])
+        conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b], ssl_module=myssl)
         conf.install()
         assert env.apache_restart() == 0
 
@@ -69,7 +76,24 @@ class TestProxySSL:
         ("SSL_CIPHER_EXPORT", "false"),
         ("SSL_CLIENT_VERIFY", "NONE"),
     ])
+    def test_tls_14_proxy_tsl_vars_const(self, env, name: str, value: str):
+        if not HttpdTestEnv.has_shared_module("tls"):
+            return
+        r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
+        assert r.exit_code == 0, r.stderr
+        assert r.json == {name: value}, r.stdout
+
+    @pytest.mark.parametrize("name, value", [
+        ("SERVER_NAME", "b.mod-tls.test"),
+        ("SSL_SESSION_RESUMED", "Initial"),
+        ("SSL_SECURE_RENEG", "true"),
+        ("SSL_COMPRESS_METHOD", "NULL"),
+        ("SSL_CIPHER_EXPORT", "false"),
+        ("SSL_CLIENT_VERIFY", "NONE"),
+    ])
     def test_tls_14_proxy_ssl_vars_const(self, env, name: str, value: str):
+        if HttpdTestEnv.has_shared_module("tls"):
+            return
         r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert r.json == {name: value}, r.stdout
@@ -78,7 +102,21 @@ class TestProxySSL:
         ("SSL_VERSION_INTERFACE", r'mod_tls/\d+\.\d+\.\d+'),
         ("SSL_VERSION_LIBRARY", r'rustls-ffi/\d+\.\d+\.\d+/rustls/\d+\.\d+\.\d+'),
     ])
+    def test_tls_14_proxy_tsl_vars_match(self, env, name: str, pattern: str):
+        if not HttpdTestEnv.has_shared_module("tls"):
+            return
+        r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
+        assert r.exit_code == 0, r.stderr
+        assert name in r.json
+        assert re.match(pattern, r.json[name]), r.json
+
+    @pytest.mark.parametrize("name, pattern", [
+        ("SSL_VERSION_INTERFACE", r'mod_ssl/\d+\.\d+\.\d+'),
+        ("SSL_VERSION_LIBRARY", r'OpenSSL/\d+\.\d+\.\d+'),
+    ])
     def test_tls_14_proxy_ssl_vars_match(self, env, name: str, pattern: str):
+        if HttpdTestEnv.has_shared_module("tls"):
+            return
         r = env.tls_get(env.domain_b, f"/proxy-ssl/vars.py?name={name}")
         assert r.exit_code == 0, r.stderr
         assert name in r.json
index ed881a034dc1d859899357f0dbfb4976fc199718..e7eb10362b02d07fcade190aa0a4c097c8518de9 100644 (file)
@@ -3,7 +3,9 @@ from datetime import timedelta
 import pytest
 
 from .conf import TlsTestConf
+from pyhttpd.env import HttpdTestEnv
 
+@pytest.mark.skipif(condition=not HttpdTestEnv.has_shared_module("tls"), reason="no mod_tls available")
 
 class TestProxyTLS:
 
index ca082362d7a9a913bc2249b5a1b976c0137454c2..88b351fd94b8ef38b3dc01f0973df856588e8874 100644 (file)
@@ -3,6 +3,9 @@ import time
 import pytest
 
 from .conf import TlsTestConf
+from pyhttpd.env import HttpdTestEnv
+
+@pytest.mark.skipif(condition=not HttpdTestEnv.has_shared_module("tls"), reason="no mod_tls available")
 
 
 class TestProxyMixed:
index 7b5ef44d6fb9d577df1b4495134240b1c5fcee80..a5410d63ad4c7468a30bcddec07d874dfb666f86 100644 (file)
@@ -3,8 +3,9 @@ import os
 import pytest
 
 from .conf import TlsTestConf
+from pyhttpd.env import HttpdTestEnv
 
-
+@pytest.mark.skipif(condition=not HttpdTestEnv.has_shared_module("tls"), reason="no mod_tls available")
 class TestProxyMachineCert:
 
     @pytest.fixture(autouse=True, scope='class')
index cd3363fb73a75b4a1d2f39f0ff9f028b54ccc140..e1c6bf5ee959972fb2da94e884dc15c2f063fd1a 100644 (file)
@@ -26,15 +26,96 @@ class HttpdConf(object):
     def install(self):
         self.env.install_test_conf(self._lines)
 
+    def replacetlsstr(self, line):
+            l = line.replace("TLS_", "")
+            l = l.replace("\n", " ")
+            l = l.replace("\\", " ")
+            l = " ".join(l.split())
+            l = l.replace(" ", ":")
+            l = l.replace("_", "-")
+            l = l.replace("-WITH", "")
+            l = l.replace("AES-", "AES")
+            l = l.replace("POLY1305-SHA256", "POLY1305")
+            return l
+
+    def replaceinstr(self, line):
+        if line.startswith("TLSCiphersPrefer"):
+            # the "TLS_" are changed into "".
+            l = self.replacetlsstr(line)
+            l = l.replace("TLSCiphersPrefer:", "SSLCipherSuite ")
+        elif line.startswith("TLSCiphersSuppress"):
+            # like SSLCipherSuite but with :!
+            l = self.replacetlsstr(line)
+            l = l.replace("TLSCiphersSuppress:", "SSLCipherSuite !")
+            l = l.replace(":", ":!")
+        elif line.startswith("TLSCertificate"):
+            l = line.replace("TLSCertificate", "SSLCertificateFile")
+        elif line.startswith("TLSProtocol"):
+            # mod_ssl is different (+ no supported and 0x code have to be translated)
+            l = line.replace("TLSProtocol", "SSLProtocol")
+            l = l.replace("+", "")
+            l = l.replace("default", "all")
+            l = l.replace("0x0303", "1.2") # need to check 1.3 and 1.1
+        elif line.startswith("SSLProtocol"):
+            l = line # we have that in test/modules/tls/test_05_proto.py
+        elif line.startswith("TLSHonorClientOrder"):
+            # mod_ssl has SSLHonorCipherOrder on = use server off = use client.
+            l = line.lower()
+            if "on" in l:
+                l = "SSLHonorCipherOrder off"
+            else:
+                l = "SSLHonorCipherOrder on"
+        elif line.startswith("TLSEngine"):
+            # In fact it should go in the corresponding VirtualHost... Not sure how to do that.
+            l = "SSLEngine On"
+        else:
+            if line != "":
+                l = line.replace("TLS", "SSL")
+            else:
+                l = line
+        return l
+
     def add(self, line: Any):
+        # make we transform the TLS to SSL if we are using mod_ssl
         if isinstance(line, str):
+            if not HttpdTestEnv.has_shared_module("tls"):
+                line = self.replaceinstr(line)
             if self._indents > 0:
                 line = f"{'  ' * self._indents}{line}"
             self._lines.append(line)
         else:
-            if self._indents > 0:
-                line = [f"{'  ' * self._indents}{l}" for l in line]
-            self._lines.extend(line)
+            if not HttpdTestEnv.has_shared_module("tls"):
+                new = []
+                previous = ""
+                for l in line:
+                    if previous.startswith("SSLCipherSuite"):
+                        if l.startswith("TLSCiphersPrefer") or l.startswith("TLSCiphersSuppress"):
+                            # we need to merge it   
+                            l = self.replaceinstr(l)
+                            l = l.replace("SSLCipherSuite ", ":")
+                            previous = previous + l
+                            continue
+                        else:
+                            if self._indents > 0:
+                                previous = f"{'  ' * self._indents}{previous}"
+                            new.append(previous)
+                            previous = ""
+                    l = self.replaceinstr(l)
+                    if l.startswith("SSLCipherSuite"):
+                        previous = l
+                        continue
+                    if self._indents > 0:
+                        l = f"{'  ' * self._indents}{l}"
+                    new.append(l)
+                if previous != "":
+                    if self._indents > 0:
+                        previous = f"{'  ' * self._indents}{previous}"
+                    new.append(previous)
+                self._lines.extend(new)
+            else:
+                if self._indents > 0:
+                    line = [f"{'  ' * self._indents}{l}" for l in line]
+                self._lines.extend(line)
         return self
 
     def add_certificate(self, cert_file, key_file, ssl_module=None):