Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Apache/test/modules/http2/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 7.6.2025 mit Größe 10 kB image not shown  

Quelle  test_200_header_invalid.py   Sprache: Python

 
import re
import pytest

from .env import H2Conf, H2TestEnv


@pytest.mark.skipif(condition=H2TestEnv.is_unsupported, reason="mod_http2 not supported here")
class TestInvalidHeaders:

    @pytest.fixture(autouse=True, scope='class')
    def _class_scope(self, env):
        H2Conf(env).add_vhost_cgi().install()
        assert env.apache_restart() == 0

    # let the hecho.py CGI echo chars < 0x20 in field name
    # for almost all such characters, the stream returns a 500
    # or in httpd >= 2.5.0 gets aborted with a h2 error
    # cr is handled special
    def test_h2_200_01(self, env):
        url = env.mkurl("https""cgi""/hecho.py")
        for x in range(1, 32):
            data = f'name=x%{x:02x}x&value=yz'
            r = env.curl_post_data(url, data)
            if x in [13]:
                assert 0 == r.exit_code, f'unexpected exit code for char 0x{x:02}'
                assert 200 == r.response["status"], f'unexpected status for char 0x{x:02}'
            elif x in [10] or env.httpd_is_at_least('2.5.0'):
                assert 0 == r.exit_code, f'unexpected exit code for char 0x{x:02}'
                assert 500 == r.response["status"], f'unexpected status for char 0x{x:02}'
            else:
                assert 0 != r.exit_code, f'unexpected exit code for char 0x{x:02}'
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02429"   # Response header name contains invalid characters
            ],
            matches = [
                r'.*malformed header from script \'hecho.py\': Bad header: x.*'
            ]
        )

    # let the hecho.py CGI echo chars < 0x20 in field value
    # for almost all such characters, the stream returns a 500
    # or in httpd >= 2.5.0 gets aborted with a h2 error
    # cr and lf are handled special
    def test_h2_200_02(self, env):
        url = env.mkurl("https""cgi""/hecho.py")
        for x in range(1, 32):
            if 9 != x:
                r = env.curl_post_data(url, "name=x&value=y%%%02x" % x)
                if x in [10, 13]:
                    assert 0 == r.exit_code, "unexpected exit code for char 0x%02x" % x
                    assert 200 == r.response["status"], "unexpected status for char 0x%02x" % x
                elif env.httpd_is_at_least('2.5.0'):
                    assert 0 == r.exit_code, f'unexpected exit code for char 0x{x:02}'
                    assert 500 == r.response["status"], f'unexpected status for char 0x{x:02}'
                else:
                    assert 0 != r.exit_code, "unexpected exit code for char 0x%02x" % x
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02430"   # Response header value contains invalid characters
            ]
        )

    # let the hecho.py CGI echo 0x10 and 0x7f in field name and value
    def test_h2_200_03(self, env):
        url = env.mkurl("https""cgi""/hecho.py")
        for h in ["10""7f"]:
            r = env.curl_post_data(url, "name=x%%%s&value=yz" % h)
            if env.httpd_is_at_least('2.5.0'):
                assert 0 == r.exit_code, f"unexpected exit code for char 0x{h:02}"
                assert 500 == r.response["status"], f"unexpected exit code for char 0x{h:02}"
            else:
                assert 0 != r.exit_code
            r = env.curl_post_data(url, "name=x&value=y%%%sz" % h)
            if env.httpd_is_at_least('2.5.0'):
                assert 0 == r.exit_code, f"unexpected exit code for char 0x{h:02}"
                assert 500 == r.response["status"], f"unexpected exit code for char 0x{h:02}"
            else:
                assert 0 != r.exit_code
        #
        env.httpd_error_log.ignore_recent(
            lognos = [
                "AH02429",  # Response header name contains invalid characters
                "AH02430"   # Response header value contains invalid characters
            ]
        )

    # test header field lengths check, LimitRequestLine
    def test_h2_200_10(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestLine 1024
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        val = 200*"1234567890"
        url = env.mkurl("https""cgi", f'/?{val[:1022]}')
        r = env.curl_get(url)
        assert r.response["status"] == 200
        url = env.mkurl("https""cgi", f'/?{val[:1023]}')
        r = env.curl_get(url)
        # URI too long
        assert 414 == r.response["status"]

    # test header field lengths check, LimitRequestFieldSize (default 8190)
    def test_h2_200_11(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestFieldSize 1024
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        url = env.mkurl("https""cgi""/")
        val = 200*"1234567890"
        # two fields, concatenated with ', '
        # LimitRequestFieldSize, one more char -> 400 in HTTP/1.1
        r = env.curl_get(url, options=[
            '-H', f'x: {val[:500]}''-H', f'x: {val[:519]}'
        ])
        assert r.exit_code == 0, f'{r}'
        assert r.response["status"] == 200, f'{r}'
        r = env.curl_get(url, options=[
            '--http1.1''-H', f'x: {val[:500]}''-H', f'x: {val[:523]}'
        ])
        assert 400 == r.response["status"]
        r = env.curl_get(url, options=[
            '-H', f'x: {val[:500]}''-H', f'x: {val[:520]}'
        ])
        assert 431 == r.response["status"]

    # test header field count, LimitRequestFields (default 100)
    # see #201: several headers with same name are merged and counted
    def test_h2_200_12(self, env):
        url = env.mkurl("https""cgi""/")
        opt = []
        # curl sends 3 headers itself (user-agent, accept, and our AP-Test-Name)
        for i in range(97):
            opt += ["-H""x: 1"]
        r = env.curl_get(url, options=opt)
        assert r.response["status"] == 200
        r = env.curl_get(url, options=(opt + ["-H""y: 2"]))
        assert r.response["status"] == 431

    # test header field count, LimitRequestFields (default 100)
    # different header names count each
    def test_h2_200_13(self, env):
        url = env.mkurl("https""cgi""/")
        opt = []
        # curl sends 3 headers itself (user-agent, accept, and our AP-Test-Name)
        for i in range(97):
            opt += ["-H", f"x{i}: 1"]
        r = env.curl_get(url, options=opt)
        assert r.response["status"] == 200
        r = env.curl_get(url, options=(opt + ["-H""y: 2"]))
        assert 431 == r.response["status"]

    # test "LimitRequestFields 0" setting, see #200
    def test_h2_200_14(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestFields 20
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        url = env.mkurl("https""cgi""/")
        opt = []
        for i in range(21):
            opt += ["-H""x{0}: 1".format(i)]
        r = env.curl_get(url, options=opt)
        assert 431 == r.response["status"]
        conf = H2Conf(env)
        conf.add("""
            LimitRequestFields 0
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        url = env.mkurl("https""cgi""/")
        opt = []
        for i in range(100):
            opt += ["-H""x{0}: 1".format(i)]
        r = env.curl_get(url, options=opt)
        assert r.response["status"] == 200

    # the uri limits
    def test_h2_200_15(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestLine 48
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        url = env.mkurl("https""cgi""/")
        r = env.curl_get(url)
        assert r.response["status"] == 200
        url = env.mkurl("https""cgi""/" + (48*"x"))
        r = env.curl_get(url)
        assert 414 == r.response["status"]
        # nghttp sends the :method: header first (so far)
        # trigger a too long request line on it
        # the stream will RST and we get no response
        url = env.mkurl("https""cgi""/")
        opt = ["-H:method: {0}".format(100*"x")]
        r = env.nghttp().get(url, options=opt)
        assert r.exit_code == 0, r
        assert not r.response

    # invalid chars in method
    def test_h2_200_16(self, env):
        if not env.h2load_is_at_least('1.45.0'):
            pytest.skip(f'nhttp2 version too old')
        conf = H2Conf(env)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        url = env.mkurl("https""cgi""/hello.py")
        opt = ["-H:method: GET /hello.py"]
        r = env.nghttp().get(url, options=opt)
        assert r.exit_code == 0, r
        assert r.response is None
        url = env.mkurl("https""cgi""/proxy/hello.py")
        r = env.nghttp().get(url, options=opt)
        assert r.exit_code == 0, r
        assert r.response is None

    # test few failed headers, should
    def test_h2_200_17(self, env):
        url = env.mkurl("https""cgi""/")

    # test few failed headers, should give response
    def test_h2_200_17(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestFieldSize 20
            LogLevel http2:debug
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        re_emitted = re.compile(r'.* (AH03401: .* shutdown,|'
                                r'AH03066: .* FRAME\[GOAWAY.*) remote.emitted=1')
        url = env.mkurl("https""cgi""/")
        opt = []
        for i in range(10):
            opt += ["-H", f"x{i}: 012345678901234567890123456789"]
        r = env.curl_get(url, options=opt)
        assert r.response
        assert r.response["status"] == 431
        assert env.httpd_error_log.scan_recent(re_emitted)

    # test too many failed headers, should give RST
    def test_h2_200_18(self, env):
        conf = H2Conf(env)
        conf.add("""
            LimitRequestFieldSize 20
            LogLevel http2:debug
            """)
        conf.add_vhost_cgi()
        conf.install()
        assert env.apache_restart() == 0
        re_emitted = re.compile(r'.* (AH03401: .* shutdown,|'
                                r'AH03066: .* FRAME\[GOAWAY.*) remote.emitted=1')
        url = env.mkurl("https""cgi""/")
        opt = []
        for i in range(100):
            opt += ["-H", f"x{i}: 012345678901234567890123456789"]
        r = env.curl_get(url, options=opt)
        assert r.response is None
        assert env.httpd_error_log.scan_recent(re_emitted)

    # test header 10 invalid headers, should trigger stream RST
    def test_h2_200_19(self, env):
        url = env.mkurl("https""cgi""/")
        opt = []
        invalid = '\x7f'
        for i in range(10):
            opt += ["-H", f"x{i}: {invalid}"]
        r = env.curl_get(url, options=opt)
        assert r.response is None

84%


¤ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.