From 88c17516d902e337786f7ec3e19652d3bb01615c Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Mon, 20 Apr 2020 15:51:10 -0400 Subject: [PATCH 01/14] Improve resilience to malformed email addresses --- CHANGES | 1 + dkimpy_milter/__init__.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 6cfeb0b..57a3ac6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ 1.2.2 + - Improve resilience to malformed email addresses - Improve README.md formating for markdown display on pypi - Improve documentation in dkimpy-milter.conf (5) and README.md for signing for multiple domains (Thanks to Stefano Rivera) diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 5118ae8..a0db433 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -141,6 +141,8 @@ class dkimMilter(Milter.Base): self.fdomain = self.author.split('@')[1].lower() except IndexError as er: pass # self.author was not a proper email address + # This keeps non-ascii characters out of the From domain + self.fdomain = str(codecs.encode(self.fdomain, 'ascii', 'replace'), 'ascii', 'ignore') if (self.conf.get('Syslog') and self.conf.get('debugLevel') >= 1): syslog.syslog("{0}: {1}".format(name, val)) @@ -148,7 +150,11 @@ class dkimMilter(Milter.Base): self.arheaders.append(val) if self.fp: try: - self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii'))) + if lname == 'from': + # Non-ascii in email address localpart is legal, so this is a special case + self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'UTF-8', 'replace'))) + else: + self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii'))) except: # Don't choke on header fields with non-ascii garbage in them. pass From 44d892406060673d32c2e3723ea332a594927cb4 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 9 Aug 2020 13:50:40 -0400 Subject: [PATCH 02/14] WIP for invalid UTF-8 resilience --- CHANGES | 2 +- dkimpy_milter/__init__.py | 6 ++++-- setup.py | 2 +- tests/02_sign_message.miltertest | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 57a3ac6..354775f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -1.2.2 +1.3.0 WARNING LAST COMMIT IS WIP - Improve resilience to malformed email addresses - Improve README.md formating for markdown display on pypi - Improve documentation in dkimpy-milter.conf (5) and README.md for signing diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index a0db433..facae23 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -107,9 +107,11 @@ class dkimMilter(Milter.Base): # envfrom (MAIL FROM in the SMTP protocol) seems to mark the start # of each message. @Milter.noreply - def envfrom(self, f, *str): + def envfrom(self, f, *moredata): + f = str(codecs.encode(f, 'UTF-8', 'replace'), 'UTF-8', 'ignore') + moredata = str(codecs.encode(str(moredata), 'UTF-8', 'replace'), 'UTF-8', 'ignore') if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 2: - syslog.syslog("mail from: {0} {1}".format(f, str)) + syslog.syslog("mail from: {0} {1}".format(f, moredata)) self.fp = io.BytesIO() self.mailfrom = f t = parse_addr(f) diff --git a/setup.py b/setup.py index 07039f7..c661a91 100644 --- a/setup.py +++ b/setup.py @@ -89,7 +89,7 @@ except ImportError: # If PyDNS is not installed, prefer dnspython setup( name='dkimpy-milter', - version='1.2.1', + version='1.3.0', author='Scott Kitterman', author_email='scott@kitterman.com', url='https://launchpad.net/dkimpy-milter', diff --git a/tests/02_sign_message.miltertest b/tests/02_sign_message.miltertest index 77907ba..1596240 100644 --- a/tests/02_sign_message.miltertest +++ b/tests/02_sign_message.miltertest @@ -26,7 +26,7 @@ function connect_and_send (sockname, headers, body) end -- mt.macro(conn, SMFIC_MAIL, "i", "simple-message") - if mt.mailfrom(conn, "") ~= nil then + if mt.mailfrom(conn, " (Alicþþÿÿe)") ~= nil then error "mt.mailfrom() failed" end if mt.getreply(conn) ~= SMFIR_CONTINUE then From b4da312ea7a6ca46c2e572547e3114a15d74e602 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 9 Aug 2020 14:12:05 -0400 Subject: [PATCH 03/14] Minimal fix for dnspython 2.0.0 compatibility (still works with 1.16.0) --- CHANGES | 3 +++ dkimpy_milter/dnsplug.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 354775f..9b5c3c1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,11 @@ 1.3.0 WARNING LAST COMMIT IS WIP - Improve resilience to malformed email addresses + +1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi - Improve documentation in dkimpy-milter.conf (5) and README.md for signing for multiple domains (Thanks to Stefano Rivera) + - Minimal fix for dnspython 2.0.0 compatibility (still works with 1.16.0) 1.2.1 2020-01-04 - Fix expand option not to fail if files are missing since socket activation diff --git a/dkimpy_milter/dnsplug.py b/dkimpy_milter/dnsplug.py index 9e7aa58..d1f7a15 100644 --- a/dkimpy_milter/dnsplug.py +++ b/dkimpy_milter/dnsplug.py @@ -127,7 +127,7 @@ def DNSLookup_dnspython(name,qtype,tcpfallback=True,timeout=5): elif qtype == 'PTR': retVal.append(((name, qtype), rdata.target.to_text(True))) elif qtype == 'TXT' or qtype == 'SPF': - retVal.append(((name, qtype), rdata.strings)) + retVal.append(((name, qtype), list(rdata.strings))) except dns.resolver.NoAnswer: pass except dns.resolver.NXDOMAIN: From 1a0abcddc71a4ad96d54c6e68ec6933aec506714 Mon Sep 17 00:00:00 2001 From: Casper Bruun Date: Mon, 5 Dec 2022 20:07:43 -0500 Subject: [PATCH 04/14] Fixup UTF-8 string decoding - Thanks to Casper Bruun --- dkimpy_milter/__init__.py | 24 ++++++++++++++++++++---- dkimpy_milter/config.py | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index facae23..9391bb8 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -101,15 +101,26 @@ class dkimMilter(Milter.Base): if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 1: syslog.syslog("connect from {0} at {1} {2}" .format(hostname, hostaddr, connecttype)) - return Milter.CONTINUE + if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 3: + syslog.syslog("internal_conn: {0}, external_conn: {1}" + .format(self.internal_connection, self.external_connection)) + + return Milter.CONTINUE # multiple messages can be received on a single connection # envfrom (MAIL FROM in the SMTP protocol) seems to mark the start # of each message. @Milter.noreply def envfrom(self, f, *moredata): - f = str(codecs.encode(f, 'UTF-8', 'replace'), 'UTF-8', 'ignore') - moredata = str(codecs.encode(str(moredata), 'UTF-8', 'replace'), 'UTF-8', 'ignore') + try: + f = str(codecs.encode(f, 'UTF-8', 'replace'), 'UTF-8', 'ignore') + except TypeError: + f = codecs.encode(f, 'UTF-8', 'replace').decode() + try: + moredata = str(codecs.encode(str(moredata), 'UTF-8', 'replace'), 'UTF-8', 'ignore') + except TypeError: + moredata = codecs.encode(str(moredata), 'UTF-8', 'replace').decode() + if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 2: syslog.syslog("mail from: {0} {1}".format(f, moredata)) self.fp = io.BytesIO() @@ -144,7 +155,10 @@ class dkimMilter(Milter.Base): except IndexError as er: pass # self.author was not a proper email address # This keeps non-ascii characters out of the From domain - self.fdomain = str(codecs.encode(self.fdomain, 'ascii', 'replace'), 'ascii', 'ignore') + try: + self.fdomain = str(codecs.encode(self.fdomain, 'ascii', 'replace'), 'ascii', 'ignore') + except TypeError: + self.fdomain = codecs.encode(self.fdomain, 'ascii', 'replace').decode('ascii','ignore') if (self.conf.get('Syslog') and self.conf.get('debugLevel') >= 1): syslog.syslog("{0}: {1}".format(name, val)) @@ -203,6 +217,8 @@ class dkimMilter(Milter.Base): syslog.syslog('self.domain: {0}, self.fdomain: {1}, self.iequals: {2}'.format(self.domain, self.fdomain, self.iequals)) if ((self.fdomain in self.domain) and not self.conf.get('Mode') == 'v' and not self.external_connection): + if (self.conf.get('Syslog') and self.conf.get('debugLevel') >= 3): + syslog.syslog("Signing DKIM") self.sign_dkim(txt) if ((self.has_dkim) and (not self.internal_connection) and (self.conf.get('Mode') == 'v' or diff --git a/dkimpy_milter/config.py b/dkimpy_milter/config.py index cbbfaea..d52b5a4 100644 --- a/dkimpy_milter/config.py +++ b/dkimpy_milter/config.py @@ -89,16 +89,23 @@ class HostsDataset(object): self.item = item[1:] self.negative = True try: - self.item = ipaddress.ip_address(str(self.item, "utf-8")) + try: + self.item = ipaddress.ip_address(str(self.item, "utf-8")) + except TypeError: + self.item = ipaddress.ip_address(self.item) if isinstance(self.item, ipaddress.IPv4Address): self.isipv4 = True elif isinstance(self.item, ipaddress.IPv6Address): self.isipv6 = True except ValueError as e: try: - self.item = ipaddress.ip_network(str - (self.item, "utf-8"), - strict=False) + try: + self.item = ipaddress.ip_network(str + (self.item, "utf-8"), + strict=False) + except TypeError: + self.item = ipaddress.ip_network(self.item, + strict=False) if isinstance(self.item, ipaddress.IPv4Network): self.isipv4cidr = True elif isinstance(self.item, ipaddress.IPv6Network): @@ -114,7 +121,10 @@ class HostsDataset(object): def match(self, connectip): '''Check if the connect IP is part of the dataset''' - source = ipaddress.ip_address(str(connectip, "utf-8")) + try: + source = ipaddress.ip_address(str(connectip, "utf-8")) + except TypeError: + source = ipaddress.ip_address(connectip) for item in self.dataset: if item.isdomain or item.ishostname: result = self.matchname(source) # Match host/domains first @@ -164,13 +174,19 @@ class HostsDataset(object): if isinstance(source, ipaddress.IPv4Address): ips = s.dns(name, 'A') for ip in ips: - ip = ipaddress.IPv4Address(str(ip, 'UTF-8')) + try: + ip = ipaddress.IPv4Address(str(ip, 'UTF-8')) + except TypeError: + ip = ipaddress.IPv4Address(ip) if ip == source: results.append(name) if isinstance(source, ipaddress.IPv6Address): ips = s.dns(name, 'AAAA') for ip in ips: - ip = ipaddress.IPv6Address(str(ip, 'UTF-8')) + try: + ip = ipaddress.IPv6Address(str(ip, 'UTF-8')) + except TypeError: + ip = ipaddress.IPv6Address(ip) if ip == source: results.append(name) return results @@ -439,8 +455,14 @@ def _readConfigFile(path, configData=None, configGlobal={}): fp.close() try: configData['AuthservID'] = _make_authserv_id(configData.get('AuthservID', 'HOSTNAME')) + except Exception as e: + syslog.syslog("Could not make AuthservID: {}".format(e)) + pass + + try: configData['IntHosts'] = HostsDataset(configData['InternalHosts']) - except: + except Exception as e: + syslog.syslog("Could not make HostDataset from InternalHosts: {}".format(e)) pass return(configData) From 53368939fa2e601846d21ba866c8bca9b8eea381 Mon Sep 17 00:00:00 2001 From: Mike Tiainen Date: Mon, 5 Dec 2022 20:11:38 -0500 Subject: [PATCH 05/14] Support percent in KeyTable - Thanks to Mika Tiainen --- dkimpy_milter/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 9391bb8..2e946e0 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -319,6 +319,8 @@ class dkimMilter(Milter.Base): except: if (self.conf.get('Syslog')): syslog.syslog('Error: Invalid KeyTable data {0}'.format(keytabledata)) + if (self.fdomain == '%'): + self.fdomain = self.author.split('@')[1].lower() break def sign_dkim(self, txt): From e378fb02661924a91fee9a323b47e8bff5dbf998 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Mon, 5 Dec 2022 20:21:14 -0500 Subject: [PATCH 06/14] Fixup on UTF-8 changes --- dkimpy_milter/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 2e946e0..1e6cd16 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -105,7 +105,7 @@ class dkimMilter(Milter.Base): syslog.syslog("internal_conn: {0}, external_conn: {1}" .format(self.internal_connection, self.external_connection)) - return Milter.CONTINUE + return Milter.CONTINUE # multiple messages can be received on a single connection # envfrom (MAIL FROM in the SMTP protocol) seems to mark the start From 039fcc54fd9bf63e8919ce3c7b0f7c7ed8a7dc1d Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 18:31:36 -0500 Subject: [PATCH 07/14] Finalize UTF-8 fixup, including dkimpy/pymilter version bumps --- CHANGES | 9 +++++++-- README.md | 5 +++++ setup.py | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 9b5c3c1..4d7dfcb 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ -1.3.0 WARNING LAST COMMIT IS WIP - - Improve resilience to malformed email addresses +1.3.0 + - Improve support for non-ASCII email messages. Anything UTF-8 should work + (including correct signing/verification). For messages that contain header + fields with non-ASCII or UTF-8 content, signatures are likely fail + verification, but the milter should continue to run. + - Set minimum pymilter and dkimpy versions in setup.py to those that will + work reliably with non-ASCII content. 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/README.md b/README.md index 49efe6f..8d51b01 100644 --- a/README.md +++ b/README.md @@ -336,3 +336,8 @@ later support Ed25519 signing and verification. RFC 8301 removed rsa-sha1 from DKIM. dkimpy-milter does not sign with rsa-sha1, but still considers rsa-sha1 signatures as valid for verification because they are still in common use and are not known to be cryptographically broken. + +Support for non-ASCII email messages: Anything UTF-8 should work (including +correct signing/verification). For messages that contain header fields with +non-ASCII or UTF-8 content, signatures are likely fail verification, but the +milter should continue to run. RFC 8616 is not supported. diff --git a/setup.py b/setup.py index c661a91..cf59b8d 100644 --- a/setup.py +++ b/setup.py @@ -83,9 +83,9 @@ class FileMacroExpand(distutils.cmd.Command): kw = {} # Work-around for lack of 'or' requires in setuptools. try: import dns - kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'dnspython>=1.16.0'] + kw['install_requires'] = ['dkimpy>=1.1.0', 'pymilter>=1.0.5', 'authres>=1.1.0', 'PyNaCl', 'dnspython>=1.16.0'] except ImportError: # If PyDNS is not installed, prefer dnspython - kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS'] + kw['install_requires'] = ['dkimpy>=1.1.0', 'pymilter>=1.0.5', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS'] setup( name='dkimpy-milter', From ea2ef1043881988317ccce3088bf8d5811386ef1 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 18:34:30 -0500 Subject: [PATCH 08/14] Add missing CHANGES entries --- CHANGES | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 4d7dfcb..02f63e5 100644 --- a/CHANGES +++ b/CHANGES @@ -2,9 +2,11 @@ - Improve support for non-ASCII email messages. Anything UTF-8 should work (including correct signing/verification). For messages that contain header fields with non-ASCII or UTF-8 content, signatures are likely fail - verification, but the milter should continue to run. + verification, but the milter should continue to run. (Thanks to Casper + Bruun for help with this) - Set minimum pymilter and dkimpy versions in setup.py to those that will work reliably with non-ASCII content. + - Fixed support for percent in KeyTable - Thanks to Mika Tiainen 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi From c3d6bce238d66f05c9a3996c533dbce222dde15b Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 18:35:39 -0500 Subject: [PATCH 09/14] Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5) (Closes: #995335) --- CHANGES | 2 ++ man/dkimpy-milter.conf.5 | 2 +- man/dkimpy-milter.conf.5.in | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 02f63e5..ba34c0b 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,8 @@ - Set minimum pymilter and dkimpy versions in setup.py to those that will work reliably with non-ASCII content. - Fixed support for percent in KeyTable - Thanks to Mika Tiainen + - Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5) + (Closes: #995335) 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/man/dkimpy-milter.conf.5 b/man/dkimpy-milter.conf.5 index a363598..89faecd 100644 --- a/man/dkimpy-milter.conf.5 +++ b/man/dkimpy-milter.conf.5 @@ -327,7 +327,7 @@ be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; -TP +.TP .I MinimumKeyBits (integer) Establishes a minimum key size for acceptable RSA signatures. Signatures with smaller key sizes, even if they otherwise pass DKIM validation, will me marked diff --git a/man/dkimpy-milter.conf.5.in b/man/dkimpy-milter.conf.5.in index 45e3097..7dde804 100644 --- a/man/dkimpy-milter.conf.5.in +++ b/man/dkimpy-milter.conf.5.in @@ -327,7 +327,7 @@ be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; -TP +.TP .I MinimumKeyBits (integer) Establishes a minimum key size for acceptable RSA signatures. Signatures with smaller key sizes, even if they otherwise pass DKIM validation, will me marked From 815e1a612cf658aca532c9206b4413e595a75dfa Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 18:39:02 -0500 Subject: [PATCH 10/14] Reset the i= signature identity in get_identities_sign() (Closes: #981157) --- CHANGES | 1 + dkimpy_milter/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ba34c0b..8c15630 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,7 @@ - Fixed support for percent in KeyTable - Thanks to Mika Tiainen - Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5) (Closes: #995335) + - Reset the i= signature identity in get_identities_sign() (Closes: #981157) 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 1e6cd16..fa05ce4 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -251,7 +251,7 @@ class dkimMilter(Milter.Base): def get_identities_sign(self): """Determine d= and i= identiies for signature""" self.domain = [] - iequals = None + self.iequals = None try: self.privkeyRSA = self.conf.get('privateRSA') except: From 84803d377939516c99f11dbf9b69bb210505126b Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 19:38:53 -0500 Subject: [PATCH 11/14] Improve documentation of inter-relationship between Mode, InternalHosts, MacroList, and MacroListVerify options in dkimpy-milter.conf.5 (Closes: #969215) --- CHANGES | 3 +++ man/dkimpy-milter.conf.5 | 17 +++++++++++++++++ man/dkimpy-milter.conf.5.in | 17 +++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/CHANGES b/CHANGES index 8c15630..4c9a530 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,9 @@ - Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5) (Closes: #995335) - Reset the i= signature identity in get_identities_sign() (Closes: #981157) + - Improve documentation of inter-relationship between Mode, InternalHosts, + MacroList, and MacroListVerify options in dkimpy-milter.conf.5 (Closes: + #969215) 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/man/dkimpy-milter.conf.5 b/man/dkimpy-milter.conf.5 index 89faecd..289d09e 100644 --- a/man/dkimpy-milter.conf.5 +++ b/man/dkimpy-milter.conf.5 @@ -244,6 +244,10 @@ Naturally, providing a value here overrides the default, so if mail from 127.0.0.1 should be signed, the list provided here should include that address explicitly. [PeerList NOT IMPLEMENTED] +Mail sent via connections from InternalHosts will not have any existing DKIM +signatures verified. This is not overridden by MacroList or Mode. If the +Mode is 'v', then no actions will be performed. + .TP .I KeyFile (string) Gives the location of a PEM-formatted private key to be used for RSA signing @@ -298,6 +302,10 @@ at the time the filter receives a connection from the MTA and its availability depends upon the version of milter used to compile the filter and the version of the MTA making the connection. +Mail sent via connections where macros that are in MacroList are provided +will not have any existing DKIM signatures verified. If the Mode is 'v', then +no actions will be performed. + .TP .I MacroListVerify (dataset) Defines a set of MTA-provided @@ -308,6 +316,10 @@ Entries in this data set follow the same form as those of the .I MacroList option above. [this option is not inhereted from OpenDKIM] +Mail sent via connections where macros that are in MacroListVerify are +provided will be not DKIM signed. If the Mode is 's', then no actions will +be performed. + .TP .I Mode (string) Selects operating modes. The string is a concatenation of characters that @@ -327,6 +339,11 @@ be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; +The action to sign or verify is also affected by the InternalHosts, MacroList, +and MacroListVerify options. Those options may preclude signing or +verification in some cases, but will not enable signing or verifying if not +allowed by Mode. + .TP .I MinimumKeyBits (integer) Establishes a minimum key size for acceptable RSA signatures. Signatures with diff --git a/man/dkimpy-milter.conf.5.in b/man/dkimpy-milter.conf.5.in index 7dde804..48aa210 100644 --- a/man/dkimpy-milter.conf.5.in +++ b/man/dkimpy-milter.conf.5.in @@ -244,6 +244,10 @@ Naturally, providing a value here overrides the default, so if mail from 127.0.0.1 should be signed, the list provided here should include that address explicitly. [PeerList NOT IMPLEMENTED] +Mail sent via connections from InternalHosts will not have any existing DKIM +signatures verified. This is not overridden by MacroList or Mode. If the +Mode is 'v', then no actions will be performed. + .TP .I KeyFile (string) Gives the location of a PEM-formatted private key to be used for RSA signing @@ -298,6 +302,10 @@ at the time the filter receives a connection from the MTA and its availability depends upon the version of milter used to compile the filter and the version of the MTA making the connection. +Mail sent via connections where macros that are in MacroList are provided +will not have any existing DKIM signatures verified. If the Mode is 'v', then +no actions will be performed. + .TP .I MacroListVerify (dataset) Defines a set of MTA-provided @@ -308,6 +316,10 @@ Entries in this data set follow the same form as those of the .I MacroList option above. [this option is not inhereted from OpenDKIM] +Mail sent via connections where macros that are in MacroListVerify are +provided will be not DKIM signed. If the Mode is 's', then no actions will +be performed. + .TP .I Mode (string) Selects operating modes. The string is a concatenation of characters that @@ -327,6 +339,11 @@ be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; +The action to sign or verify is also affected by the InternalHosts, MacroList, +and MacroListVerify options. Those options may preclude signing or +verification in some cases, but will not enable signing or verifying if not +allowed by Mode. + .TP .I MinimumKeyBits (integer) Establishes a minimum key size for acceptable RSA signatures. Signatures with From 6d1c796a5e97fb350a0b07c9e1141d5164603502 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 19:49:12 -0500 Subject: [PATCH 12/14] Fix subdomain signing with top-level organizational domain (LP: #1999434) --- CHANGES | 2 ++ dkimpy_milter/__init__.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 4c9a530..2085060 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ - Improve documentation of inter-relationship between Mode, InternalHosts, MacroList, and MacroListVerify options in dkimpy-milter.conf.5 (Closes: #969215) + - Fix subdomain signing with top-level organizational domain (LP: #1999434) + - Thanks to Matthias Hunstock for the report and the fix 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index fa05ce4..7fe56f5 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -304,6 +304,7 @@ class dkimMilter(Milter.Base): keytabledata = self.conf.get('privateRSATable')[keytablekey] try: self.fdomain = keytabledata[0] + self.domain.append(self.fdomain) self.selectorRSA = keytabledata[1] self.privkeyRSA = keytabledata[2] except: @@ -314,6 +315,7 @@ class dkimMilter(Milter.Base): keytabledata = self.conf.get('privateEd25519Table')[keytablekey] try: self.fdomain = keytabledata[0] + self.domain.append(self.fdomain) self.selectorEd25519 = keytabledata[1] self.privkeyEd25519 = keytabledata[2] except: From 16ab67db0fcd42c418490cbc2845f4d259681e2c Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 19:59:03 -0500 Subject: [PATCH 13/14] Fix comma separated list processing in dkimpy_milter/config.py (LP: #1901445) --- CHANGES | 2 ++ dkimpy_milter/config.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 2085060..e7e041e 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,8 @@ #969215) - Fix subdomain signing with top-level organizational domain (LP: #1999434) - Thanks to Matthias Hunstock for the report and the fix + - Fix comma separated list processing in dkimpy_milter/config.py + (LP: #1901445) 1.2.2 2020-08-09 - Improve README.md formating for markdown display on pypi diff --git a/dkimpy_milter/config.py b/dkimpy_milter/config.py index d52b5a4..1cad1cd 100644 --- a/dkimpy_milter/config.py +++ b/dkimpy_milter/config.py @@ -322,9 +322,15 @@ def _dataset_to_list(dataset): return dsd # If it's a str and csl, it has one value and we return a list if dataset[:4] == 'csl:': - return [dataset[4:].strip().strip(',')] + datalist = dataset[4:].split(',') + for item in datalist: + datalist[datalist.index(item)] = item.strip().strip(',') + return datalist else: - return [dataset.strip().strip(',')] + datalist = dataset.split(',') + for item in datalist: + datalist[datalist.index(item)] = item.strip().strip(',') + return datalist if dataset[-3:] == '.db' or dataset[:3] == 'db:': # This is a Sleepycat (Oracle) DB dataset, which we dont support raise dkim.ParameterError('Unsupported dataset db datase: {0}' From c2409105dc807572c5254397f825991a20452b5b Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Sun, 26 Feb 2023 20:13:46 -0500 Subject: [PATCH 14/14] Change version to 1.2.3 (these are all bug fixes) and set release date --- CHANGES | 2 +- dkimpy_milter/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index e7e041e..c4e2315 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -1.3.0 +1.2.3 2023-02-26 - Improve support for non-ASCII email messages. Anything UTF-8 should work (including correct signing/verification). For messages that contain header fields with non-ASCII or UTF-8 content, signatures are likely fail diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 7fe56f5..a6bb26f 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -39,7 +39,7 @@ from dkimpy_milter.util import write_pid from dkimpy_milter.util import get_keys from dkimpy_milter.util import fold -__version__ = "1.2.0" +__version__ = "1.2.3" FWS = re.compile(r'\r?\n[ \t]+') diff --git a/setup.py b/setup.py index cf59b8d..e760bec 100644 --- a/setup.py +++ b/setup.py @@ -89,7 +89,7 @@ except ImportError: # If PyDNS is not installed, prefer dnspython setup( name='dkimpy-milter', - version='1.3.0', + version='1.2.3', author='Scott Kitterman', author_email='scott@kitterman.com', url='https://launchpad.net/dkimpy-milter',