ARC signing fails on AR headers with authres-version or comments before resinfo
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
dkimpy |
Fix Released
|
Medium
|
Scott Kitterman |
Bug Description
ARC signing doesn't support full spectrum of valid Authentication-
Traceback (most recent call last):
File "arc-sign/
parsed_
File "arc-sign/
return authres.
File "arc-sign/
return self.parse_
File "arc-sign/
header.
File "arc-sign/
result = self._parse_
File "arc-sign/
method, version, result = self._parse_
File "arc-sign/
raise SyntaxError(
authres.
dkim=pass (2048-bit key)
#011header.d=...
This fails when a header like the following is present in the mail:
Authentication
dkim=pass (2048-bit key)
Note that either a comment ("(amavisd-new)" above) or authres-version ("1" above). Extra whitespace before the first ';' may also cause issues.
Library version: dkimpy==1.1.5
The following patch fixes the issue at the cost of stripping comments from AR headers for the purposes of AAR header construction. This seems to be allowed by the RFC, since comments are intended to be used by humans.
--- dkim/__
+++ dkim/__init__.py 2024-02-06 15:20:14.866534604 +0000
@@ -1052,28 +1052,26 @@
# extract, parse, filter & group AR headers
ar_headers = [res.strip() for [ar, res] in self.headers if ar == b'Authenticatio
- grouped_headers = []
+ parsed_ar_headers = []
for res in ar_headers:
try: # see LP: #1884044
- grouped_
+ # Note: parsing headers currently strips embedded comments
+ parsed_
except authres.
# Skip over invalid AR header fields
pass
- auth_headers = [res for res in grouped_headers if res[1].authserv_id == srv_id.
+ auth_headers = [header for header in parsed_ar_headers if header.authserv_id == srv_id.
if len(auth_headers) == 0:
return []
# consolidate headers
- results_lists = [raw.replace(srv_id + b';', b'', 1).strip() for (raw, parsed) in auth_headers]
- results_lists = [tags.split(b';') for tags in results_lists]
- results = [tag.strip() for sublist in results_lists for tag in sublist]
- auth_results = srv_id + b'; ' + (b';' + self.linesep + b' ').join(results)
+ results = [res for header in auth_headers for res in header.results]
+ auth_results = srv_id + b''.join(b';' + self.linesep + b' ' + str(res)
# extract cv
- parsed_auth_results = authres.
- arc_results = [res for res in parsed_
+ arc_results = [res for res in results if res.method == 'arc']
if len(arc_results) == 0:
elif len(arc_results) != 1:
--- dkim/tests/
+++ dkim/tests/
@@ -74,7 +74,7 @@
sig_lines = dkim.arc_sign(
- expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345;\r\n b=MBw2+
+ expected_sig = [b'ARC-Seal: i=1; cv=none; a=rsa-sha256; d=example.com; s=test; t=12345;\r\n b=iSKjTQ93xUC6g
(cv, res, reason) = dkim.arc_
Changed in dkimpy: | |
status: | Triaged → Fix Committed |
Changed in dkimpy: | |
status: | Fix Committed → Fix Released |
Thank you. In the future, patches attached in a text file are much more useful since the web U/I strips leading spaced. I plan to include this in the next release.