Add support for specifying DNSTimeout (bumps required dkimpy version to 1.0)

This commit is contained in:
Scott Kitterman
2020-01-03 16:14:08 -05:00
parent 042005b38d
commit 8a2760531b
8 changed files with 65 additions and 8 deletions
+1
View File
@@ -2,6 +2,7 @@
- Add support for SigningTable, KeyTable, and KeyTableEd25519 (LP: #1797397) - Add support for SigningTable, KeyTable, and KeyTableEd25519 (LP: #1797397)
- Add support for specifying MinimumKeyBits for RSA signatures - Add support for specifying MinimumKeyBits for RSA signatures
- Add support for SignHeaders feature, thanks to Ralph Seichter for the patch - Add support for SignHeaders feature, thanks to Ralph Seichter for the patch
- Add support for specifying DNSTimeout (bumps required dkimpy version to 1.0)
- Add information on message content conversion to README - Add information on message content conversion to README
- Add new expand option to setup.py so various file system locations can be - Add new expand option to setup.py so various file system locations can be
specified at build/install time rather than being hard coded specified at build/install time rather than being hard coded
+1 -1
View File
@@ -50,7 +50,7 @@ Subdomain support implemented verified
Test suite implemented verified Test suite implemented verified
1.2.0 1.2.0
DNSTimeout (dkimpy 1.0) DNSTimeout (dkimpy 1.0) implemented verified by inspection
KeyTable implemented verified KeyTable implemented verified
KeytableEd25519 implemented verified KeytableEd25519 implemented verified
MinimumKeyBits implemented verified MinimumKeyBits implemented verified
+1 -1
View File
@@ -359,7 +359,7 @@ class dkimMilter(Milter.Base):
res = False res = False
self.header_a = None self.header_a = None
for y in range(self.has_dkim): # Verify _ALL_ the signatures for y in range(self.has_dkim): # Verify _ALL_ the signatures
d = dkim.DKIM(txt, minkey=self.conf.get('MinimumKeyBits')) d = dkim.DKIM(txt, minkey=self.conf.get('MinimumKeyBits'), timeout=self.conf.get('DNSTimeout'))
try: try:
dnsoverride = self.conf.get('DNSOverride') dnsoverride = self.conf.get('DNSOverride')
if isinstance(dnsoverride, str): if isinstance(dnsoverride, str):
+3 -1
View File
@@ -50,6 +50,7 @@ defaultConfigData = {
'MacroList': '', 'MacroList': '',
'MacroListVerify': '', 'MacroListVerify': '',
'DNSOverride': None, 'DNSOverride': None,
'DNSTimeout': 5,
'SubDomains': False, 'SubDomains': False,
'SigningTable': None, 'SigningTable': None,
'debugLevel': 0 # Undocumented config item for developer use 'debugLevel': 0 # Undocumented config item for developer use
@@ -158,7 +159,7 @@ class HostsDataset(object):
'''Get validated PTR name of IP address''' '''Get validated PTR name of IP address'''
results = [] results = []
s = Session() s = Session()
ptrnames = s.dns(source.reverse_pointer, 'PTR') ptrnames = s.dns(source.reverse_pointer, 'PTR', timeout=self.conf.get('DNSTimeout'))
for name in ptrnames: for name in ptrnames:
if isinstance(source, ipaddress.IPv4Address): if isinstance(source, ipaddress.IPv4Address):
ips = s.dns(name, 'A') ips = s.dns(name, 'A')
@@ -357,6 +358,7 @@ def _readConfigFile(path, configData=None, configGlobal={}):
'MacroList': 'dataset', 'MacroList': 'dataset',
'MacroListVerify': 'dataset', 'MacroListVerify': 'dataset',
'DNSOverride': 'str', 'DNSOverride': 'str',
'DNSTimeout': 'int',
'debugLevel': 'int', 'debugLevel': 'int',
'SignHeaders': 'dataset' 'SignHeaders': 'dataset'
} }
+3 -3
View File
@@ -88,7 +88,7 @@ class Session(object):
result = self.dns(cname, qtype, cnames=cnames) result = self.dns(cname, qtype, cnames=cnames)
return result return result
def DNSLookup_pydns(name, qtype, tcpfallback=True, timeout=30): def DNSLookup_pydns(name, qtype, tcpfallback=True, timeout=5):
try: try:
# FIXME: To be thread safe, we create a fresh DnsRequest with # FIXME: To be thread safe, we create a fresh DnsRequest with
# each call. It would be more efficient to reuse # each call. It would be more efficient to reuse
@@ -114,11 +114,11 @@ def DNSLookup_pydns(name, qtype, tcpfallback=True, timeout=30):
except IOError as x: except IOError as x:
raise DNS.DNSError('DNS: ' + str(x)) raise DNS.DNSError('DNS: ' + str(x))
def DNSLookup_dnspython(name,qtype,tcpfallback=True,timeout=30): def DNSLookup_dnspython(name,qtype,tcpfallback=True,timeout=5):
retVal = [] retVal = []
try: try:
# FIXME: how to disable TCP fallback in dnspython if not tcpfallback? # FIXME: how to disable TCP fallback in dnspython if not tcpfallback?
answers = dns.resolver.query(name, qtype) answers = dns.resolver.query(name, qtype, raise_on_no_answer=False, lifetime=timeout)
for rdata in answers: for rdata in answers:
if qtype == 'A' or qtype == 'AAAA': if qtype == 'A' or qtype == 'AAAA':
retVal.append(((name, qtype), rdata.address)) retVal.append(((name, qtype), rdata.address))
+27
View File
@@ -358,6 +358,12 @@ consulting the DNS on each message. This is useful primarily for
testing purposes in environments where it is awkward to modify the testing purposes in environments where it is awkward to modify the
system DNS resolution. It should not be used in production. system DNS resolution. It should not be used in production.
.TP
.I DNSTimeout (integer)
Sets the DNS timeout in seconds. A value of 0 causes no wait (this is
different than opendkim). The default is 5. See also the NOTES section
below.
.TP .TP
.I PeerList (dataset) .I PeerList (dataset)
Identifies a set of "peers" that identifies clients whose connections Identifies a set of "peers" that identifies clients whose connections
@@ -511,6 +517,27 @@ unless an alternate
.I group .I group
is specified. is specified.
.SH NOTES
When using DNS timeouts (see the
.I DNSTimeout
option above), be sure not to use a timeout that is larger than the timeout
being used for interaction between
.I sendmail
and the filter. Otherwise, the MTA could abort a message while waiting for
a reply from the filter, which in turn is still waiting for a DNS reply. This
must take into accout that the timeout is per DNS lookup so the total DNS wait
time may be subustantially loner than the value specified in
.I DNSTimeout
\. There is a DNS lookup for each connection if the
.I InternalHosts
option is in use and one for DKIM public key record lookup for each algorithm
per signature per message (i.e. potentially two lookups per signature).
.SH FILES
.TP
.I /usr/local/etc/dkimpy-milter/dkimpy-milter.conf
Default location of this file.
.SH "AUTHORS" .SH "AUTHORS"
\ddkimpy-milter\fR was written by Scott Kitterman <scott@kitterman.com>. \ddkimpy-milter\fR was written by Scott Kitterman <scott@kitterman.com>.
It is based on dkim-milter.py Copyright (c) 2001-2013 Business Management Systems, Inc. It is based on dkim-milter.py Copyright (c) 2001-2013 Business Management Systems, Inc.
+27
View File
@@ -358,6 +358,12 @@ consulting the DNS on each message. This is useful primarily for
testing purposes in environments where it is awkward to modify the testing purposes in environments where it is awkward to modify the
system DNS resolution. It should not be used in production. system DNS resolution. It should not be used in production.
.TP
.I DNSTimeout (integer)
Sets the DNS timeout in seconds. A value of 0 causes no wait (this is
different than opendkim). The default is 5. See also the NOTES section
below.
.TP .TP
.I PeerList (dataset) .I PeerList (dataset)
Identifies a set of "peers" that identifies clients whose connections Identifies a set of "peers" that identifies clients whose connections
@@ -511,6 +517,27 @@ unless an alternate
.I group .I group
is specified. is specified.
.SH NOTES
When using DNS timeouts (see the
.I DNSTimeout
option above), be sure not to use a timeout that is larger than the timeout
being used for interaction between
.I sendmail
and the filter. Otherwise, the MTA could abort a message while waiting for
a reply from the filter, which in turn is still waiting for a DNS reply. This
must take into accout that the timeout is per DNS lookup so the total DNS wait
time may be subustantially loner than the value specified in
.I DNSTimeout
\. There is a DNS lookup for each connection if the
.I InternalHosts
option is in use and one for DKIM public key record lookup for each algorithm
per signature per message (i.e. potentially two lookups per signature).
.SH FILES
.TP
.I @CONFDIR@/dkimpy-milter.conf
Default location of this file.
.SH "AUTHORS" .SH "AUTHORS"
\ddkimpy-milter\fR was written by Scott Kitterman <scott@kitterman.com>. \ddkimpy-milter\fR was written by Scott Kitterman <scott@kitterman.com>.
It is based on dkim-milter.py Copyright (c) 2001-2013 Business Management Systems, Inc. It is based on dkim-milter.py Copyright (c) 2001-2013 Business Management Systems, Inc.
+2 -2
View File
@@ -80,9 +80,9 @@ class FileMacroExpand(distutils.cmd.Command):
kw = {} # Work-around for lack of 'or' requires in setuptools. kw = {} # Work-around for lack of 'or' requires in setuptools.
try: try:
import dns import dns
kw['install_requires'] = ['dkimpy>=0.7', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'dnspython'] kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'dnspython>=1.16.0']
except ImportError: # If PyDNS is not installed, prefer dnspython except ImportError: # If PyDNS is not installed, prefer dnspython
kw['install_requires'] = ['dkimpy>=0.7', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS'] kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS']
setup( setup(
name='dkimpy-milter', name='dkimpy-milter',