@@ -423,10 +423,10 @@ class TestFilter(object):
423
423
424
424
hdr_validation_combos = [
425
425
h2.utilities.HeaderValidationFlags(
426
- is_client, is_trailer, is_response_header, is_push_promise
426
+ is_client, is_trailer, is_response_header, is_push_promise, is_rfc8441_enabled
427
427
)
428
- for is_client, is_trailer, is_response_header, is_push_promise in (
429
- itertools.product([True, False], repeat=4 )
428
+ for is_client, is_trailer, is_response_header, is_push_promise, is_rfc8441_enabled in (
429
+ itertools.product([True, False], repeat=5 )
430
430
)
431
431
]
432
432
@@ -494,6 +494,68 @@ class TestFilter(object):
494
494
(u':path', u''),
495
495
),
496
496
)
497
+ invalid_connect_request_block_bytes = (
498
+ # First, missing :authority with :protocol header
499
+ (
500
+ (b':method', b'CONNECT'),
501
+ (b':protocol', b'test_value'),
502
+ (b'host', b'example.com'),
503
+ ),
504
+ # Next, missing :authority without :protocol header
505
+ (
506
+ (b':method', b'CONNECT'),
507
+ (b'host', b'example.com'),
508
+ )
509
+ )
510
+ invalid_connect_request_block_unicode = (
511
+ # First, missing :authority with :protocol header
512
+ (
513
+ (u':method', u'CONNECT'),
514
+ (u':protocol', u'websocket'),
515
+ (u'host', u'example.com'),
516
+ ),
517
+ # Next, missing :authority without :protocol header
518
+ (
519
+ (u':method', u'CONNECT'),
520
+ (u'host', u'example.com'),
521
+ ),
522
+ )
523
+ invalid_connect_req_rfc8441_bytes = (
524
+ # First, missing :path header
525
+ (
526
+ (b':authority', b'example.com'),
527
+ (b':method', b'CONNECT'),
528
+ (b':protocol', b'test_value'),
529
+ (b':scheme', b'https'),
530
+ (b'host', b'example.com'),
531
+ ),
532
+ # Next, missing :scheme header
533
+ (
534
+ (b':authority', b'example.com'),
535
+ (b':method', b'CONNECT'),
536
+ (b':protocol', b'test_value'),
537
+ (b':path', b'/'),
538
+ (b'host', b'example.com'),
539
+ )
540
+ )
541
+ invalid_connect_req_rfc8441_unicode = (
542
+ # First, missing :path header
543
+ (
544
+ (u':authority', u'example.com'),
545
+ (u':method', u'CONNECT'),
546
+ (u':protocol', u'test_value'),
547
+ (u':scheme', u'https'),
548
+ (u'host', u'example.com'),
549
+ ),
550
+ # Next, missing :scheme header
551
+ (
552
+ (u':authority', u'example.com'),
553
+ (u':method', u'CONNECT'),
554
+ (u':protocol', u'test_value'),
555
+ (u':path', u'/'),
556
+ (u'host', u'example.com'),
557
+ )
558
+ )
497
559
498
560
# All headers that are forbidden from either request or response blocks.
499
561
forbidden_request_headers_bytes = (b':status',)
@@ -504,6 +566,8 @@ class TestFilter(object):
504
566
forbidden_response_headers_unicode = (
505
567
u':path', u':scheme', u':authority', u':method'
506
568
)
569
+ forbidden_connect_request_headers_bytes = (b':scheme', b':path')
570
+ forbidden_connect_request_headers_unicode = (u':scheme', u':path')
507
571
508
572
@pytest.mark.parametrize('validation_function', validation_functions)
509
573
@pytest.mark.parametrize('hdr_validation_flags', hdr_validation_combos)
@@ -688,6 +752,144 @@ def test_inbound_resp_header_extra_pseudo_headers(self,
688
752
with pytest.raises(h2.exceptions.ProtocolError):
689
753
list(h2.utilities.validate_headers(headers, hdr_validation_flags))
690
754
755
+ @pytest.mark.parametrize(
756
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
757
+ )
758
+ @pytest.mark.parametrize(
759
+ 'header_block', (
760
+ invalid_connect_request_block_bytes +
761
+ invalid_connect_request_block_unicode
762
+ )
763
+ )
764
+ def test_outbound_connect_req_missing_pseudo_headers(self,
765
+ hdr_validation_flags,
766
+ header_block):
767
+ if not hdr_validation_flags.is_rfc8441_enabled:
768
+ with pytest.raises(h2.exceptions.ProtocolError) as protocol_error:
769
+ list(
770
+ h2.utilities.validate_outbound_headers(
771
+ header_block, hdr_validation_flags
772
+ )
773
+ )
774
+ # Check if missing :path and :scheme headers doesn't throw ProtocolError exception
775
+ assert "missing mandatory :path header" not in str(protocol_error.value)
776
+ assert "missing mandatory :scheme header" not in str(protocol_error.value)
777
+
778
+ @pytest.mark.parametrize(
779
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
780
+ )
781
+ @pytest.mark.parametrize(
782
+ 'header_block', invalid_connect_request_block_bytes
783
+ )
784
+ def test_inbound_connect_req_missing_pseudo_headers(self,
785
+ hdr_validation_flags,
786
+ header_block):
787
+ if not hdr_validation_flags.is_rfc8441_enabled:
788
+ with pytest.raises(h2.exceptions.ProtocolError) as protocol_error:
789
+ list(
790
+ h2.utilities.validate_headers(
791
+ header_block, hdr_validation_flags
792
+ )
793
+ )
794
+ # Check if missing :path and :scheme headers doesn't throw ProtocolError exception
795
+ assert "missing mandatory :path header" not in str(protocol_error.value)
796
+ assert "missing mandatory :scheme header" not in str(protocol_error.value)
797
+
798
+ @pytest.mark.parametrize(
799
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
800
+ )
801
+ @pytest.mark.parametrize(
802
+ 'invalid_header',
803
+ forbidden_connect_request_headers_bytes + forbidden_connect_request_headers_unicode
804
+ )
805
+ def test_outbound_connect_req_extra_pseudo_headers(self,
806
+ hdr_validation_flags,
807
+ invalid_header):
808
+ """
809
+ Inbound request header blocks containing the forbidden request headers
810
+ fail validation.
811
+ """
812
+ headers = [
813
+ (b':authority', b'google.com'),
814
+ (b':method', b'CONNECT'),
815
+ (b':protocol', b'websocket'),
816
+ ]
817
+ if not hdr_validation_flags.is_rfc8441_enabled:
818
+ headers.append((invalid_header, b'some value'))
819
+ with pytest.raises(h2.exceptions.ProtocolError) as protocol_error:
820
+ list(h2.utilities.validate_outbound_headers(headers, hdr_validation_flags))
821
+ if isinstance(invalid_header, bytes):
822
+ expected_exception_string = (b'Header block must not contain ' + invalid_header + b' header')\
823
+ .decode("utf-8")
824
+ else:
825
+ expected_exception_string = 'Header block must not contain ' + invalid_header + ' header'
826
+ assert expected_exception_string == str(protocol_error.value)
827
+
828
+ @pytest.mark.parametrize(
829
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
830
+ )
831
+ @pytest.mark.parametrize(
832
+ 'invalid_header',
833
+ forbidden_connect_request_headers_bytes
834
+ )
835
+ def test_inbound_connect_req_extra_pseudo_headers(self,
836
+ hdr_validation_flags,
837
+ invalid_header):
838
+ """
839
+ Inbound request header blocks containing the forbidden request headers
840
+ fail validation.
841
+ """
842
+ headers = [
843
+ (b':authority', b'google.com'),
844
+ (b':method', b'CONNECT'),
845
+ (b':protocol', b'some value'),
846
+ ]
847
+ if not hdr_validation_flags.is_rfc8441_enabled:
848
+ headers.append((invalid_header, b'some value'))
849
+ with pytest.raises(h2.exceptions.ProtocolError) as protocol_error:
850
+ list(h2.utilities.validate_headers(headers, hdr_validation_flags))
851
+ assert (b'Header block must not contain ' + invalid_header + b' header').decode("utf-8") \
852
+ == str(protocol_error.value)
853
+
854
+
855
+ @pytest.mark.parametrize(
856
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
857
+ )
858
+ @pytest.mark.parametrize(
859
+ 'header_block', (
860
+ invalid_connect_req_rfc8441_bytes +
861
+ invalid_connect_req_rfc8441_unicode
862
+ )
863
+ )
864
+ def test_outbound_connect_req_rfc8441_missing_pseudo_headers(self,
865
+ hdr_validation_flags,
866
+ header_block):
867
+ if hdr_validation_flags.is_rfc8441_enabled:
868
+ with pytest.raises(h2.exceptions.ProtocolError):
869
+ list(
870
+ h2.utilities.validate_outbound_headers(
871
+ header_block, hdr_validation_flags
872
+ )
873
+ )
874
+
875
+ @pytest.mark.parametrize(
876
+ 'hdr_validation_flags', hdr_validation_request_headers_no_trailer
877
+ )
878
+ @pytest.mark.parametrize(
879
+ 'header_block', invalid_connect_req_rfc8441_bytes
880
+ )
881
+ def test_inbound_connect_req_rfc8441_missing_pseudo_headers(self,
882
+ hdr_validation_flags,
883
+ header_block):
884
+ if hdr_validation_flags.is_rfc8441_enabled:
885
+ print("here", header_block)
886
+ with pytest.raises(h2.exceptions.ProtocolError):
887
+ list(
888
+ h2.utilities.validate_headers(
889
+ header_block, hdr_validation_flags
890
+ )
891
+ )
892
+
691
893
692
894
class TestOversizedHeaders(object):
693
895
"""
0 commit comments