1- from abc import abstractmethod , ABC
21from xml .etree .ElementTree import Element
32
43from cryptography .hazmat .backends import default_backend
@@ -52,9 +51,8 @@ def process_task(
5251 hsts_header , hpkp_header , expect_ct_header , hpkp_report_only , certificate_chain = self ._get_security_headers (
5352 server_info
5453 )
55- return HttpHeadersScanResult (
56- server_info , scan_command , hsts_header , hpkp_header , expect_ct_header , hpkp_report_only , certificate_chain
57- )
54+ return HttpHeadersScanResult (server_info , scan_command , hsts_header , hpkp_header , expect_ct_header ,
55+ hpkp_report_only , certificate_chain )
5856
5957 @classmethod
6058 def _get_security_headers (
@@ -95,30 +93,7 @@ def _get_security_headers(
9593 return hsts_header , hpkp_header , expect_ct_header , hpkp_report_only , certificate_chain
9694
9795
98- class HttpHeaderParsingError (ValueError ):
99- """Raised when an HTTP header is badly formatted and could not be parsed.
100- """
101- pass
102-
103-
104- class _ParsedHttpHeader (ABC ):
105-
106- def __init__ (self , raw_header : str ) -> None :
107- # Handle headers defined multiple times by picking the first value
108- if ',' in raw_header :
109- raw_header = raw_header .split (',' )[0 ]
110-
111- try :
112- self ._parse_header (raw_header )
113- except ValueError :
114- raise HttpHeaderParsingError (f'Error when trying to parse "{ raw_header } "; HTTP header is badly formatted?' )
115-
116- @abstractmethod
117- def _parse_header (self , raw_header : str ) -> None :
118- pass
119-
120-
121- class ParsedHstsHeader (_ParsedHttpHeader ):
96+ class ParsedHstsHeader :
12297 """The HTTP Strict Transport Security header returned by the server.
12398
12499 Attributes:
@@ -127,12 +102,13 @@ class ParsedHstsHeader(_ParsedHttpHeader):
127102 max_age (int): The content of the max-age field.
128103 """
129104 def __init__ (self , raw_hsts_header : str ) -> None :
130- self .max_age : int
105+ # Handle headers defined multiple times by picking the first value
106+ if ',' in raw_hsts_header :
107+ raw_hsts_header = raw_hsts_header .split (',' )[0 ]
108+
109+ self .max_age = None
131110 self .include_subdomains = False
132111 self .preload = False
133- super ().__init__ (raw_hsts_header )
134-
135- def _parse_header (self , raw_hsts_header : str ) -> None :
136112 for hsts_directive in raw_hsts_header .split (';' ):
137113 hsts_directive = hsts_directive .strip ()
138114 if not hsts_directive :
@@ -150,26 +126,28 @@ def _parse_header(self, raw_hsts_header: str) -> None:
150126 raise ValueError ('Unexpected value in HSTS header: {}' .format (repr (hsts_directive )))
151127
152128
153- class ParsedHpkpHeader ( _ParsedHttpHeader ) :
129+ class ParsedHpkpHeader :
154130 """The HTTP Public Key Pinning header returned by the server.
155131
156132 Attributes:
157133 report_only (bool): True if the HPKP header used is "Public-Key-Pins-Report-Only" (instead of
158134 "Public-Key-Pins").
159- report_uri (Optional[ str] ): The content of the report-uri field.
135+ report_uri (str): The content of the report-uri field.
160136 include_subdomains (bool): True if the includesubdomains directive is set.
161137 max_age (int): The content of the max-age field.
162138 pin_sha256_list (List[str]): The list of pin-sha256 values set in the header.
163139 """
164140
165141 def __init__ (self , raw_hpkp_header : str , report_only : bool = False ) -> None :
142+ # Handle headers defined multiple times by picking the first value
143+ if ',' in raw_hpkp_header :
144+ raw_hpkp_header = raw_hpkp_header .split (',' )[0 ]
145+
166146 self .report_only = report_only
167- self .report_uri : Optional [ str ] = None
147+ self .report_uri = None
168148 self .include_subdomains = False
169- self .max_age : int
170- super ().__init__ (raw_hpkp_header )
149+ self .max_age = None
171150
172- def _parse_header (self , raw_hpkp_header : str ) -> None :
173151 pin_sha256_list = []
174152 for hpkp_directive in raw_hpkp_header .split (';' ):
175153 hpkp_directive = hpkp_directive .strip ()
@@ -192,22 +170,21 @@ def _parse_header(self, raw_hpkp_header: str) -> None:
192170 self .pin_sha256_list = pin_sha256_list
193171
194172
195- class ParsedExpectCtHeader (_ParsedHttpHeader ):
173+ # TODO(AD): Rename this to ParsedExpectCtHeader
174+ class ParsedExpectCTHeader :
196175 """Expect-CT header returned by the server.
197176
198177 Attributes:
199178 max-age (int): The content of the max-age field.
200- report-uri (Optional[ str] ): The content of report-uri field.
179+ report-uri (str): The content of report-uri field.
201180 enforce (bool): True if enforce directive is set.
202181 """
203182
204183 def __init__ (self , raw_expect_ct_header : str ) -> None :
205- self .max_age : int
206- self .report_uri : Optional [ str ] = None
184+ self .max_age = None
185+ self .report_uri = None
207186 self .enforce = False
208- super ().__init__ (raw_expect_ct_header )
209187
210- def _parse_header (self , raw_expect_ct_header : str ) -> None :
211188 for expect_ct_directive in raw_expect_ct_header .split (',' ):
212189 expect_ct_directive = expect_ct_directive .strip ()
213190
@@ -260,7 +237,7 @@ def __init__(
260237 super ().__init__ (server_info , scan_command )
261238 self .hsts_header = ParsedHstsHeader (raw_hsts_header ) if raw_hsts_header else None
262239 self .hpkp_header = ParsedHpkpHeader (raw_hpkp_header , hpkp_report_only ) if raw_hpkp_header else None
263- self .expect_ct_header = ParsedExpectCtHeader (raw_expect_ct_header ) if raw_expect_ct_header else None
240+ self .expect_ct_header = ParsedExpectCTHeader (raw_expect_ct_header ) if raw_expect_ct_header else None
264241 self .verified_certificate_chain : List [Certificate ] = []
265242 try :
266243 main_trust_store = TrustStoresRepository .get_default ().get_main_store ()
0 commit comments