diff options
author | Stefan Eissing <icing@apache.org> | 2024-09-17 13:06:04 +0200 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2024-09-17 13:06:04 +0200 |
commit | 988f4496320604225900061e696c7201db8e9d03 (patch) | |
tree | 0db4386b90b8ac956a97153b27febc23659f5525 /test | |
parent | some text formatting cleanup (diff) | |
download | apache2-988f4496320604225900061e696c7201db8e9d03.tar.xz apache2-988f4496320604225900061e696c7201db8e9d03.zip |
removed experimental mod_tls. source, documenation and test cases
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1920744 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test')
30 files changed, 0 insertions, 1946 deletions
diff --git a/test/modules/tls/__init__.py b/test/modules/tls/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 --- a/test/modules/tls/__init__.py +++ /dev/null diff --git a/test/modules/tls/conf.py b/test/modules/tls/conf.py deleted file mode 100644 index b34f746004..0000000000 --- a/test/modules/tls/conf.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -from typing import List, Dict, Any - -from pyhttpd.conf import HttpdConf -from pyhttpd.env import HttpdTestEnv - - -class TlsTestConf(HttpdConf): - - def __init__(self, env: HttpdTestEnv, extras: Dict[str, Any] = None): - extras = extras if extras is not None else {} - super().__init__(env=env, extras=extras) - - def start_tls_vhost(self, domains: List[str], port=None, ssl_module=None): - if ssl_module is None: - 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): - self.end_vhost() - - def add_tls_vhosts(self, domains: List[str], port=None, ssl_module=None): - for domain in domains: - self.start_tls_vhost(domains=[domain], port=port, ssl_module=ssl_module) - self.end_tls_vhost() - - def add_md_vhosts(self, domains: List[str], port = None): - self.add([ - f"LoadModule md_module {self.env.libexec_dir}/mod_md.so", - "LogLevel md:debug", - ]) - for domain in domains: - self.add(f"<MDomain {domain}>") - for cred in self.env.ca.get_credentials_for_name(domain): - cert_file = os.path.relpath(cred.cert_file, self.env.server_dir) - pkey_file = os.path.relpath(cred.pkey_file, self.env.server_dir) if cred.pkey_file else cert_file - self.add([ - f" MDCertificateFile {cert_file}", - 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=ssl_module) - - def add_md_base(self, domain: str): - self.add([ - f"LoadModule md_module {self.env.libexec_dir}/mod_md.so", - "LogLevel md:debug", - f"ServerName {domain}", - "MDBaseServer on", - ]) - self.add(f"TLSEngine {self.env.https_port}") - self.add(f"<MDomain {domain}>") - for cred in self.env.ca.get_credentials_for_name(domain): - cert_file = os.path.relpath(cred.cert_file, self.env.server_dir) - pkey_file = os.path.relpath(cred.pkey_file, self.env.server_dir) if cred.pkey_file else cert_file - self.add([ - f"MDCertificateFile {cert_file}", - f"MDCertificateKeyFile {pkey_file}", - ]) - self.add("</MDomain>") diff --git a/test/modules/tls/conftest.py b/test/modules/tls/conftest.py deleted file mode 100644 index 6f6f983cfd..0000000000 --- a/test/modules/tls/conftest.py +++ /dev/null @@ -1,38 +0,0 @@ -import logging -import os -import sys -import pytest - -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - -from .env import TlsTestEnv - - -def pytest_report_header(config, startdir): - _x = config - _x = startdir - env = TlsTestEnv() - return "mod_tls [apache: {aversion}({prefix})]".format( - prefix=env.prefix, - aversion=env.get_httpd_version() - ) - - -@pytest.fixture(scope="package") -def env(pytestconfig) -> TlsTestEnv: - level = logging.INFO - console = logging.StreamHandler() - console.setLevel(level) - console.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) - logging.getLogger('').addHandler(console) - logging.getLogger('').setLevel(level=level) - env = TlsTestEnv(pytestconfig=pytestconfig) - env.setup_httpd() - env.apache_access_log_clear() - env.httpd_error_log.clear_log() - return env - -@pytest.fixture(autouse=True, scope="package") -def _stop_package_scope(env): - yield - assert env.apache_stop() == 0 diff --git a/test/modules/tls/env.py b/test/modules/tls/env.py deleted file mode 100644 index efc4f0b247..0000000000 --- a/test/modules/tls/env.py +++ /dev/null @@ -1,199 +0,0 @@ -import inspect -import logging -import os -import re -import subprocess - -from datetime import timedelta, datetime -from typing import List, Optional, Dict, Tuple, Union - -from pyhttpd.certs import CertificateSpec -from pyhttpd.env import HttpdTestEnv, HttpdTestSetup -from pyhttpd.result import ExecResult - -log = logging.getLogger(__name__) - - -class TlsTestSetup(HttpdTestSetup): - - def __init__(self, env: 'HttpdTestEnv'): - super().__init__(env=env) - self.add_source_dir(os.path.dirname(inspect.getfile(TlsTestSetup))) - self.add_modules(["tls", "http2", "cgid", "watchdog", "proxy_http2"]) - - -class TlsCipher: - - def __init__(self, id: int, name: str, flavour: str, - min_version: float, max_version: float = None, - openssl: str = None): - self.id = id - self.name = name - self.flavour = flavour - self.min_version = min_version - self.max_version = max_version if max_version is not None else self.min_version - if openssl is None: - if name.startswith('TLS13_'): - openssl = re.sub(r'^TLS13_', 'TLS_', name) - else: - openssl = re.sub(r'^TLS_', '', name) - openssl = re.sub(r'_WITH_([^_]+)_', r'_\1_', openssl) - openssl = re.sub(r'_AES_(\d+)', r'_AES\1', openssl) - openssl = re.sub(r'(_POLY1305)_\S+$', r'\1', openssl) - openssl = re.sub(r'_', '-', openssl) - self.openssl_name = openssl - self.id_name = "TLS_CIPHER_0x{0:04x}".format(self.id) - - def __repr__(self): - return self.name - - def __str__(self): - return self.name - - -class TlsTestEnv(HttpdTestEnv): - - CURL_SUPPORTS_TLS_1_3 = None - - @classmethod - @property - def is_unsupported(cls): - mpm_module = f"mpm_{os.environ['MPM']}" if 'MPM' in os.environ else 'mpm_event' - return mpm_module == 'mpm_prefork' - - @classmethod - def curl_supports_tls_1_3(cls) -> bool: - if cls.CURL_SUPPORTS_TLS_1_3 is None: - # Unfortunately, there is no reliable, platform-independant - # way to verify that TLSv1.3 is properly supported by curl. - # - # p = subprocess.run(['curl', '--tlsv1.3', 'https://shouldneverexistreally'], - # stderr=subprocess.PIPE, stdout=subprocess.PIPE) - # return code 6 means the site could not be resolved, but the - # tls parameter was recognized - cls.CURL_SUPPORTS_TLS_1_3 = False - return cls.CURL_SUPPORTS_TLS_1_3 - - - # current rustls supported ciphers in their order of preference - # used to test cipher selection, see test_06_ciphers.py - RUSTLS_CIPHERS = [ - TlsCipher(0x1303, "TLS13_CHACHA20_POLY1305_SHA256", "CHACHA", 1.3), - TlsCipher(0x1302, "TLS13_AES_256_GCM_SHA384", "AES", 1.3), - TlsCipher(0x1301, "TLS13_AES_128_GCM_SHA256", "AES", 1.3), - TlsCipher(0xcca9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "ECDSA", 1.2), - TlsCipher(0xcca8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", 1.2), - TlsCipher(0xc02c, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDSA", 1.2), - TlsCipher(0xc02b, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDSA", 1.2), - TlsCipher(0xc030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "RSA", 1.2), - TlsCipher(0xc02f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "RSA", 1.2), - ] - - def __init__(self, pytestconfig=None): - super().__init__(pytestconfig=pytestconfig) - self._domain_a = "a.mod-tls.test" - self._domain_b = "b.mod-tls.test" - self.add_httpd_conf([ - f'<Directory "{self.server_dir}/htdocs/{self.domain_a}">', - ' AllowOverride None', - ' Require all granted', - ' AddHandler cgi-script .py', - ' Options +ExecCGI', - '</Directory>', - f'<Directory "{self.server_dir}/htdocs/{self.domain_b}">', - ' AllowOverride None', - ' Require all granted', - ' AddHandler cgi-script .py', - ' Options +ExecCGI', - '</Directory>', - f'<VirtualHost *:{self.http_port}>', - ' ServerName localhost', - ' DocumentRoot "htdocs"', - '</VirtualHost>', - f'<VirtualHost *:{self.http_port}>', - f' ServerName {self.domain_a}', - ' DocumentRoot "htdocs/a.mod-tls.test"', - '</VirtualHost>', - f'<VirtualHost *:{self.http_port}>', - f' ServerName {self.domain_b}', - ' DocumentRoot "htdocs/b.mod-tls.test"', - '</VirtualHost>', - ]) - self.add_cert_specs([ - CertificateSpec(domains=[self.domain_a]), - CertificateSpec(domains=[self.domain_b], key_type='secp256r1', single_file=True), - CertificateSpec(domains=[self.domain_b], key_type='rsa4096'), - CertificateSpec(name="clientsX", sub_specs=[ - CertificateSpec(name="user1", client=True, single_file=True), - CertificateSpec(name="user2", client=True, single_file=True), - CertificateSpec(name="user_expired", client=True, - single_file=True, valid_from=timedelta(days=-91), - valid_to=timedelta(days=-1)), - ]), - CertificateSpec(name="clientsY", sub_specs=[ - CertificateSpec(name="user1", client=True, single_file=True), - ]), - CertificateSpec(name="user1", client=True, single_file=True), - ]) - 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): - if setup is None: - setup = TlsTestSetup(env=self) - super().setup_httpd(setup=setup) - - @property - def domain_a(self) -> str: - return self._domain_a - - @property - def domain_b(self) -> str: - return self._domain_b - - def tls_get(self, domain, paths: Union[str, List[str]], options: List[str] = None, no_stdout_list = False) -> ExecResult: - if isinstance(paths, str): - paths = [paths] - urls = [f"https://{domain}:{self.https_port}{path}" for path in paths] - return self.curl_raw(urls=urls, options=options, no_stdout_list=no_stdout_list) - - def tls_get_json(self, domain: str, path: str, options=None): - r = self.tls_get(domain=domain, paths=path, options=options) - return r.json - - def run_diff(self, fleft: str, fright: str) -> ExecResult: - return self.run(['diff', '-u', fleft, fright]) - - def openssl(self, args: List[str]) -> ExecResult: - return self.run(['openssl'] + args) - - def openssl_client(self, domain, extra_args: List[str] = None) -> ExecResult: - args = ["s_client", "-CAfile", self.ca.cert_file, "-servername", domain, - "-connect", "localhost:{port}".format( - port=self.https_port - )] - if extra_args: - args.extend(extra_args) - args.extend([]) - return self.openssl(args) - - OPENSSL_SUPPORTED_PROTOCOLS = None - - @staticmethod - def openssl_supports_tls_1_3() -> bool: - if TlsTestEnv.OPENSSL_SUPPORTED_PROTOCOLS is None: - env = TlsTestEnv() - r = env.openssl(args=["ciphers", "-v"]) - protos = set() - ciphers = set() - for line in r.stdout.splitlines(): - m = re.match(r'^(\S+)\s+(\S+)\s+(.*)$', line) - if m: - ciphers.add(m.group(1)) - protos.add(m.group(2)) - TlsTestEnv.OPENSSL_SUPPORTED_PROTOCOLS = protos - TlsTestEnv.OPENSSL_SUPPORTED_CIPHERS = ciphers - return "TLSv1.3" in TlsTestEnv.OPENSSL_SUPPORTED_PROTOCOLS diff --git a/test/modules/tls/htdocs/a.mod-tls.test/index.json b/test/modules/tls/htdocs/a.mod-tls.test/index.json deleted file mode 100644 index ffc32cb275..0000000000 --- a/test/modules/tls/htdocs/a.mod-tls.test/index.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "domain": "a.mod-tls.test" -}
\ No newline at end of file diff --git a/test/modules/tls/htdocs/a.mod-tls.test/vars.py b/test/modules/tls/htdocs/a.mod-tls.test/vars.py deleted file mode 100755 index bd520e27bb..0000000000 --- a/test/modules/tls/htdocs/a.mod-tls.test/vars.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -import json -import os, sys -from urllib import parse -import multipart # https://github.com/andrew-d/python-multipart (`apt install python3-multipart`) - - -def get_request_params(): - oforms = {} - ofiles = {} - if "REQUEST_URI" in os.environ: - qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query) - for name, values in qforms.items(): - oforms[name] = values[0] - if "HTTP_CONTENT_TYPE" in os.environ: - ctype = os.environ["HTTP_CONTENT_TYPE"] - if ctype == "application/x-www-form-urlencoded": - qforms = parse.parse_qs(parse.urlsplit(sys.stdin.read()).query) - for name, values in qforms.items(): - oforms[name] = values[0] - elif ctype.startswith("multipart/"): - def on_field(field): - oforms[field.field_name] = field.value - def on_file(file): - ofiles[field.field_name] = field.value - multipart.parse_form(headers={"Content-Type": ctype}, input_stream=sys.stdin.buffer, on_field=on_field, on_file=on_file) - return oforms, ofiles - - -forms, files = get_request_params() - -jenc = json.JSONEncoder() - -def get_var(name: str, def_val: str = ""): - if name in os.environ: - return os.environ[name] - return def_val - -def get_json_var(name: str, def_val: str = ""): - var = get_var(name, def_val=def_val) - return jenc.encode(var) - - -name = forms['name'] if 'name' in forms else None - -print("Content-Type: application/json\n") -if name: - print(f"""{{ "{name}" : {get_json_var(name, '')}}}""") -else: - print(f"""{{ "https" : {get_json_var('HTTPS', '')}, - "host" : {get_json_var('SERVER_NAME', '')}, - "protocol" : {get_json_var('SERVER_PROTOCOL', '')}, - "ssl_protocol" : {get_json_var('SSL_PROTOCOL', '')}, - "ssl_cipher" : {get_json_var('SSL_CIPHER', '')} -}}""") - diff --git a/test/modules/tls/htdocs/b.mod-tls.test/dir1/vars.py b/test/modules/tls/htdocs/b.mod-tls.test/dir1/vars.py deleted file mode 100755 index b86a968b55..0000000000 --- a/test/modules/tls/htdocs/b.mod-tls.test/dir1/vars.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 -import os - -def get_var(name: str, def_val: str = ""): - if name in os.environ: - return os.environ[name] - return def_val - -print("Content-Type: application/json") -print() -print("""{{ "https" : "{https}", - "host" : "{server_name}", - "protocol" : "{protocol}", - "ssl_protocol" : "{ssl_protocol}", - "ssl_cipher" : "{ssl_cipher}" -}}""".format( - https=get_var('HTTPS', ''), - server_name=get_var('SERVER_NAME', ''), - protocol=get_var('SERVER_PROTOCOL', ''), - ssl_protocol=get_var('SSL_PROTOCOL', ''), - ssl_cipher=get_var('SSL_CIPHER', ''), -)) - diff --git a/test/modules/tls/htdocs/b.mod-tls.test/index.json b/test/modules/tls/htdocs/b.mod-tls.test/index.json deleted file mode 100644 index e5d3ccf1fa..0000000000 --- a/test/modules/tls/htdocs/b.mod-tls.test/index.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "domain": "b.mod-tls.test" -}
\ No newline at end of file diff --git a/test/modules/tls/htdocs/b.mod-tls.test/resp-jitter.py b/test/modules/tls/htdocs/b.mod-tls.test/resp-jitter.py deleted file mode 100755 index f7b134999d..0000000000 --- a/test/modules/tls/htdocs/b.mod-tls.test/resp-jitter.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 -import random -import sys -import time -from datetime import timedelta - -random.seed() -to_write = total_len = random.randint(1, 10*1024*1024) - -sys.stdout.write("Content-Type: application/octet-stream\n") -sys.stdout.write(f"Content-Length: {total_len}\n") -sys.stdout.write("\n") -sys.stdout.flush() - -while to_write > 0: - len = random.randint(1, 1024*1024) - len = min(len, to_write) - sys.stdout.buffer.write(random.randbytes(len)) - to_write -= len - delay = timedelta(seconds=random.uniform(0.0, 0.5)) - time.sleep(delay.total_seconds()) -sys.stdout.flush() - diff --git a/test/modules/tls/htdocs/b.mod-tls.test/vars.py b/test/modules/tls/htdocs/b.mod-tls.test/vars.py deleted file mode 100755 index bd520e27bb..0000000000 --- a/test/modules/tls/htdocs/b.mod-tls.test/vars.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -import json -import os, sys -from urllib import parse -import multipart # https://github.com/andrew-d/python-multipart (`apt install python3-multipart`) - - -def get_request_params(): - oforms = {} - ofiles = {} - if "REQUEST_URI" in os.environ: - qforms = parse.parse_qs(parse.urlsplit(os.environ["REQUEST_URI"]).query) - for name, values in qforms.items(): - oforms[name] = values[0] - if "HTTP_CONTENT_TYPE" in os.environ: - ctype = os.environ["HTTP_CONTENT_TYPE"] - if ctype == "application/x-www-form-urlencoded": - qforms = parse.parse_qs(parse.urlsplit(sys.stdin.read()).query) - for name, values in qforms.items(): - oforms[name] = values[0] - elif ctype.startswith("multipart/"): - def on_field(field): - oforms[field.field_name] = field.value - def on_file(file): - ofiles[field.field_name] = field.value - multipart.parse_form(headers={"Content-Type": ctype}, input_stream=sys.stdin.buffer, on_field=on_field, on_file=on_file) - return oforms, ofiles - - -forms, files = get_request_params() - -jenc = json.JSONEncoder() - -def get_var(name: str, def_val: str = ""): - if name in os.environ: - return os.environ[name] - return def_val - -def get_json_var(name: str, def_val: str = ""): - var = get_var(name, def_val=def_val) - return jenc.encode(var) - - -name = forms['name'] if 'name' in forms else None - -print("Content-Type: application/json\n") -if name: - print(f"""{{ "{name}" : {get_json_var(name, '')}}}""") -else: - print(f"""{{ "https" : {get_json_var('HTTPS', '')}, - "host" : {get_json_var('SERVER_NAME', '')}, - "protocol" : {get_json_var('SERVER_PROTOCOL', '')}, - "ssl_protocol" : {get_json_var('SSL_PROTOCOL', '')}, - "ssl_cipher" : {get_json_var('SSL_CIPHER', '')} -}}""") - diff --git a/test/modules/tls/htdocs/index.html b/test/modules/tls/htdocs/index.html deleted file mode 100644 index 3c07626144..0000000000 --- a/test/modules/tls/htdocs/index.html +++ /dev/null @@ -1,9 +0,0 @@ -<html> - <head> - <title>mod_h2 test site generic</title> - </head> - <body> - <h1>mod_h2 test site generic</h1> - </body> -</html> - diff --git a/test/modules/tls/htdocs/index.json b/test/modules/tls/htdocs/index.json deleted file mode 100644 index 6d456e0af5..0000000000 --- a/test/modules/tls/htdocs/index.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "domain": "localhost" -}
\ No newline at end of file diff --git a/test/modules/tls/test_01_apache.py b/test/modules/tls/test_01_apache.py deleted file mode 100644 index cb6af6d461..0000000000 --- a/test/modules/tls/test_01_apache.py +++ /dev/null @@ -1,14 +0,0 @@ -import pytest - -from .conf import TlsTestConf - - -class TestApache: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - TlsTestConf(env=env).install() - assert env.apache_restart() == 0 - - def test_tls_01_apache_http(self, env): - assert env.is_live(env.http_base_url) diff --git a/test/modules/tls/test_02_conf.py b/test/modules/tls/test_02_conf.py deleted file mode 100644 index 88be80c3a6..0000000000 --- a/test/modules/tls/test_02_conf.py +++ /dev/null @@ -1,144 +0,0 @@ -import os -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf - - -class TestConf: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - TlsTestConf(env=env).install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - if env.is_live(timeout=timedelta(milliseconds=100)): - assert env.apache_stop() == 0 - - def test_tls_02_conf_cert_args_missing(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSCertificate") - conf.install() - assert env.apache_fail() == 0 - - def test_tls_02_conf_cert_single_arg(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSCertificate cert.pem") - conf.install() - assert env.apache_fail() == 0 - - def test_tls_02_conf_cert_file_missing(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSCertificate cert.pem key.pem") - conf.install() - assert env.apache_fail() == 0 - - def test_tls_02_conf_cert_file_exist(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSCertificate test-02-cert.pem test-02-key.pem") - conf.install() - for name in ["test-02-cert.pem", "test-02-key.pem"]: - with open(os.path.join(env.server_dir, name), "w") as fd: - fd.write("") - assert env.apache_fail() == 0 - - def test_tls_02_conf_cert_listen_missing(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSEngine") - conf.install() - assert env.apache_fail() == 0 - - def test_tls_02_conf_cert_listen_wrong(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSEngine ^^^^^") - conf.install() - assert env.apache_fail() == 0 - - @pytest.mark.parametrize("listen", [ - "443", - "129.168.178.188:443", - "[::]:443", - ]) - def test_tls_02_conf_cert_listen_valid(self, env, listen: str): - conf = TlsTestConf(env=env) - 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 - conf = TlsTestConf(env=env) - conf.add_tls_vhosts(domains=[domain]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_02_conf_proto_wrong(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSProtocol wrong") - conf.install() - assert env.apache_fail() == 0 - - @pytest.mark.parametrize("proto", [ - "default", - "TLSv1.2+", - "TLSv1.3+", - "TLSv0x0303+", - ]) - def test_tls_02_conf_proto_valid(self, env, proto): - conf = TlsTestConf(env=env) - conf.add("TLSProtocol {proto}".format(proto=proto)) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_02_conf_honor_wrong(self, env): - conf = TlsTestConf(env=env) - conf.add("TLSHonorClientOrder wrong") - conf.install() - assert env.apache_fail() == 0 - - @pytest.mark.parametrize("honor", [ - "on", - "OfF", - ]) - def test_tls_02_conf_honor_valid(self, env, honor: str): - conf = TlsTestConf(env=env) - conf.add("TLSHonorClientOrder {honor}".format(honor=honor)) - conf.install() - assert env.apache_restart() == 0 - - @pytest.mark.parametrize("cipher", [ - "default", - "TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:" - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - """TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 \\ - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\\ - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256""" - ]) - def test_tls_02_conf_cipher_valid(self, env, cipher): - conf = TlsTestConf(env=env) - conf.add("TLSCiphersPrefer {cipher}".format(cipher=cipher)) - conf.install() - assert env.apache_restart() == 0 - - @pytest.mark.parametrize("cipher", [ - "wrong", - "YOLO", - "TLS_NULL_WITH_NULL_NULLX", # not supported - "TLS_DHE_RSA_WITH_AES128_GCM_SHA256", # not supported - ]) - def test_tls_02_conf_cipher_wrong(self, env, cipher): - conf = TlsTestConf(env=env) - conf.add("TLSCiphersPrefer {cipher}".format(cipher=cipher)) - conf.install() - assert env.apache_fail() == 0 diff --git a/test/modules/tls/test_03_sni.py b/test/modules/tls/test_03_sni.py deleted file mode 100644 index cbd142afbc..0000000000 --- a/test/modules/tls/test_03_sni.py +++ /dev/null @@ -1,89 +0,0 @@ -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv - - -class TestSni: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - pass - - def test_tls_03_sni_get_a(self, env): - # do we see the correct json for the domain_a? - data = env.tls_get_json(env.domain_a, "/index.json") - assert data == {'domain': env.domain_a} - - def test_tls_03_sni_get_b(self, env): - # do we see the correct json for the domain_a? - data = env.tls_get_json(env.domain_b, "/index.json") - assert data == {'domain': env.domain_b} - - def test_tls_03_sni_unknown(self, env): - # connection will be denied as cert does not cover this domain - domain_unknown = "unknown.test" - r = env.tls_get(domain_unknown, "/index.json") - assert r.exit_code != 0 - # - env.httpd_error_log.ignore_recent( - lognos = [ - "AH10353" # cannot decrypt peer's message - ] - ) - - def test_tls_03_sni_request_other_same_config(self, env): - # do we see the first vhost response for another domain with different certs? - r = env.tls_get(env.domain_a, "/index.json", options=[ - "-vvvv", "--header", "Host: {0}".format(env.domain_b) - ]) - # request is marked as misdirected - assert r.exit_code == 0 - assert r.json is None - assert r.response['status'] == 421 - # - env.httpd_error_log.ignore_recent( - lognos = [ - "AH10345" # Connection host selected via SNI and request have incompatible TLS configurations - ] - ) - - def test_tls_03_sni_request_other_other_honor(self, env): - # do we see the first vhost response for an unknown domain? - conf = TlsTestConf(env=env, extras={ - env.domain_a: "TLSProtocol TLSv1.2+", - env.domain_b: "TLSProtocol TLSv1.3+" - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - r = env.tls_get(env.domain_a, "/index.json", options=[ - "-vvvv", "--tls-max", "1.2", "--header", "Host: {0}".format(env.domain_b) - ]) - # request denied - assert r.exit_code == 0 - assert r.json is None - # - env.httpd_error_log.ignore_recent( - lognos = [ - "AH10345" # Connection host selected via SNI and request have incompatible TLS configurations - ] - ) - - @pytest.mark.skip('openssl behaviour changed on ventura, unreliable') - def test_tls_03_sni_bad_hostname(self, env): - # curl checks hostnames we give it, but the openssl client - # does not. Good for us, since we need to test it. - r = env.openssl(["s_client", "-connect", - "localhost:{0}".format(env.https_port), - "-servername", b'x\x2f.y'.decode()]) - assert r.exit_code == 1, r.stderr diff --git a/test/modules/tls/test_04_get.py b/test/modules/tls/test_04_get.py deleted file mode 100644 index 6944381307..0000000000 --- a/test/modules/tls/test_04_get.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -import time -from datetime import timedelta - -import pytest - -from .env import TlsTestEnv -from .conf import TlsTestConf - - -def mk_text_file(fpath: str, lines: int): - t110 = 11 * "0123456789" - with open(fpath, "w") as fd: - for i in range(lines): - fd.write("{0:015d}: ".format(i)) # total 128 bytes per line - fd.write(t110) - fd.write("\n") - - -class TestGet: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - docs_a = os.path.join(env.server_docs_dir, env.domain_a) - mk_text_file(os.path.join(docs_a, "1k.txt"), 8) - mk_text_file(os.path.join(docs_a, "10k.txt"), 80) - mk_text_file(os.path.join(docs_a, "100k.txt"), 800) - mk_text_file(os.path.join(docs_a, "1m.txt"), 8000) - mk_text_file(os.path.join(docs_a, "10m.txt"), 80000) - assert env.apache_restart() == 0 - - @pytest.mark.parametrize("fname, flen", [ - ("1k.txt", 1024), - ("10k.txt", 10*1024), - ("100k.txt", 100 * 1024), - ("1m.txt", 1000 * 1024), - ("10m.txt", 10000 * 1024), - ]) - def test_tls_04_get(self, env, fname, flen): - # do we see the correct json for the domain_a? - docs_a = os.path.join(env.server_docs_dir, env.domain_a) - r = env.tls_get(env.domain_a, "/{0}".format(fname)) - assert r.exit_code == 0 - assert len(r.stdout) == flen - pref = os.path.join(docs_a, fname) - pout = os.path.join(docs_a, "{0}.out".format(fname)) - with open(pout, 'w') as fd: - fd.write(r.stdout) - dr = env.run_diff(pref, pout) - assert dr.exit_code == 0, "differences found:\n{0}".format(dr.stdout) - - @pytest.mark.parametrize("fname, flen", [ - ("1k.txt", 1024), - ]) - def test_tls_04_double_get(self, env, fname, flen): - # we'd like to check that we can do >1 requests on the same connection - # however curl hides that from us, unless we analyze its verbose output - docs_a = os.path.join(env.server_docs_dir, env.domain_a) - r = env.tls_get(env.domain_a, no_stdout_list=True, paths=[ - "/{0}".format(fname), - "/{0}".format(fname) - ]) - assert r.exit_code == 0 - assert len(r.stdout) == 2*flen diff --git a/test/modules/tls/test_05_proto.py b/test/modules/tls/test_05_proto.py deleted file mode 100644 index d874a905ef..0000000000 --- a/test/modules/tls/test_05_proto.py +++ /dev/null @@ -1,64 +0,0 @@ -import time -from datetime import timedelta -import socket -from threading import Thread - -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv - - -class TestProto: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_a: "TLSProtocol TLSv1.3+", - env.domain_b: [ - "# the commonly used name", - "TLSProtocol TLSv1.2+", - "# the numeric one (yes, this is 1.2)", - "TLSProtocol TLSv0x0303+", - ], - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - pass - - def test_tls_05_proto_1_2(self, env): - r = env.tls_get(env.domain_b, "/index.json", options=["--tlsv1.2"]) - assert r.exit_code == 0, r.stderr - - @pytest.mark.skip('curl does not have TLSv1.3 on all platforms') - def test_tls_05_proto_1_3(self, env): - r = env.tls_get(env.domain_a, "/index.json", options=["--tlsv1.3", '-v']) - if True: # testing TlsTestEnv.curl_supports_tls_1_3() is unreliable (curl should support TLS1.3 nowadays..) - assert r.exit_code == 0, f'{r}' - else: - assert r.exit_code == 4, f'{r}' - - def test_tls_05_proto_close(self, env): - s = socket.create_connection(('localhost', env.https_port)) - time.sleep(0.1) - s.close() - - def test_tls_05_proto_ssl_close(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': "LogLevel ssl:debug", - env.domain_a: "SSLProtocol TLSv1.3", - env.domain_b: "SSLProtocol TLSv1.2", - }) - for d in [env.domain_a, env.domain_b]: - conf.add_vhost(domains=[d], port=env.https_port) - conf.install() - assert env.apache_restart() == 0 - s = socket.create_connection(('localhost', env.https_port)) - time.sleep(0.1) - s.close() - - diff --git a/test/modules/tls/test_06_ciphers.py b/test/modules/tls/test_06_ciphers.py deleted file mode 100644 index 4bedd692ce..0000000000 --- a/test/modules/tls/test_06_ciphers.py +++ /dev/null @@ -1,212 +0,0 @@ -import re -from datetime import timedelta - -import pytest - -from .env import TlsTestEnv -from .conf import TlsTestConf - - -class TestCiphers: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': "TLSHonorClientOrder off", - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - pass - - def _get_protocol_cipher(self, output: str): - protocol = None - cipher = None - for line in output.splitlines(): - m = re.match(r'^\s+Protocol\s*:\s*(\S+)$', line) - if m: - protocol = m.group(1) - continue - m = re.match(r'^\s+Cipher\s*:\s*(\S+)$', line) - if m: - cipher = m.group(1) - return protocol, cipher - - def test_tls_06_ciphers_ecdsa(self, env): - ecdsa_1_2 = [c for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'ECDSA'][0] - # client speaks only this cipher, see that it gets it - r = env.openssl_client(env.domain_b, extra_args=[ - "-cipher", ecdsa_1_2.openssl_name, "-tls1_2" - ]) - protocol, cipher = self._get_protocol_cipher(r.stdout) - assert protocol == "TLSv1.2", r.stdout - assert cipher == ecdsa_1_2.openssl_name, r.stdout - - def test_tls_06_ciphers_rsa(self, env): - rsa_1_2 = [c for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'RSA'][0] - # client speaks only this cipher, see that it gets it - r = env.openssl_client(env.domain_b, extra_args=[ - "-cipher", rsa_1_2.openssl_name, "-tls1_2" - ]) - protocol, cipher = self._get_protocol_cipher(r.stdout) - assert protocol == "TLSv1.2", r.stdout - assert cipher == rsa_1_2.openssl_name, r.stdout - - @pytest.mark.parametrize("cipher", [ - c for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'ECDSA' - ], ids=[ - c.name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'ECDSA' - ]) - def test_tls_06_ciphers_server_prefer_ecdsa(self, env, cipher): - # Select a ECSDA ciphers as preference and suppress all RSA ciphers. - # The last is not strictly necessary since rustls prefers ECSDA anyway - suppress_names = [c.name for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'RSA'] - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSHonorClientOrder off", - f"TLSCiphersPrefer {cipher.name}", - f"TLSCiphersSuppress {':'.join(suppress_names)}", - ] - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - r = env.openssl_client(env.domain_b, extra_args=["-tls1_2"]) - client_proto, client_cipher = self._get_protocol_cipher(r.stdout) - assert client_proto == "TLSv1.2", r.stdout - assert client_cipher == cipher.openssl_name, r.stdout - - @pytest.mark.skip(reason="Wrong certified key selected by rustls") - # see <https://github.com/rustls/rustls-ffi/issues/236> - @pytest.mark.parametrize("cipher", [ - c for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ], ids=[ - c.name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ]) - def test_tls_06_ciphers_server_prefer_rsa(self, env, cipher): - # Select a RSA ciphers as preference and suppress all ECDSA ciphers. - # The last is necessary since rustls prefers ECSDA and openssl leaks that it can. - suppress_names = [c.name for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'ECDSA'] - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSHonorClientOrder off", - f"TLSCiphersPrefer {cipher.name}", - f"TLSCiphersSuppress {':'.join(suppress_names)}", - ] - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - r = env.openssl_client(env.domain_b, extra_args=["-tls1_2"]) - client_proto, client_cipher = self._get_protocol_cipher(r.stdout) - assert client_proto == "TLSv1.2", r.stdout - assert client_cipher == cipher.openssl_name, r.stdout - - @pytest.mark.skip(reason="Wrong certified key selected by rustls") - # see <https://github.com/rustls/rustls-ffi/issues/236> - @pytest.mark.parametrize("cipher", [ - c for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ], ids=[ - c.openssl_name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ]) - def test_tls_06_ciphers_server_prefer_rsa_alias(self, env, cipher): - # same as above, but using openssl names for ciphers - suppress_names = [c.openssl_name for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'ECDSA'] - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSHonorClientOrder off", - f"TLSCiphersPrefer {cipher.openssl_name}", - f"TLSCiphersSuppress {':'.join(suppress_names)}", - ] - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - r = env.openssl_client(env.domain_b, extra_args=["-tls1_2"]) - client_proto, client_cipher = self._get_protocol_cipher(r.stdout) - assert client_proto == "TLSv1.2", r.stdout - assert client_cipher == cipher.openssl_name, r.stdout - - @pytest.mark.skip(reason="Wrong certified key selected by rustls") - # see <https://github.com/rustls/rustls-ffi/issues/236> - @pytest.mark.parametrize("cipher", [ - c for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ], ids=[ - c.id_name for c in TlsTestEnv.RUSTLS_CIPHERS if c.max_version == 1.2 and c.flavour == 'RSA' - ]) - def test_tls_06_ciphers_server_prefer_rsa_id(self, env, cipher): - # same as above, but using openssl names for ciphers - suppress_names = [c.id_name for c in env.RUSTLS_CIPHERS - if c.max_version == 1.2 and c.flavour == 'ECDSA'] - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSHonorClientOrder off", - f"TLSCiphersPrefer {cipher.id_name}", - f"TLSCiphersSuppress {':'.join(suppress_names)}", - ] - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - r = env.openssl_client(env.domain_b, extra_args=["-tls1_2"]) - client_proto, client_cipher = self._get_protocol_cipher(r.stdout) - assert client_proto == "TLSv1.2", r.stdout - assert client_cipher == cipher.openssl_name, r.stdout - - def test_tls_06_ciphers_pref_unknown(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_b: "TLSCiphersPrefer TLS_MY_SUPER_CIPHER:SSL_WHAT_NOT" - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() != 0 - # get a working config again, so that subsequent test cases do not stumble - conf = TlsTestConf(env=env) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - env.apache_restart() - - def test_tls_06_ciphers_pref_unsupported(self, env): - # a warning on preferring a known, but not supported cipher - conf = TlsTestConf(env=env, extras={ - env.domain_b: "TLSCiphersPrefer TLS_NULL_WITH_NULL_NULL" - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - 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 = [ - "AH10319" # Server has TLSCiphersPrefer configured that are not supported by rustls - ] - ) - - def test_tls_06_ciphers_supp_unknown(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_b: "TLSCiphersSuppress TLS_MY_SUPER_CIPHER:SSL_WHAT_NOT" - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() != 0 - - def test_tls_06_ciphers_supp_unsupported(self, env): - # no warnings on suppressing known, but not supported ciphers - conf = TlsTestConf(env=env, extras={ - env.domain_b: "TLSCiphersSuppress TLS_NULL_WITH_NULL_NULL" - }) - 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 diff --git a/test/modules/tls/test_07_alpn.py b/test/modules/tls/test_07_alpn.py deleted file mode 100644 index aa7e1b844c..0000000000 --- a/test/modules/tls/test_07_alpn.py +++ /dev/null @@ -1,45 +0,0 @@ -import re -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv - - -@pytest.mark.skipif(condition=TlsTestEnv.is_unsupported, reason="h2 not supported here") -class TestAlpn: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_b: "Protocols h2 http/1.1" - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - pass - - def _get_protocol(self, output: str): - for line in output.splitlines(): - m = re.match(r'^\*\s+ALPN[:,] server accepted (to use\s+)?(.*)$', line) - if m: - return m.group(2) - return None - - def test_tls_07_alpn_get_a(self, env): - # do we see the correct json for the domain_a? - r = env.tls_get(env.domain_a, "/index.json", options=["-vvvvvv", "--http1.1"]) - assert r.exit_code == 0, r.stderr - protocol = self._get_protocol(r.stderr) - assert protocol == "http/1.1", r.stderr - - def test_tls_07_alpn_get_b(self, env): - # do we see the correct json for the domain_a? - r = env.tls_get(env.domain_b, "/index.json", options=["-vvvvvv"]) - assert r.exit_code == 0, r.stderr - protocol = self._get_protocol(r.stderr) - assert protocol == "h2", r.stderr diff --git a/test/modules/tls/test_08_vars.py b/test/modules/tls/test_08_vars.py deleted file mode 100644 index 0e3ee74d2d..0000000000 --- a/test/modules/tls/test_08_vars.py +++ /dev/null @@ -1,75 +0,0 @@ -import re - -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv - - -class TestVars: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': [ - "TLSHonorClientOrder off", - "TLSOptions +StdEnvVars", - ] - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_08_vars_root(self, env): - # in domain_b root, the StdEnvVars is switch on - exp_proto = "TLSv1.2" - 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 - assert r.json == { - 'https': 'on', - 'host': 'b.mod-tls.test', - 'protocol': 'HTTP/1.1', - 'ssl_protocol': exp_proto, - # this will vary by client potentially - 'ssl_cipher': exp_cipher, - } - - @pytest.mark.parametrize("name, value", [ - ("SERVER_NAME", "b.mod-tls.test"), - ("SSL_SESSION_RESUMED", "Initial"), - ("SSL_SECURE_RENEG", "false"), - ("SSL_COMPRESS_METHOD", "NULL"), - ("SSL_CIPHER_EXPORT", "false"), - ("SSL_CLIENT_VERIFY", "NONE"), - ]) - 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 - 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+'), - ("SSL_VERSION_LIBRARY", r'rustls-ffi/\d+\.\d+\.\d+/rustls/\d+\.\d+(\.\d+)?'), - ]) - def test_tls_08_vars_match(self, env, name: str, pattern: str): - r = env.tls_get(env.domain_b, f"/vars.py?name={name}") - assert r.exit_code == 0, r.stderr - assert name in 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 diff --git a/test/modules/tls/test_09_timeout.py b/test/modules/tls/test_09_timeout.py deleted file mode 100644 index 70cc89417a..0000000000 --- a/test/modules/tls/test_09_timeout.py +++ /dev/null @@ -1,43 +0,0 @@ -import socket -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf - - -class TestTimeout: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': "RequestReadTimeout handshake=1", - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - pass - - def test_tls_09_timeout_handshake(self, env): - # in domain_b root, the StdEnvVars is switch on - s = socket.create_connection(('localhost', env.https_port)) - s.send(b'1234') - s.settimeout(0.0) - try: - s.recv(1024) - assert False, "able to recv() on a TLS connection before we sent a hello" - except BlockingIOError: - pass - s.settimeout(3.0) - try: - while True: - buf = s.recv(1024) - if not buf: - break - print("recv() -> {0}".format(buf)) - except (socket.timeout, BlockingIOError): - assert False, "socket not closed as handshake timeout should trigger" - s.close() diff --git a/test/modules/tls/test_10_session_id.py b/test/modules/tls/test_10_session_id.py deleted file mode 100644 index 848bc1a556..0000000000 --- a/test/modules/tls/test_10_session_id.py +++ /dev/null @@ -1,50 +0,0 @@ -import re -from typing import List - -import pytest - -from pyhttpd.result import ExecResult -from .env import TlsTestEnv -from .conf import TlsTestConf - - -class TestSessionID: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def find_openssl_session_ids(self, r: ExecResult) -> List[str]: - ids = [] - for line in r.stdout.splitlines(): - m = re.match(r'^\s*Session-ID: (\S+)$', line) - if m: - ids.append(m.group(1)) - return ids - - def test_tls_10_session_id_12(self, env): - r = env.openssl_client(env.domain_b, extra_args=[ - "-reconnect", "-tls1_2" - ]) - session_ids = self.find_openssl_session_ids(r) - assert 1 < len(session_ids), "expected several session-ids: {0}, stderr={1}".format( - session_ids, r.stderr - ) - assert 1 == len(set(session_ids)), "sesion-ids should all be the same: {0}".format(session_ids) - - @pytest.mark.skipif(True or not TlsTestEnv.openssl_supports_tls_1_3(), - reason="openssl TLSv1.3 session storage test incomplete") - def test_tls_10_session_id_13(self, env): - r = env.openssl_client(env.domain_b, extra_args=[ - "-reconnect", "-tls1_3" - ]) - # openssl -reconnect closes connection immediately after the handhshake, so - # the Session data in TLSv1.3 is not seen and not found in its output. - # FIXME: how to check session data with TLSv1.3? - session_ids = self.find_openssl_session_ids(r) - assert 0 == len(session_ids), "expected no session-ids: {0}, stderr={1}".format( - session_ids, r.stdout - ) diff --git a/test/modules/tls/test_11_md.py b/test/modules/tls/test_11_md.py deleted file mode 100644 index 9d733db9d1..0000000000 --- a/test/modules/tls/test_11_md.py +++ /dev/null @@ -1,37 +0,0 @@ -import time -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf - - -class TestMD: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': "LogLevel md:trace4" - }) - conf.add_md_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_11_get_a(self, env): - # do we see the correct json for the domain_a? - data = env.tls_get_json(env.domain_a, "/index.json") - assert data == {'domain': env.domain_a} - - def test_tls_11_get_b(self, env): - # do we see the correct json for the domain_a? - data = env.tls_get_json(env.domain_b, "/index.json") - assert data == {'domain': env.domain_b} - - def test_tls_11_get_base(self, env): - # give the base server domain_a and lookup its index.json - conf = TlsTestConf(env=env) - conf.add_md_base(domain=env.domain_a) - conf.install() - assert env.apache_restart() == 0 - data = env.tls_get_json(env.domain_a, "/index.json") - assert data == {'domain': 'localhost'} diff --git a/test/modules/tls/test_12_cauth.py b/test/modules/tls/test_12_cauth.py deleted file mode 100644 index 14116091c6..0000000000 --- a/test/modules/tls/test_12_cauth.py +++ /dev/null @@ -1,235 +0,0 @@ -import os -from datetime import timedelta -from typing import Optional - -import pytest - -from pyhttpd.certs import Credentials -from .conf import TlsTestConf - - -@pytest.fixture -def clients_x(env): - return env.ca.get_first("clientsX") - - -@pytest.fixture -def clients_y(env): - return env.ca.get_first("clientsY") - - -@pytest.fixture -def cax_file(clients_x): - return os.path.join(os.path.dirname(clients_x.cert_file), "clientX-ca.pem") - - -@pytest.mark.skip(reason="client certs disabled") -class TestTLS: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env, clients_x, cax_file): - with open(cax_file, 'w') as fd: - fd.write("".join(open(clients_x.cert_file).readlines())) - fd.write("".join(open(env.ca.cert_file).readlines())) - - @pytest.fixture(autouse=True, scope='function') - def _function_scope(self, env): - if env.is_live(timeout=timedelta(milliseconds=100)): - assert env.apache_stop() == 0 - - def get_ssl_var(self, env, domain: str, cert: Optional[Credentials], name: str): - r = env.tls_get(domain, f"/vars.py?name={name}", options=[ - "--cert", cert.cert_file - ] if cert else []) - assert r.exit_code == 0, r.stderr - assert r.json, r.stderr + r.stdout - return r.json[name] if name in r.json else None - - def test_tls_12_set_ca_non_existing(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_a: "TLSClientCA xxx" - }) - conf.add_md_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 1 - - def test_tls_12_set_ca_existing(self, env, cax_file): - conf = TlsTestConf(env=env, extras={ - env.domain_a: f"TLSClientCA {cax_file}" - }) - conf.add_md_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_12_set_auth_no_ca(self, env): - conf = TlsTestConf(env=env, extras={ - env.domain_a: "TLSClientCertificate required" - }) - conf.add_md_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - # will fail bc lacking clien CA - assert env.apache_restart() == 1 - - def test_tls_12_auth_option_std(self, env, cax_file, clients_x): - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - f"TLSClientCertificate required", - f"TLSClientCA {cax_file}", - "# TODO: TLSUserName SSL_CLIENT_S_DN_CN", - "TLSOptions +StdEnvVars", - ] - }) - conf.add_md_vhosts(domains=[env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - # should be denied - r = env.tls_get(domain=env.domain_b, paths="/index.json") - assert r.exit_code != 0, r.stdout - # should work - ccert = clients_x.get_first("user1") - data = env.tls_get_json(env.domain_b, "/index.json", options=[ - "--cert", ccert.cert_file - ]) - assert data == {'domain': env.domain_b} - r = env.tls_get(env.domain_b, "/vars.py?name=SSL_CLIENT_S_DN_CN") - assert r.exit_code != 0, "should have been prevented" - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_S_DN_CN") - assert val == 'Not Implemented' - # TODO - # val = self.get_ssl_var(env, env.domain_b, ccert, "REMOTE_USER") - # assert val == 'Not Implemented' - # not set on StdEnvVars, needs option ExportCertData - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CERT") - assert val == "" - - def test_tls_12_auth_option_cert(self, env, test_ca, cax_file, clients_x): - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSClientCertificate required", - f"TLSClientCA {cax_file}", - "TLSOptions Defaults +ExportCertData", - ] - }) - conf.add_md_vhosts(domains=[env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - ccert = clients_x.get_first("user1") - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CERT") - assert val == ccert.cert_pem.decode() - # no chain should be present - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CHAIN_0") - assert val == '' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_SERVER_CERT") - assert val - server_certs = test_ca.get_credentials_for_name(env.domain_b) - assert val in [c.cert_pem.decode() for c in server_certs] - - def test_tls_12_auth_ssl_optional(self, env, cax_file, clients_x): - domain = env.domain_b - conf = TlsTestConf(env=env, extras={ - domain: [ - "SSLVerifyClient optional", - "SSLVerifyDepth 2", - "SSLOptions +StdEnvVars +ExportCertData", - f"SSLCACertificateFile {cax_file}", - "SSLUserName SSL_CLIENT_S_DN", - ] - }) - conf.add_ssl_vhosts(domains=[domain]) - conf.install() - assert env.apache_restart() == 0 - # should work either way - data = env.tls_get_json(domain, "/index.json") - assert data == {'domain': domain} - # no client cert given, we expect the server variable to be empty - val = self.get_ssl_var(env, env.domain_b, None, "SSL_CLIENT_S_DN_CN") - assert val == '' - ccert = clients_x.get_first("user1") - data = env.tls_get_json(domain, "/index.json", options=[ - "--cert", ccert.cert_file - ]) - assert data == {'domain': domain} - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_S_DN_CN") - assert val == 'user1' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_S_DN") - assert val == 'O=abetterinternet-mod_tls,OU=clientsX,CN=user1' - val = self.get_ssl_var(env, env.domain_b, ccert, "REMOTE_USER") - assert val == 'O=abetterinternet-mod_tls,OU=clientsX,CN=user1' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_I_DN") - assert val == 'O=abetterinternet-mod_tls,OU=clientsX' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_I_DN_CN") - assert val == '' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_I_DN_OU") - assert val == 'clientsX' - val = self.get_ssl_var(env, env.domain_b, ccert, "SSL_CLIENT_CERT") - assert val == ccert.cert_pem.decode() - - def test_tls_12_auth_optional(self, env, cax_file, clients_x): - domain = env.domain_b - conf = TlsTestConf(env=env, extras={ - domain: [ - "TLSClientCertificate optional", - f"TLSClientCA {cax_file}", - ] - }) - conf.add_md_vhosts(domains=[domain]) - conf.install() - assert env.apache_restart() == 0 - # should work either way - data = env.tls_get_json(domain, "/index.json") - assert data == {'domain': domain} - # no client cert given, we expect the server variable to be empty - r = env.tls_get(domain, "/vars.py?name=SSL_CLIENT_S_DN_CN") - assert r.exit_code == 0, r.stderr - assert r.json == { - 'SSL_CLIENT_S_DN_CN': '', - }, r.stdout - data = env.tls_get_json(domain, "/index.json", options=[ - "--cert", clients_x.get_first("user1").cert_file - ]) - assert data == {'domain': domain} - r = env.tls_get(domain, "/vars.py?name=SSL_CLIENT_S_DN_CN", options=[ - "--cert", clients_x.get_first("user1").cert_file - ]) - # with client cert, we expect the server variable to show? Do we? - assert r.exit_code == 0, r.stderr - assert r.json == { - 'SSL_CLIENT_S_DN_CN': 'Not Implemented', - }, r.stdout - - def test_tls_12_auth_expired(self, env, cax_file, clients_x): - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSClientCertificate required", - f"TLSClientCA {cax_file}", - ] - }) - conf.add_md_vhosts(domains=[env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - # should not work - r = env.tls_get(domain=env.domain_b, paths="/index.json", options=[ - "--cert", clients_x.get_first("user_expired").cert_file - ]) - assert r.exit_code != 0 - - def test_tls_12_auth_other_ca(self, env, cax_file, clients_y): - conf = TlsTestConf(env=env, extras={ - env.domain_b: [ - "TLSClientCertificate required", - f"TLSClientCA {cax_file}", - ] - }) - conf.add_md_vhosts(domains=[env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - # should not work - r = env.tls_get(domain=env.domain_b, paths="/index.json", options=[ - "--cert", clients_y.get_first("user1").cert_file - ]) - assert r.exit_code != 0 - # This will work, as the CA root is present in the CA file - r = env.tls_get(domain=env.domain_b, paths="/index.json", options=[ - "--cert", env.ca.get_first("user1").cert_file - ]) - assert r.exit_code == 0 diff --git a/test/modules/tls/test_13_proxy.py b/test/modules/tls/test_13_proxy.py deleted file mode 100644 index 8bd305f718..0000000000 --- a/test/modules/tls/test_13_proxy.py +++ /dev/null @@ -1,40 +0,0 @@ -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf - - -class TestProxy: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace1", - env.domain_b: [ - "ProxyPreserveHost on", - f'ProxyPass "/proxy/" "http://127.0.0.1:{env.http_port}/"', - f'ProxyPassReverse "/proxy/" "http://{env.domain_b}:{env.http_port}"', - ] - }) - # add vhosts a+b and a ssl proxy from a to b - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_13_proxy_http_get(self, env): - data = env.tls_get_json(env.domain_b, "/proxy/index.json") - assert data == {'domain': env.domain_b} - - @pytest.mark.parametrize("name, value", [ - ("SERVER_NAME", "b.mod-tls.test"), - ("SSL_SESSION_RESUMED", ""), - ("SSL_SECURE_RENEG", ""), - ("SSL_COMPRESS_METHOD", ""), - ("SSL_CIPHER_EXPORT", ""), - ("SSL_CLIENT_VERIFY", ""), - ]) - def test_tls_13_proxy_http_vars(self, env, name: str, value: str): - r = env.tls_get(env.domain_b, f"/proxy/vars.py?name={name}") - assert r.exit_code == 0, r.stderr - assert r.json == {name: value}, r.stdout diff --git a/test/modules/tls/test_14_proxy_ssl.py b/test/modules/tls/test_14_proxy_ssl.py deleted file mode 100644 index 81cb4f31b0..0000000000 --- a/test/modules/tls/test_14_proxy_ssl.py +++ /dev/null @@ -1,125 +0,0 @@ -import re -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv -from pyhttpd.env import HttpdTestEnv - - -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", - f"<Proxy https://127.0.0.1:{env.https_port}/>", - " SSLProxyEngine on", - " SSLProxyVerify require", - f" SSLProxyCACertificateFile {env.ca.cert_file}", - " ProxyPreserveHost on", - "</Proxy>", - f"<Proxy https://localhost:{env.https_port}/>", - " ProxyPreserveHost on", - "</Proxy>", - f"<Proxy h2://127.0.0.1:{env.https_port}/>", - " SSLProxyEngine on", - " SSLProxyVerify require", - f" SSLProxyCACertificateFile {env.ca.cert_file}", - " ProxyPreserveHost on", - "</Proxy>", - ], - env.domain_b: [ - "Protocols h2 http/1.1", - 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}/', - myoptions, - ], - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b], ssl_module=myssl) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_14_proxy_ssl_get(self, env): - data = env.tls_get_json(env.domain_b, "/proxy-ssl/index.json") - assert data == {'domain': env.domain_b} - - def test_tls_14_proxy_ssl_get_local(self, env): - # does not work, since SSLProxy* not configured - data = env.tls_get_json(env.domain_b, "/proxy-local/index.json") - assert data is None - # - env.httpd_error_log.ignore_recent( - lognos = [ - "AH01961", # failed to enable ssl support [Hint: if using mod_ssl, see SSLProxyEngine] - "AH00961" # failed to enable ssl support (mod_proxy) - ] - ) - - @pytest.mark.skipif(condition=TlsTestEnv.is_unsupported, reason="h2 not supported here") - def test_tls_14_proxy_ssl_h2_get(self, env): - r = env.tls_get(env.domain_b, "/proxy-h2-ssl/index.json") - assert r.exit_code == 0 - assert r.json == {'domain': env.domain_b} - - @pytest.mark.parametrize("name, value", [ - ("SERVER_NAME", "b.mod-tls.test"), - ("SSL_SESSION_RESUMED", "Initial"), - ("SSL_SECURE_RENEG", "false"), - ("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 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 - - @pytest.mark.parametrize("name, pattern", [ - ("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_ssl_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 - assert re.match(pattern, r.json[name]), r.json diff --git a/test/modules/tls/test_15_proxy_tls.py b/test/modules/tls/test_15_proxy_tls.py deleted file mode 100644 index 3fe6cfe478..0000000000 --- a/test/modules/tls/test_15_proxy_tls.py +++ /dev/null @@ -1,97 +0,0 @@ -from datetime import timedelta - -import pytest - -from .conf import TlsTestConf -from .env import TlsTestEnv -from pyhttpd.env import HttpdTestEnv - -@pytest.mark.skipif(condition=not HttpdTestEnv.has_shared_module("tls"), reason="no mod_tls available") - -class TestProxyTLS: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - # add vhosts a+b and a ssl proxy from a to b - conf = TlsTestConf(env=env, extras={ - 'base': [ - "LogLevel proxy:trace1 proxy_http:trace1 proxy_http2:trace2 http2:trace2 cgid:trace4", - "TLSProxyProtocol TLSv1.3+", - f"<Proxy https://127.0.0.1:{env.https_port}/>", - " TLSProxyEngine on", - f" TLSProxyCA {env.ca.cert_file}", - " TLSProxyProtocol TLSv1.2+", - " TLSProxyCiphersPrefer TLS13_AES_256_GCM_SHA384", - " TLSProxyCiphersSuppress TLS13_AES_128_GCM_SHA256", - " ProxyPreserveHost on", - "</Proxy>", - f"<Proxy https://localhost:{env.https_port}/>", - " ProxyPreserveHost on", - "</Proxy>", - f"<Proxy h2://127.0.0.1:{env.https_port}/>", - " TLSProxyEngine on", - f" TLSProxyCA {env.ca.cert_file}", - " TLSProxyCiphersSuppress TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256", - " ProxyPreserveHost on", - "</Proxy>", - ], - env.domain_b: [ - "Protocols h2 http/1.1", - f"ProxyPass /proxy-tls/ https://127.0.0.1:{env.https_port}/", - f"ProxyPass /proxy-local/ https://localhost:{env.https_port}/", - f"ProxyPass /proxy-h2-tls/ h2://127.0.0.1:{env.https_port}/", - "TLSOptions +StdEnvVars", - ], - }) - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_15_proxy_tls_get(self, env): - data = env.tls_get_json(env.domain_b, "/proxy-tls/index.json") - assert data == {'domain': env.domain_b} - - def test_tls_15_proxy_tls_get_local(self, env): - # does not work, since SSLProxy* not configured - data = env.tls_get_json(env.domain_b, "/proxy-local/index.json") - assert data is None - # - env.httpd_error_log.ignore_recent( - lognos = [ - "AH01961", # failed to enable ssl support [Hint: if using mod_ssl, see SSLProxyEngine] - "AH00961" # failed to enable ssl support (mod_proxy) - ] - ) - - @pytest.mark.skipif(condition=TlsTestEnv.is_unsupported, reason="h2 not supported here") - def test_tls_15_proxy_tls_h2_get(self, env): - r = env.tls_get(env.domain_b, "/proxy-h2-tls/index.json") - assert r.exit_code == 0 - assert r.json == {'domain': env.domain_b}, f"{r.stdout}" - - @pytest.mark.parametrize("name, value", [ - ("SERVER_NAME", "b.mod-tls.test"), - ("SSL_PROTOCOL", "TLSv1.3"), - ("SSL_CIPHER", "TLS_AES_256_GCM_SHA384"), - ("SSL_SESSION_RESUMED", "Initial"), - ("SSL_SECURE_RENEG", "false"), - ("SSL_COMPRESS_METHOD", "NULL"), - ("SSL_CIPHER_EXPORT", "false"), - ("SSL_CLIENT_VERIFY", "NONE"), - ]) - def test_tls_15_proxy_tls_h1_vars(self, env, name: str, value: str): - r = env.tls_get(env.domain_b, f"/proxy-tls/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_PROTOCOL", "TLSv1.3"), - ("SSL_CIPHER", "TLS_CHACHA20_POLY1305_SHA256"), - ("SSL_SESSION_RESUMED", "Initial"), - ]) - @pytest.mark.skipif(condition=TlsTestEnv.is_unsupported, reason="h2 not supported here") - def test_tls_15_proxy_tls_h2_vars(self, env, name: str, value: str): - r = env.tls_get(env.domain_b, f"/proxy-h2-tls/vars.py?name={name}") - assert r.exit_code == 0, r.stderr - assert r.json == {name: value}, r.stdout diff --git a/test/modules/tls/test_16_proxy_mixed.py b/test/modules/tls/test_16_proxy_mixed.py deleted file mode 100644 index 88b351fd94..0000000000 --- a/test/modules/tls/test_16_proxy_mixed.py +++ /dev/null @@ -1,50 +0,0 @@ -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: - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(self, env): - conf = TlsTestConf(env=env, extras={ - 'base': [ - "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace1 proxy_http2:trace1 http2:debug", - "ProxyPreserveHost on", - ], - env.domain_a: [ - "Protocols h2 http/1.1", - "TLSProxyEngine on", - f"TLSProxyCA {env.ca.cert_file}", - "<Location /proxy-tls/>", - f" ProxyPass h2://127.0.0.1:{env.https_port}/", - "</Location>", - ], - env.domain_b: [ - "SSLProxyEngine on", - "SSLProxyVerify require", - f"SSLProxyCACertificateFile {env.ca.cert_file}", - "<Location /proxy-ssl/>", - f" ProxyPass https://127.0.0.1:{env.https_port}/", - "</Location>", - ], - }) - # add vhosts a+b and a ssl proxy from a to b - conf.add_tls_vhosts(domains=[env.domain_a, env.domain_b]) - conf.install() - assert env.apache_restart() == 0 - - def test_tls_16_proxy_mixed_ssl_get(self, env, repeat): - data = env.tls_get_json(env.domain_b, "/proxy-ssl/index.json") - assert data == {'domain': env.domain_b} - - def test_tls_16_proxy_mixed_tls_get(self, env, repeat): - data = env.tls_get_json(env.domain_a, "/proxy-tls/index.json") - if data is None: - time.sleep(300) - assert data == {'domain': env.domain_a} diff --git a/test/modules/tls/test_17_proxy_machine_cert.py b/test/modules/tls/test_17_proxy_machine_cert.py deleted file mode 100644 index a5410d63ad..0000000000 --- a/test/modules/tls/test_17_proxy_machine_cert.py +++ /dev/null @@ -1,70 +0,0 @@ -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') - def clients_x(cls, env): - return env.ca.get_first("clientsX") - - @pytest.fixture(autouse=True, scope='class') - def clients_y(cls, env): - return env.ca.get_first("clientsY") - - @pytest.fixture(autouse=True, scope='class') - def cax_file(cls, clients_x): - return os.path.join(os.path.dirname(clients_x.cert_file), "clientsX-ca.pem") - - @pytest.fixture(autouse=True, scope='class') - def _class_scope(cls, env, cax_file, clients_x): - # add vhosts a(tls)+b(ssl, port2) and a ssl proxy from a to b with a machine cert - # host b requires a client certificate - conf = TlsTestConf(env=env, extras={ - 'base': [ - "LogLevel proxy:trace1 proxy_http:trace1 ssl:trace4 proxy_http2:trace1", - "ProxyPreserveHost on", - f"Listen {env.proxy_port}", - ], - }) - conf.start_tls_vhost(domains=[env.domain_a], port=env.https_port) - conf.add([ - "Protocols h2 http/1.1", - "TLSProxyEngine on", - f"TLSProxyCA {env.ca.cert_file}", - f"TLSProxyMachineCertificate {clients_x.get_first('user1').cert_file}", - "<Location /proxy-tls/>", - f" ProxyPass https://127.0.0.1:{env.proxy_port}/", - "</Location>", - ]) - conf.end_tls_vhost() - conf.start_vhost(domains=[env.domain_a], port=env.proxy_port, - doc_root=f"htdocs/{env.domain_a}", with_ssl=True) - conf.add([ - "SSLVerifyClient require", - "SSLVerifyDepth 2", - "SSLOptions +StdEnvVars +ExportCertData", - f"SSLCACertificateFile {cax_file}", - "SSLUserName SSL_CLIENT_S_DN_CN" - ]) - conf.end_vhost() - conf.install() - assert env.apache_restart() == 0 - - def test_tls_17_proxy_machine_cert_get_a(self, env): - data = env.tls_get_json(env.domain_a, "/proxy-tls/index.json") - assert data == {'domain': env.domain_a} - - @pytest.mark.parametrize("name, value", [ - ("SERVER_NAME", "a.mod-tls.test"), - ("SSL_CLIENT_VERIFY", "SUCCESS"), - ("REMOTE_USER", "user1"), - ]) - def test_tls_17_proxy_machine_cert_vars(self, env, name: str, value: str): - r = env.tls_get(env.domain_a, f"/proxy-tls/vars.py?name={name}") - assert r.exit_code == 0, r.stderr - assert r.json == {name: value}, r.stdout diff --git a/test/travis_run_linux.sh b/test/travis_run_linux.sh index 7f99b23415..1e0a5b2031 100755 --- a/test/travis_run_linux.sh +++ b/test/travis_run_linux.sh @@ -282,14 +282,6 @@ if test -v TEST_MD -a $RV -eq 0; then RV=$? fi -if test -v TEST_MOD_TLS -a $RV -eq 0; then - # Run mod_tls tests. The underlying librustls was build - # and installed before we configured the server (see top of file). - # This will be replaced once librustls is available as a package. - py.test-3 test/modules/tls - RV=$? -fi - # Catch cases where abort()s get logged to stderr by libraries but # only cause child processes to terminate e.g. during shutdown, # which may not otherwise trigger test failures. |