]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
* test: allow more flexibility in the ssl modules used
authorStefan Eissing <icing@apache.org>
Tue, 30 Nov 2021 15:58:30 +0000 (15:58 +0000)
committerStefan Eissing <icing@apache.org>
Tue, 30 Nov 2021 15:58:30 +0000 (15:58 +0000)
    for a vhost. Adjust http2 and md test cases for working
    with modules other than mod_ssl.

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

test/modules/http2/env.py
test/modules/http2/test_101_ssl_reneg.py
test/modules/http2/test_700_load_get.py
test/modules/md/test_702_auto.py
test/modules/md/test_800_must_staple.py
test/modules/md/test_801_stapling.py
test/modules/md/test_810_ec.py
test/pyhttpd/conf.py
test/pyhttpd/env.py

index dae91657764572ff94412b82a364a53c31574baf..158646809c944333e5026871d319456f92cc9eaa 100644 (file)
@@ -17,7 +17,7 @@ class H2TestSetup(HttpdTestSetup):
     def __init__(self, env: 'HttpdTestEnv'):
         super().__init__(env=env)
         self.add_source_dir(os.path.dirname(inspect.getfile(H2TestSetup)))
-        self.add_modules(["http2", "proxy_http2", "cgid", "autoindex"])
+        self.add_modules(["http2", "proxy_http2", "cgid", "autoindex", "ssl"])
 
     def make(self):
         super().make()
@@ -90,6 +90,7 @@ class H2TestEnv(HttpdTestEnv):
             re.compile(r'.*malformed header from script \'hecho.py\': Bad header: x.*'),
             re.compile(r'.*:tls_post_process_client_hello:.*'),
             re.compile(r'.*:tls_process_client_certificate:.*'),
+            re.compile(r'.*have incompatible TLS configurations.'),
         ])
 
     def setup_httpd(self, setup: HttpdTestSetup = None):
@@ -106,8 +107,11 @@ class H2Conf(HttpdConf):
             ]
         }))
 
-    def start_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None):
-        super().start_vhost(domains=domains, port=port, doc_root=doc_root, with_ssl=with_ssl)
+    def start_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None,
+                    ssl_module=None, with_certificates=None):
+        super().start_vhost(domains=domains, port=port, doc_root=doc_root,
+                            with_ssl=with_ssl, ssl_module=ssl_module,
+                            with_certificates=with_certificates)
         if f"noh2.{self.env.http_tld}" in domains:
             protos = ["http/1.1"]
         elif port == self.env.https_port or with_ssl is True:
index 6d0b6ec70df1b36d577a9b8dd56ab245fc7f9ef0..1ca23d4a5d4de9eccbe9660a2526581e0218c146 100644 (file)
@@ -1,9 +1,10 @@
 import re
 import pytest
 
-from .env import H2Conf
+from .env import H2Conf, H2TestEnv
 
 
+@pytest.mark.skipif(H2TestEnv.get_ssl_module() != "mod_ssl", reason="only for mod_ssl")
 class TestSslRenegotiation:
 
     @pytest.fixture(autouse=True, scope='class')
index d181cd2882c09f83599ba038da6b8fb52e8ba5b9..69430c33f697bbca445acac5cb16c5822ec1bdd6 100644 (file)
@@ -31,7 +31,9 @@ class TestLoadGet:
         chunk = 32
         for n in range(0, 5):
             args = [env.h2load, "-n", "%d" % chunk, "-c", "1", "-m", "10",
-                    f"--base-uri={env.https_base_url}"]
+                    f"--connect-to=localhost:{env.https_port}",
+                    f"--base-uri={env.mkurl('https', 'cgi', '/')}",
+            ]
             for i in range(0, chunk):
                 args.append(env.mkurl("https", "cgi", ("/mnot164.py?count=%d&text=%s" % (start+(n*chunk)+i, text))))
             r = env.run(args)
@@ -47,7 +49,9 @@ class TestLoadGet:
         chunk = 64
         for n in range(0, 5):
             args = [env.h2load, "-n", "%d" % chunk, "-c", "%d" % conns, "-m", "10",
-                    f"--base-uri={env.https_base_url}"]
+                    f"--connect-to=localhost:{env.https_port}",
+                    f"--base-uri={env.mkurl('https', 'cgi', '/')}",
+            ]
             for i in range(0, chunk):
                 args.append(env.mkurl("https", "cgi", ("/mnot164.py?count=%d&text=%s" % (start+(n*chunk)+i, text))))
             r = env.run(args)
index ab96063268f5f2391764db25b6d47fc8f71e4a60..6864b0d2bce271bbc499a916e0d82a47eb1291cb 100644 (file)
@@ -548,7 +548,7 @@ class TestAutov2:
 
     # test case: 2.4.40 mod_ssl stumbles over a SSLCertificateChainFile when installing
     # a fallback certificate
-    @pytest.mark.skipif(HttpdTestEnv.get_ssl_module() != "ssl", reason="only for mod_ssl")
+    @pytest.mark.skipif(HttpdTestEnv.get_ssl_module() != "mod_ssl", reason="only for mod_ssl")
     def test_md_702_042(self, env):
         domain = self.test_domain
         dns_list = [domain]
@@ -658,6 +658,9 @@ class TestAutov2:
             "<IfModule ssl_module>",
             "  SSLEngine on",
             "</IfModule>",
+            "<IfModule tls_module>",
+            f"  TLSEngine {env.https_port}",
+            "</IfModule>",
             ])
         conf.add_md([domain])
         conf.install()
index 2cc063c2d3fb8afe91cea529cf20facff1f4b687..06e881c2f1e2021b40ba9b7f75510f31d0ff85ea 100644 (file)
@@ -67,7 +67,7 @@ class TestMustStaple:
 
     # MD that must staple
     @pytest.mark.skipif(MDTestEnv.lacks_ocsp(), reason="no OCSP responder")
-    @pytest.mark.skipif(MDTestEnv.get_ssl_module() != "ssl", reason="only for mod_ssl")
+    @pytest.mark.skipif(MDTestEnv.get_ssl_module() != "mod_ssl", reason="only for mod_ssl")
     def test_md_800_004(self, env):
         # mod_ssl stapling is off, expect no stapling
         stat = env.get_ocsp_status(self.domain)
index ba1aa49ad251636d997c818f4614dfd79e82722b..5c0360251b5d022943e04852fb7b0f90bcdec310 100644 (file)
@@ -103,7 +103,7 @@ class TestStapling:
         assert env.apache_restart() == 0
         stat = env.get_ocsp_status(md)
         assert stat['ocsp'] == "successful (0x0)" if \
-            env.ssl_module == "ssl" else "no response sent"
+            env.ssl_module == "mod_ssl" else "no response sent"
         stat = env.get_md_status(md)
         assert not stat["stapling"]
         #
@@ -124,7 +124,7 @@ class TestStapling:
         assert env.apache_restart() == 0
         stat = env.get_ocsp_status(md)
         assert stat['ocsp'] == "successful (0x0)" if \
-            env.ssl_module == "ssl" else "no response sent"
+            env.ssl_module == "mod_ssl" else "no response sent"
         stat = env.get_md_status(md)
         assert not stat["stapling"]
         
@@ -187,7 +187,7 @@ class TestStapling:
         # mdB has no md stapling, but mod_ssl kicks in
         stat = env.get_ocsp_status(md_b)
         assert stat['ocsp'] == "successful (0x0)" if \
-            env.ssl_module == "ssl" else "no response sent"
+            env.ssl_module == "mod_ssl" else "no response sent"
         stat = env.get_md_status(md_b)
         assert not stat["stapling"]
 
index cd849b42ad87b192c102eff6f2adac42e032eef6..f8480dd4ada6a812b12014849cf6b780a5d2a6e6 100644 (file)
@@ -89,7 +89,7 @@ class TestAutov2:
 
     # use a curve unsupported by LE
     # only works with mod_ssl as rustls refuses to load such a weak key
-    @pytest.mark.skipif(MDTestEnv.get_ssl_module() != "ssl", reason="only for mod_ssl")
+    @pytest.mark.skipif(MDTestEnv.get_ssl_module() != "mod_ssl", reason="only for mod_ssl")
     @pytest.mark.skipif(MDTestEnv.get_acme_server() != 'boulder', reason="onyl boulder rejects this")
     def test_md_810_004(self, env):
         domain = self.test_domain
@@ -111,7 +111,7 @@ class TestAutov2:
         domain = self.test_domain
         # behaviour differences, mod_ssl selects the strongest suitable,
         # mod_tls selects the first suitable
-        ec_key_len = 384 if env.ssl_module == "ssl" else 256
+        ec_key_len = 384 if env.ssl_module == "mod_ssl" else 256
         self.set_get_check_pkeys(env, domain, [
             {'spec': "secp256r1", 'ciphers': "ECDSA", 'keylen': ec_key_len},
             {'spec': "RSA 4096", 'ciphers': "ECDHE-RSA-CHACHA20-POLY1305", 'keylen': 4096},
index 3fefffaa8c0261e01f1cf024ffff9cb1f96141c1..a2eeab9bfea236265870a350410a08bbb7b73967 100644 (file)
@@ -17,6 +17,7 @@ class HttpdConf(object):
         self._extras = extras.copy() if extras else {}
         if 'base' in self._extras:
             self.add(self._extras['base'])
+        self._tls_engine_ports = set()
 
     def __repr__(self):
         s = '\n'.join(self._lines)
@@ -36,29 +37,45 @@ class HttpdConf(object):
             self._lines.extend(line)
         return self
 
-    def add_certificate(self, cert_file, key_file):
-        if self.env.ssl_module == "ssl":
+    def add_certificate(self, cert_file, key_file, ssl_module=None):
+        if ssl_module is None:
+            ssl_module = self.env.ssl_module
+        if ssl_module == 'mod_ssl':
             self.add([
                 f"SSLCertificateFile {cert_file}",
                 f"SSLCertificateKeyFile {key_file if key_file else cert_file}",
             ])
-        elif self.env.ssl_module == "tls":
-            self.add(f"""
-                TLSCertificate {cert_file} {key_file}
-            """)
+        elif ssl_module == 'mod_tls':
+            self.add(f"TLSCertificate {cert_file} {key_file if key_file else ''}")
+        elif ssl_module == 'mod_gnutls':
+            self.add([
+                f"GnuTLSCertificateFile {cert_file}",
+                f"GnuTLSKeyFile {key_file if key_file else cert_file}",
+            ])
+        else:
+            raise Exception(f"unsupported ssl module: {ssl_module}")
 
-    def add_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None):
-        self.start_vhost(domains=domains, port=port, doc_root=doc_root, with_ssl=with_ssl)
+    def add_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None,
+                  with_certificates=None, ssl_module=None):
+        self.start_vhost(domains=domains, port=port, doc_root=doc_root,
+                         with_ssl=with_ssl, with_certificates=with_certificates,
+                         ssl_module=ssl_module)
         self.end_vhost()
         return self
 
-    def start_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None):
+    def start_vhost(self, domains, port=None, doc_root="htdocs", with_ssl=None,
+                    ssl_module=None, with_certificates=None):
         if not isinstance(domains, list):
             domains = [domains]
         if port is None:
             port = self.env.https_port
+        if ssl_module is None:
+            ssl_module = self.env.ssl_module
         if with_ssl is None:
-            with_ssl = (self.env.https_port == port)
+            with_ssl = self.env.https_port == port
+        if with_ssl and ssl_module == 'mod_tls' and port not in self._tls_engine_ports:
+            self.add(f"TLSEngine {port}")
+            self._tls_engine_ports.add(port)
         self.add("")
         self.add(f"<VirtualHost *:{port}>")
         self._indents += 1
@@ -67,10 +84,13 @@ class HttpdConf(object):
             self.add(f"ServerAlias {alias}")
         self.add(f"DocumentRoot {doc_root}")
         if with_ssl:
-            if self.env.ssl_module == "ssl":
+            if ssl_module == 'mod_ssl':
                 self.add("SSLEngine on")
-            for cred in self.env.get_credentials_for_name(domains[0]):
-                self.add_certificate(cred.cert_file, cred.pkey_file)
+            elif ssl_module == 'mod_gnutls':
+                self.add("GnuTLSEnable on")
+            if with_certificates is not False:
+                for cred in self.env.get_credentials_for_name(domains[0]):
+                    self.add_certificate(cred.cert_file, cred.pkey_file, ssl_module=ssl_module)
         if domains[0] in self._extras:
             self.add(self._extras[domains[0]])
         return self
index 73044ae40b122de82fc48aae34d913cb97b54cba..be28e9979054ae1eddb1791005e3d228bcbe3570 100644 (file)
@@ -72,9 +72,7 @@ class HttpdTestSetup:
         self._source_dirs.append(source_dir)
 
     def add_modules(self, modules: List[str]):
-        for m in modules:
-            if m not in self._modules:
-                self._modules.append(m)
+        self._modules.extend(modules)
 
     def make(self):
         self._make_dirs()
@@ -122,11 +120,17 @@ class HttpdTestSetup:
             fd.write(t.substitute(var_map))
 
     def _make_modules_conf(self):
+        loaded = set()
         modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf')
         with open(modules_conf, 'w') as fd:
             # issue load directives for all modules we want that are shared
             missing_mods = list()
             for m in self._modules:
+                match = re.match(r'^mod_(.+)$', m)
+                if match:
+                    m = match.group(1)
+                if m in loaded:
+                    continue
                 mod_path = os.path.join(self.env.libexec_dir, f"mod_{m}.so")
                 if os.path.isfile(mod_path):
                     fd.write(f"LoadModule {m}_module   \"{mod_path}\"\n")
@@ -134,6 +138,7 @@ class HttpdTestSetup:
                     fd.write(f"#built static: LoadModule {m}_module   \"{mod_path}\"\n")
                 else:
                     missing_mods.append(m)
+                loaded.add(m)
         if len(missing_mods) > 0:
             raise Exception(f"Unable to find modules: {missing_mods} "
                             f"DSOs: {self.env.dso_modules}")
@@ -162,7 +167,7 @@ class HttpdTestEnv:
 
     @classmethod
     def get_ssl_module(cls):
-        return os.environ['SSL'] if 'SSL' in os.environ else 'ssl'
+        return os.environ['SSL'] if 'SSL' in os.environ else 'mod_ssl'
 
     def __init__(self, pytestconfig=None):
         self._our_dir = os.path.dirname(inspect.getfile(Dummy))