diff --git a/checks/migrations/0016_add_tlsrpt.py b/checks/migrations/0016_add_tlsrpt.py index ce58c24d5..20740c46a 100644 --- a/checks/migrations/0016_add_tlsrpt.py +++ b/checks/migrations/0016_add_tlsrpt.py @@ -10,7 +10,7 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( + migrations.AddField( model_name="mailtestauth", name="tlsrpt_score", field=models.IntegerField(null=True), diff --git a/checks/scoring.py b/checks/scoring.py index 741f22ea1..e168fdcbd 100644 --- a/checks/scoring.py +++ b/checks/scoring.py @@ -236,7 +236,7 @@ MAIL_AUTH_SPF_WORST_STATUS = STATUS_FAIL MAIL_AUTH_TLSRPT_PASS = NO_POINTS -MAIL_AUTH_TLSRPT_FAIL = NO_POINTS # TLS-RPT fail does not give a points penalty +MAIL_AUTH_TLSRPT_FAIL = NO_POINTS # TLS-RPT fail does not give a points penalty MAIL_AUTH_TLSRPT_ERROR = NO_POINTS MAIL_AUTH_TLSRPT_WORST_STATUS = STATUS_FAIL diff --git a/checks/tasks/tlsrpt_parsing.py b/checks/tasks/tlsrpt_parsing.py index e4ee47ad1..6616bc290 100644 --- a/checks/tasks/tlsrpt_parsing.py +++ b/checks/tasks/tlsrpt_parsing.py @@ -1,12 +1,12 @@ # Copyright: 2022-2024, ECP, NLnet Labs, the Internet.nl contributors and SYS4 AG. # SPDX-License-Identifier: Apache-2.0 -''' +""" SMTP TLS Reporting policy parser as defined by: RFC 8460, Section "3. Reporting Policy", see: https://datatracker.ietf.org/doc/html/rfc8460#section-3 -''' +""" from pyparsing import ( Literal, @@ -23,14 +23,14 @@ ) -WSP = White(ws=' ', exact=1).suppress() # Whitespace +WSP = White(ws=" ", exact=1).suppress() # Whitespace -field_delim = ZeroOrMore(WSP) + Literal(';') + ZeroOrMore(WSP) # Fields are semicolon-delimited -ura_delim = ZeroOrMore(WSP) + Literal(',') + ZeroOrMore(WSP) # multiple RUAs are comma-delimited +field_delim = ZeroOrMore(WSP) + Literal(";") + ZeroOrMore(WSP) # Fields are semicolon-delimited +ura_delim = ZeroOrMore(WSP) + Literal(",") + ZeroOrMore(WSP) # multiple RUAs are comma-delimited tlsrpt_ext_name = Word(alphanums, alphanums + "_-.", max=32) tlsrpt_ext_value = Word(alphanums, alphanums + "_-.") -tlsrpt_extension = ZeroOrMore(tlsrpt_ext_name + Literal('=') + tlsrpt_ext_value) +tlsrpt_extension = ZeroOrMore(tlsrpt_ext_name + Literal("=") + tlsrpt_ext_value) # RegEx for parsing email. regex_tld = r"(?:[a-zA-Z]{2,63}|xn--[a-zA-Z0-9]+)" @@ -38,8 +38,7 @@ r"(?P([a-zA-Z0-9]{0,61}@)?([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+" r"" + regex_tld + ")" ) mail_uri = Combine(CaselessLiteral("mailto:") + Regex(regex_mailaddr)) -tlsrpt_rua = Literal("rua=") + \ - delimitedList(mail_uri | pyparsing_common.url, delim=',').setResultsName('tlsrpt_uri') +tlsrpt_rua = Literal("rua=") + delimitedList(mail_uri | pyparsing_common.url, delim=",").setResultsName("tlsrpt_uri") tlsrpt_field = tlsrpt_rua + ZeroOrMore(field_delim + tlsrpt_extension) diff --git a/checks/test/test_tlsrpt_parsing.py b/checks/test/test_tlsrpt_parsing.py index a2436de7b..84cc21bc5 100644 --- a/checks/test/test_tlsrpt_parsing.py +++ b/checks/test/test_tlsrpt_parsing.py @@ -4,29 +4,29 @@ def test_record_parse_simple_mailto(): TXT_RECORD = "v=TLSRPTv1; rua=mailto:reports@example.com" parsed = tlsrpt_parsing.record.parseString(TXT_RECORD) - assert parsed.tlsrpt_version == 'v=TLSRPTv1' - assert parsed.tlsrpt_uri[0] == 'mailto:reports@example.com' + assert parsed.tlsrpt_version == "v=TLSRPTv1" + assert parsed.tlsrpt_uri[0] == "mailto:reports@example.com" def test_record_parse_multiple_mailto(): TXT_RECORD = "v=TLSRPTv1;rua=mailto:reports@example.com,mailto:postmaster@example.com" parsed = tlsrpt_parsing.record.parseString(TXT_RECORD) - assert parsed.tlsrpt_version == 'v=TLSRPTv1' - assert parsed.tlsrpt_uri[0] == 'mailto:reports@example.com' - assert parsed.tlsrpt_uri[1] == 'mailto:postmaster@example.com' + assert parsed.tlsrpt_version == "v=TLSRPTv1" + assert parsed.tlsrpt_uri[0] == "mailto:reports@example.com" + assert parsed.tlsrpt_uri[1] == "mailto:postmaster@example.com" def test_record_parse_simple_https(): TXT_RECORD = "v=TLSRPTv1; rua=https://reporting.example.com/v1/tlsrpt" parsed = tlsrpt_parsing.record.parseString(TXT_RECORD) - assert parsed.tlsrpt_version == 'v=TLSRPTv1' - assert parsed.tlsrpt_uri[0] == 'https://reporting.example.com/v1/tlsrpt' + assert parsed.tlsrpt_version == "v=TLSRPTv1" + assert parsed.tlsrpt_uri[0] == "https://reporting.example.com/v1/tlsrpt" def test_record_parse_with_extension(): TXT_RECORD = "v=TLSRPTv1; rua=https://reporting.example.com/v1/tlsrpt; ext=extvalue" parsed = tlsrpt_parsing.record.parseString(TXT_RECORD) - assert parsed.tlsrpt_version == 'v=TLSRPTv1' + assert parsed.tlsrpt_version == "v=TLSRPTv1" def test_parse_silent(): @@ -34,6 +34,6 @@ def test_parse_silent(): Check that parse_silent does not throw a ParseException but instead returns None if the TLSRPT policy record is malformed. """ - TXT_RECORD = "v=TLSRPTv1; rua=!!" # broken TLSRPT + TXT_RECORD = "v=TLSRPTv1; rua=!!" # broken TLSRPT parsed = tlsrpt_parsing.parse_silent(TXT_RECORD) assert parsed is None