import re
import pytest

from .env import H2Conf, H2TestEnv


@pytest.mark.skipif(condition=H2TestEnv.is_unsupported, reason="mod_http2 not supported here")
@pytest.mark.skipif(H2TestEnv.get_ssl_module() != "mod_ssl", reason="only for mod_ssl")
class TestSslRenegotiation:

    @pytest.fixture(autouse=True, scope='class')
    def _class_scope(self, env):
        domain = f"ssl.{env.http_tld}"
        conf = H2Conf(env, extras={
            'base': [
                "SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384",
                f"<Directory \"{env.server_dir}/htdocs/ssl-client-verify\">",
                "    Require all granted",
                "    SSLVerifyClient require",
                "    SSLVerifyDepth 0",
                "</Directory>"
            ],
            domain: [
                "Protocols h2 http/1.1",
                "<Location /renegotiate/cipher>",
                "    SSLCipherSuite ECDHE-RSA-CHACHA20-POLY1305",
                "</Location>",
                "<Location /renegotiate/err-doc-cipher>",
                "    SSLCipherSuite ECDHE-RSA-CHACHA20-POLY1305",
                "    ErrorDocument 403 /forbidden.html",
                "</Location>",
                "<Location /renegotiate/verify>",
                "    SSLVerifyClient require",
                "</Location>",
                f"<Directory \"{env.server_dir}/htdocs/sslrequire\">",
                "    SSLRequireSSL",
                "</Directory>",
                f"<Directory \"{env.server_dir}/htdocs/requiressl\">",
                "    Require ssl",
                "</Directory>",
        ]})
        conf.add_vhost(domains=[domain], port=env.https_port,
                       doc_root=f"{env.server_dir}/htdocs")
        conf.install()
        # the dir needs to exists for the configuration to have effect
        env.mkpath("%s/htdocs/ssl-client-verify" % env.server_dir)
        env.mkpath("%s/htdocs/renegotiate/cipher" % env.server_dir)
        env.mkpath("%s/htdocs/sslrequire" % env.server_dir)
        env.mkpath("%s/htdocs/requiressl" % env.server_dir)
        assert env.apache_restart() == 0

    # access a resource with SSL renegotiation, using HTTP/1.1
    def test_h2_101_01(self, env):
        url = env.mkurl("https", "ssl", "/renegotiate/cipher/")
        r = env.curl_get(url, options=["-v", "--http1.1", "--tlsv1.2", "--tls-max", "1.2"])
        assert 0 == r.exit_code, f"{r}"
        assert r.response
        assert 403 == r.response["status"]
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH01276" # No matching DirectoryIndex found
            ]
        )
        
    # try to renegotiate the cipher, should fail with correct code
    def test_h2_101_02(self, env):
        if not (env.curl_is_at_least('8.2.0') or env.curl_is_less_than('8.1.0')):
            pytest.skip("need curl != 8.1.x version")
        url = env.mkurl("https", "ssl", "/renegotiate/cipher/")
        r = env.curl_get(url, options=[
            "-vvv", "--tlsv1.2", "--tls-max", "1.2", "--ciphers", "ECDHE-RSA-AES256-GCM-SHA384"
        ])
        assert 0 != r.exit_code
        assert not r.response
        assert re.search(r'HTTP_1_1_REQUIRED \(err 13\)', r.stderr)
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02261"   # Re-negotiation handshake failed
            ],
            matches = [
                r'.*:tls_post_process_client_hello:.*',
                r'.*SSL Library Error:.*:SSL routines::no shared cipher.*'
            ]
        )
        
    # try to renegotiate a client certificate from Location 
    # needs to fail with correct code
    def test_h2_101_03(self, env):
        if not (env.curl_is_at_least('8.2.0') or env.curl_is_less_than('8.1.0')):
            pytest.skip("need curl != 8.1.x version")
        url = env.mkurl("https", "ssl", "/renegotiate/verify/")
        r = env.curl_get(url, options=["-vvv", "--tlsv1.2", "--tls-max", "1.2"])
        assert 0 != r.exit_code
        assert not r.response
        assert re.search(r'HTTP_1_1_REQUIRED \(err 13\)', r.stderr)
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02261"   # Re-negotiation handshake failed
            ],
            matches = [
                r'.*:tls_process_client_certificate:.*',
                r'.*SSL Library Error:.*:SSL routines::peer did not return a certificate.*'
            ]
        )
        
    # try to renegotiate a client certificate from Directory 
    # needs to fail with correct code
    def test_h2_101_04(self, env):
        if not (env.curl_is_at_least('8.2.0') or env.curl_is_less_than('8.1.0')):
            pytest.skip("need curl != 8.1.x version")
        url = env.mkurl("https", "ssl", "/ssl-client-verify/index.html")
        r = env.curl_get(url, options=["-vvv", "--tlsv1.2", "--tls-max", "1.2"])
        assert 0 != r.exit_code, f"{r}"
        assert not r.response
        assert re.search(r'HTTP_1_1_REQUIRED \(err 13\)', r.stderr)
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02261"   # Re-negotiation handshake failed
            ],
            matches = [
                r'.*:tls_process_client_certificate:.*',
                r'.*SSL Library Error:.*:SSL routines::peer did not return a certificate.*'
            ]
        )
        
    # make 10 requests on the same connection, none should produce a status code
    # reported by erki@example.ee
    def test_h2_101_05(self, env):
        r = env.run([env.h2load, "-n", "10", "-c", "1", "-m", "1", "-vvvv",
                     f"{env.https_base_url}/ssl-client-verify/index.html"])
        assert 0 == r.exit_code
        r = env.h2load_status(r)
        assert 10 == r.results["h2load"]["requests"]["total"]
        assert 10 == r.results["h2load"]["requests"]["started"]
        assert 10 == r.results["h2load"]["requests"]["done"]
        assert 0 == r.results["h2load"]["requests"]["succeeded"]
        assert 0 == r.results["h2load"]["status"]["2xx"]
        assert 0 == r.results["h2load"]["status"]["3xx"]
        assert 0 == r.results["h2load"]["status"]["4xx"]
        assert 0 == r.results["h2load"]["status"]["5xx"]

    # Check that "SSLRequireSSL" works on h2 connections
    # See <https://bz.apache.org/bugzilla/show_bug.cgi?id=62654>
    def test_h2_101_10a(self, env):
        url = env.mkurl("https", "ssl", "/sslrequire/index.html")
        r = env.curl_get(url)
        assert 0 == r.exit_code
        assert r.response
        assert 404 == r.response["status"]

    # Check that "require ssl" works on h2 connections
    # See <https://bz.apache.org/bugzilla/show_bug.cgi?id=62654>
    def test_h2_101_10b(self, env):
        url = env.mkurl("https", "ssl", "/requiressl/index.html")
        r = env.curl_get(url)
        assert 0 == r.exit_code
        assert r.response
        assert 404 == r.response["status"]
        
    # Check that status works with ErrorDoc, see pull #174, fixes #172
    def test_h2_101_11(self, env):
        if not (env.curl_is_at_least('8.2.0') or env.curl_is_less_than('8.1.0')):
            pytest.skip("need curl != 8.1.x version")
        url = env.mkurl("https", "ssl", "/renegotiate/err-doc-cipher")
        r = env.curl_get(url, options=[
            "-vvv", "--tlsv1.2", "--tls-max", "1.2", "--ciphers", "ECDHE-RSA-AES256-GCM-SHA384"
        ])
        assert 0 != r.exit_code
        assert not r.response
        assert re.search(r'HTTP_1_1_REQUIRED \(err 13\)', r.stderr)
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02261"   # Re-negotiation handshake failed
            ],
            matches = [
                r'.*:tls_post_process_client_hello:.*',
                r'.*SSL Library Error:.*:SSL routines::no shared cipher.*'
            ]
        )
