Correct ARC signing for AR headers with authres-version or comments before resinfo (LP: #2052526) - Thanks to Nikolay Vizovitin for the report and the fix
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
UNRELEASED Version 1.1.7
|
UNRELEASED Version 1.1.7
|
||||||
- Fix error in validate_signature_fields which prevented signature
|
- Fix error in validate_signature_fields which prevented signature
|
||||||
expiration from being properly evaluated (LP: #2068937)
|
expiration from being properly evaluated (LP: #2068937)
|
||||||
|
- Correct ARC signing for AR headers with authres-version or comments
|
||||||
|
before resinfo (LP: #2052526) - Thanks to Nikolay Vizovitin for the
|
||||||
|
report and the fix
|
||||||
|
|
||||||
2024-04-14 Version 1.1.6
|
2024-04-14 Version 1.1.6
|
||||||
- Use raw byte string for regex; fixes SyntaxWarning in Python 3.12 due to
|
- Use raw byte string for regex; fixes SyntaxWarning in Python 3.12 due to
|
||||||
|
|||||||
+7
-9
@@ -1052,28 +1052,26 @@ class ARC(DomainSigner):
|
|||||||
# extract, parse, filter & group AR headers
|
# extract, parse, filter & group AR headers
|
||||||
ar_headers = [res.strip() for [ar, res] in self.headers if ar == b'Authentication-Results']
|
ar_headers = [res.strip() for [ar, res] in self.headers if ar == b'Authentication-Results']
|
||||||
|
|
||||||
grouped_headers = []
|
parsed_ar_headers = []
|
||||||
for res in ar_headers:
|
for res in ar_headers:
|
||||||
try: # see LP: #1884044
|
try: # see LP: #1884044
|
||||||
grouped_headers.append((res, authres.AuthenticationResultsHeader.parse('Authentication-Results: ' + res.decode('utf-8'))))
|
# Note: parsing headers currently strips embedded comments
|
||||||
|
parsed_ar_headers.append(authres.AuthenticationResultsHeader.parse('Authentication-Results: ' + res.decode('utf-8')))
|
||||||
except authres.core.SyntaxError:
|
except authres.core.SyntaxError:
|
||||||
# Skip over invalid AR header fields
|
# Skip over invalid AR header fields
|
||||||
pass
|
pass
|
||||||
auth_headers = [res for res in grouped_headers if res[1].authserv_id == srv_id.decode('utf-8')]
|
auth_headers = [header for header in parsed_ar_headers if header.authserv_id == srv_id.decode('utf-8')]
|
||||||
|
|
||||||
if len(auth_headers) == 0:
|
if len(auth_headers) == 0:
|
||||||
self.logger.debug("no AR headers found, chain terminated")
|
self.logger.debug("no AR headers found, chain terminated")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# consolidate headers
|
# consolidate headers
|
||||||
results_lists = [raw.replace(srv_id + b';', b'').strip() for (raw, parsed) in auth_headers]
|
results = [res for header in auth_headers for res in header.results]
|
||||||
results_lists = [tags.split(b';') for tags in results_lists]
|
auth_results = srv_id + b''.join(b';' + self.linesep + b' ' + str(res).encode('utf-8') for res in results)
|
||||||
results = [tag.strip() for sublist in results_lists for tag in sublist]
|
|
||||||
auth_results = srv_id + b'; ' + (b';' + self.linesep + b' ').join(results)
|
|
||||||
|
|
||||||
# extract cv
|
# extract cv
|
||||||
parsed_auth_results = authres.AuthenticationResultsHeader.parse('Authentication-Results: ' + auth_results.decode('utf-8'))
|
arc_results = [res for res in results if res.method == 'arc']
|
||||||
arc_results = [res for res in parsed_auth_results.results if res.method == 'arc']
|
|
||||||
if len(arc_results) == 0:
|
if len(arc_results) == 0:
|
||||||
chain_validation_status = CV_None
|
chain_validation_status = CV_None
|
||||||
elif len(arc_results) != 1:
|
elif len(arc_results) != 1:
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ Y+vtSBczUiKERHv1yRbcaQtZFh5wtiRrN04BLUTD21MycBX5jYchHjPY/wIDAQAB"""
|
|||||||
sig_lines = dkim.arc_sign(
|
sig_lines = dkim.arc_sign(
|
||||||
self.message, b"test", b"example.com", self.key, b"lists.example.org", timestamp="12345")
|
self.message, b"test", b"example.com", self.key, b"lists.example.org", timestamp="12345")
|
||||||
|
|
||||||
expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345;\r\n b=MBw2+L1/4PuYWJlt1tZlDtbOvyfbyH2t2N6DinFV/BIaB2LqbDKTYjXXk9HuuK1/qEkTd\r\n TxCYScIrtVO7pFbGiSawMuLatVzHNCqTURa1zBTXr2mKW1hgdmrtMMUcMVCYxr1AJpu6IYX\r\n VMIoOAn7tIDdO0VLokK6FnIXTWEAplQ=\r\n', b'ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;\r\n d=example.com; s=test; t=12345; h=message-id : date : from : to :\r\n subject : from; bh=wE7NXSkgnx9PGiavN4OZhJztvkqPDlemV3OGuEnLwNo=;\r\n b=a0f6qc3k9eECTSR155A0TQS+LjqPFWfI/brQBA83EUz00SNxj1wmWykvs1hhBVeM0r1kE\r\n Qc6CKbzRYaBNSiFj4q8JBpRIujLz1qLyGmPuAI6ddu/Z/1hQxgpVcp/odmI1UMV2R+d+yQ7\r\n tUp3EQxF/GYNt22rV4rNmDmANZVqJ90=\r\n', b'ARC-Authentication-Results: i=1; lists.example.org; arc=none;\r\n spf=pass smtp.mfrom=jqd@d1.example;\r\n dkim=pass (1024-bit key) header.i=@d1.example;\r\n dmarc=pass\r\n']
|
expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345;\r\n b=iSKjTQ93xUC6gt4yutHrOf0F/qb4E5voEeuucd66VhM4n/7ifBMMHqYwncgz9sefduM6C\r\n UthuUSzqE2YamkGXQgKPIG9t4ZCOrx1OXGE34WF9ZeI/E0csrN+wK7sq/RjgN3z4qxLPMsp\r\n lW+BUUHCNuCIvxcZ55Ky6evIb/Saj2o=\r\n', b'ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;\r\n d=example.com; s=test; t=12345; h=message-id : date : from : to :\r\n subject : from; bh=wE7NXSkgnx9PGiavN4OZhJztvkqPDlemV3OGuEnLwNo=;\r\n b=a0f6qc3k9eECTSR155A0TQS+LjqPFWfI/brQBA83EUz00SNxj1wmWykvs1hhBVeM0r1kE\r\n Qc6CKbzRYaBNSiFj4q8JBpRIujLz1qLyGmPuAI6ddu/Z/1hQxgpVcp/odmI1UMV2R+d+yQ7\r\n tUp3EQxF/GYNt22rV4rNmDmANZVqJ90=\r\n', b'ARC-Authentication-Results: i=1; lists.example.org;\r\n arc=none;\r\n spf=pass smtp.mfrom=jqd@d1.example;\r\n dkim=pass header.i=@d1.example;\r\n dmarc=pass\r\n']
|
||||||
self.assertEqual(expected_sig, sig_lines)
|
self.assertEqual(expected_sig, sig_lines)
|
||||||
|
|
||||||
(cv, res, reason) = dkim.arc_verify(b''.join(sig_lines) + self.message, dnsfunc=self.dnsfunc)
|
(cv, res, reason) = dkim.arc_verify(b''.join(sig_lines) + self.message, dnsfunc=self.dnsfunc)
|
||||||
|
|||||||
Reference in New Issue
Block a user