Fix merge conflicts

This commit is contained in:
Scott Kitterman
2019-02-24 07:22:58 -05:00
6 changed files with 54 additions and 55 deletions
+31 -32
View File
@@ -1,4 +1,4 @@
#! /usr/bin/python2 #! /usr/bin/python3
# Original dkim-milter.py code: # Original dkim-milter.py code:
# Author: Stuart D. Gathman <stuart@bmsi.com> # Author: Stuart D. Gathman <stuart@bmsi.com>
# Copyright 2007 Business Management Systems, Inc. # Copyright 2007 Business Management Systems, Inc.
@@ -28,8 +28,9 @@ import dkim
import authres import authres
import os import os
import tempfile import tempfile
import StringIO import io
import re import re
import codecs
from Milter.utils import parse_addr, parseaddr from Milter.utils import parse_addr, parseaddr
import dkimpy_milter.config as config import dkimpy_milter.config as config
from dkimpy_milter.util import drop_privileges from dkimpy_milter.util import drop_privileges
@@ -110,7 +111,7 @@ class dkimMilter(Milter.Base):
def envfrom(self, f, *str): def envfrom(self, f, *str):
if milterconfig.get('Syslog') and milterconfig.get('debugLevel') >= 2: if milterconfig.get('Syslog') and milterconfig.get('debugLevel') >= 2:
syslog.syslog("mail from: {0} {1}".format(f, str)) syslog.syslog("mail from: {0} {1}".format(f, str))
self.fp = StringIO.StringIO() self.fp = io.BytesIO()
self.mailfrom = f self.mailfrom = f
t = parse_addr(f) t = parse_addr(f)
if len(t) == 2: if len(t) == 2:
@@ -142,13 +143,13 @@ class dkimMilter(Milter.Base):
elif lname == 'authentication-results': elif lname == 'authentication-results':
self.arheaders.append(val) self.arheaders.append(val)
if self.fp: if self.fp:
self.fp.write("%s: %s\n" % (name, val)) self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii')))
return Milter.CONTINUE return Milter.CONTINUE
@Milter.noreply @Milter.noreply
def eoh(self): def eoh(self):
if self.fp: if self.fp:
self.fp.write("\n") # terminate headers self.fp.write(b"\n") # terminate headers
self.bodysize = 0 self.bodysize = 0
return Milter.CONTINUE return Milter.CONTINUE
@@ -195,20 +196,20 @@ class dkimMilter(Milter.Base):
h = authres.AuthenticationResultsHeader(authserv_id= h = authres.AuthenticationResultsHeader(authserv_id=
self.AuthservID, self.AuthservID,
results=self.arresults) results=self.arresults)
h = fold(str(h)) h = fold(codecs.encode(str(h), 'ascii'))
if (milterconfig.get('Syslog') and if (milterconfig.get('Syslog') and
milterconfig.get('debugLevel') >= 2): milterconfig.get('debugLevel') >= 2):
syslog.syslog(str(h)) syslog.syslog(codecs.decode(h, 'ascii'))
name, val = str(h).split(': ', 1) name, val = codecs.decode(h, 'ascii').split(': ', 1)
self.addheader(name, val, 0) self.addheader(name, val, 0)
return Milter.CONTINUE return Milter.CONTINUE
def sign_dkim(self, txt): def sign_dkim(self, txt):
canon = milterconfig.get('Canonicalization') canon = codecs.encode(milterconfig.get('Canonicalization'), 'ascii')
canonicalize = [] canonicalize = []
if len(canon.split('/')) == 2: if len(canon.split(b'/')) == 2:
canonicalize.append(canon.split('/')[0]) canonicalize.append(canon.split(b'/')[0])
canonicalize.append(canon.split('/')[1]) canonicalize.append(canon.split(b'/')[1])
else: else:
canonicalize.append(canon) canonicalize.append(canon)
canonicalize.append(canon) canonicalize.append(canon)
@@ -218,11 +219,12 @@ class dkimMilter(Milter.Base):
try: try:
if privateRSA: if privateRSA:
d = dkim.DKIM(txt) d = dkim.DKIM(txt)
h = d.sign(milterconfig.get('Selector'), self.fdomain, h = d.sign(codecs.encode(milterconfig.get('Selector'), 'ascii'), codecs.encode(self.fdomain, 'ascii'),
privateRSA, canonicalize=(canonicalize[0], codecs.encode(privateRSA, 'ascii'),
canonicalize[1])) canonicalize=(canonicalize[0],
name, val = h.split(': ', 1) canonicalize[1]))
self.addheader(name, val.strip().replace('\r\n', '\n'), 0) name, val = h.split(b': ', 1)
self.addheader(codecs.decode(name, 'ascii'), codecs.decode(val, 'ascii').strip().replace('\r\n', '\n'), 0)
if (milterconfig.get('Syslog') and if (milterconfig.get('Syslog') and
(milterconfig.get('SyslogSuccess') (milterconfig.get('SyslogSuccess')
or milterconfig.get('debugLevel') >= 1)): or milterconfig.get('debugLevel') >= 1)):
@@ -233,12 +235,12 @@ class dkimMilter(Milter.Base):
d.domain.lower())) d.domain.lower()))
if privateEd25519: if privateEd25519:
d = dkim.DKIM(txt) d = dkim.DKIM(txt)
h = d.sign(milterconfig.get('SelectorEd25519'), self.fdomain, h = d.sign(codecs.encode(milterconfig.get('SelectorEd25519'), 'ascii'), codecs.encode(self.fdomain, 'ascii'),
privateEd25519, canonicalize=(canonicalize[0], privateEd25519, canonicalize=(canonicalize[0],
canonicalize[1]), canonicalize[1]),
signature_algorithm='ed25519-sha256') signature_algorithm=b'ed25519-sha256')
name, val = h.split(': ', 1) name, val = h.split(b': ', 1)
self.addheader(name, val.strip().replace('\r\n', '\n'), 0) self.addheader(codecs.decode(name, 'ascii'), codecs.decode(val, 'ascii').strip().replace('\r\n', '\n'), 0)
if (milterconfig.get('Syslog') and if (milterconfig.get('Syslog') and
(milterconfig.get('SyslogSuccess') (milterconfig.get('SyslogSuccess')
or milterconfig.get('debugLevel') >= 1)): or milterconfig.get('debugLevel') >= 1)):
@@ -266,20 +268,17 @@ class dkimMilter(Milter.Base):
res = d.verify(idx=y, dnsfunc=lambda _x: dnsoverride) res = d.verify(idx=y, dnsfunc=lambda _x: dnsoverride)
else: else:
res = d.verify(idx=y) res = d.verify(idx=y)
algo = codecs.decode(d.signature_fields.get(b'a'), 'ascii')
if res: if res:
if d.signature_fields.get(b'a') == 'ed25519-sha256': if algo == 'ed25519-sha256':
self.dkim_comment = ('Good {0} signature' self.dkim_comment = ('Good {0} signature'
.format(d.signature_fields .format(algo))
.get(b'a')))
else: else:
self.dkim_comment = ('Good {0} bit {1} signature' self.dkim_comment = ('Good {0} bit {1} signature'
.format(d.keysize, .format(d.keysize, algo))
d.signature_fields
.get(b'a')))
else: else:
self.dkim_comment = ('Bad {0} bit {1} signature.' self.dkim_comment = ('Bad {0} bit {1} signature.'
.format(d.keysize, .format(d.keysize, algo))
d.signature_fields.get(b'a')))
except dkim.DKIMException as x: except dkim.DKIMException as x:
self.dkim_comment = str(x) self.dkim_comment = str(x)
if milterconfig.get('Syslog'): if milterconfig.get('Syslog'):
@@ -288,9 +287,9 @@ class dkimMilter(Milter.Base):
self.dkim_comment = str(x) self.dkim_comment = str(x)
if milterconfig.get('Syslog'): if milterconfig.get('Syslog'):
syslog.syslog("check_dkim: {0}".format(x)) syslog.syslog("check_dkim: {0}".format(x))
self.header_i = d.signature_fields.get(b'i') self.header_i = codecs.decode(d.signature_fields.get(b'i'), 'ascii')
self.header_d = d.signature_fields.get(b'd') self.header_d = codecs.decode(d.signature_fields.get(b'd'), 'ascii')
self.header_a = d.signature_fields.get(b'a') self.header_a = codecs.decode(d.signature_fields.get(b'a'), 'ascii')
if res: if res:
if (milterconfig.get('Syslog') and if (milterconfig.get('Syslog') and
(milterconfig.get('SyslogSuccess') or (milterconfig.get('SyslogSuccess') or
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2 #!/usr/bin/python3
from dkimpy_milter import main from dkimpy_milter import main
+10 -10
View File
@@ -31,13 +31,13 @@ import stat
import dkim import dkim
import socket import socket
import ipaddress import ipaddress
from dnsplug import Session from .dnsplug import Session
# default values # default values
defaultConfigData = { defaultConfigData = {
'Syslog': 'yes', 'Syslog': 'yes',
'SyslogFacility': 'mail', 'SyslogFacility': 'mail',
'UMask': 007, 'UMask': 0o07,
'Mode': 'sv', 'Mode': 'sv',
'Socket': 'local:/var/run/dkimpy-milter/dkimpy-milter.sock', 'Socket': 'local:/var/run/dkimpy-milter/dkimpy-milter.sock',
'PidFile': '/var/run/dkimpy-milter/dkimpy-milter.pid', 'PidFile': '/var/run/dkimpy-milter/dkimpy-milter.pid',
@@ -85,14 +85,14 @@ class HostsDataset(object):
self.item = item[1:] self.item = item[1:]
self.negative = True self.negative = True
try: try:
self.item = ipaddress.ip_address(unicode(self.item, "utf-8")) self.item = ipaddress.ip_address(str(self.item, "utf-8"))
if isinstance(self.item, ipaddress.IPv4Address): if isinstance(self.item, ipaddress.IPv4Address):
self.isipv4 = True self.isipv4 = True
elif isinstance(self.item, ipaddress.IPv6Address): elif isinstance(self.item, ipaddress.IPv6Address):
self.isipv6 = True self.isipv6 = True
except ValueError as e: except ValueError as e:
try: try:
self.item = ipaddress.ip_network(unicode self.item = ipaddress.ip_network(str
(self.item, "utf-8"), (self.item, "utf-8"),
strict=False) strict=False)
if isinstance(self.item, ipaddress.IPv4Network): if isinstance(self.item, ipaddress.IPv4Network):
@@ -110,7 +110,7 @@ class HostsDataset(object):
def match(self, connectip): def match(self, connectip):
'''Check if the connect IP is part of the dataset''' '''Check if the connect IP is part of the dataset'''
source = ipaddress.ip_address(unicode(connectip, "utf-8")) source = ipaddress.ip_address(str(connectip, "utf-8"))
for item in self.dataset: for item in self.dataset:
if item.isdomain or item.ishostname: if item.isdomain or item.ishostname:
result = self.matchname(source) # Match host/domains first result = self.matchname(source) # Match host/domains first
@@ -160,13 +160,13 @@ class HostsDataset(object):
if isinstance(source, ipaddress.IPv4Address): if isinstance(source, ipaddress.IPv4Address):
ips = s.dns(name, 'A') ips = s.dns(name, 'A')
for ip in ips: for ip in ips:
ip = ipaddress.IPv4Address(unicode(ip, 'UTF-8')) ip = ipaddress.IPv4Address(str(ip, 'UTF-8'))
if ip == source: if ip == source:
results.append(name) results.append(name)
if isinstance(source, ipaddress.IPv6Address): if isinstance(source, ipaddress.IPv6Address):
ips = s.dns(name, 'AAAA') ips = s.dns(name, 'AAAA')
for ip in ips: for ip in ips:
ip = ipaddress.IPv6Address(unicode(ip, 'UTF-8')) ip = ipaddress.IPv6Address(str(ip, 'UTF-8'))
if ip == source: if ip == source:
results.append(name) results.append(name)
return results return results
@@ -225,13 +225,13 @@ def _processConfigFile(filename=None, configdata=None, useSyslog=1,
'''Load the specified config file, exit and log errors if it fails, '''Load the specified config file, exit and log errors if it fails,
otherwise return a config dictionary.''' otherwise return a config dictionary.'''
import config from . import config
if configdata is None: if configdata is None:
configdata = config.defaultConfigData configdata = config.defaultConfigData
if filename is not None: if filename is not None:
try: try:
_readConfigFile(filename, configdata) _readConfigFile(filename, configdata)
except Exception, e: except Exception as e:
raise raise
if useSyslog: if useSyslog:
syslog.syslog(e.args[0]) syslog.syslog(e.args[0])
@@ -342,7 +342,7 @@ def _readConfigFile(path, configData=None, configGlobal={}):
# check to see if it's a file # check to see if it's a file
try: try:
mode = os.stat(path)[0] mode = os.stat(path)[0]
except OSError, e: except OSError as e:
syslog.syslog(syslog.LOG_ERR, 'ERROR stating "%s": %s' syslog.syslog(syslog.LOG_ERR, 'ERROR stating "%s": %s'
% (path, e.strerror)) % (path, e.strerror))
return(configData) return(configData)
+8 -8
View File
@@ -84,7 +84,7 @@ class Session(object):
raise DNSError('Length of CNAME chain exceeds %d' % MAX_CNAME) raise DNSError('Length of CNAME chain exceeds %d' % MAX_CNAME)
cnames[name] = cname cnames[name] = cname
if cname in cnames: if cname in cnames:
raise DNSError, 'CNAME loop' raise DNSError('CNAME loop')
result = self.dns(cname, qtype, cnames=cnames) result = self.dns(cname, qtype, cnames=cnames)
return result return result
@@ -103,16 +103,16 @@ def DNSLookup_pydns(name, qtype, tcpfallback=True, timeout=30):
# #
if resp.header['tc'] == True: if resp.header['tc'] == True:
if not tcpfallback: if not tcpfallback:
raise DNS.DNSError, 'DNS: Truncated UDP Reply, SPF records should fit in a UDP packet' raise DNS.DNSError('DNS: Truncated UDP Reply, SPF records should fit in a UDP packet')
try: try:
req = DNS.DnsRequest(name, qtype=qtype, protocol='tcp', req = DNS.DnsRequest(name, qtype=qtype, protocol='tcp',
timeout=timeout) timeout=timeout)
resp = req.req() resp = req.req()
except DNS.DNSError, x: except DNS.DNSError as x:
raise DNS.DNSError, 'TCP Fallback error: ' + str(x) raise DNS.DNSError('TCP Fallback error: ' + str(x))
return [((a['name'], a['typename']), a['data']) for a in resp.answers] return [((a['name'], a['typename']), a['data']) for a in resp.answers]
except IOError, 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=30):
retVal = [] retVal = []
@@ -164,5 +164,5 @@ if __name__ == '__main__':
import sys import sys
s = Session() s = Session()
for n,t in zip(*[iter(sys.argv[1:])]*2): for n,t in zip(*[iter(sys.argv[1:])]*2):
print n,t print(n,t)
print s.dns(n,t) print(s.dns(n,t))
+3 -3
View File
@@ -24,9 +24,9 @@ description = "Domain Keys Identified Mail (DKIM) signing/verifying milter for P
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', 'ipaddress', 'dnspython'] kw['install_requires'] = ['dkimpy>=0.7', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'dnspython']
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', 'ipaddress', 'PyDNS'] kw['install_requires'] = ['dkimpy>=0.7', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'PyDNS']
setup( setup(
name='dkimpy-milter', name='dkimpy-milter',
@@ -43,7 +43,7 @@ setup(
'License :: OSI Approved :: GNU General Public License (GPL)', 'License :: OSI Approved :: GNU General Public License (GPL)',
'Natural Language :: English', 'Natural Language :: English',
'Operating System :: POSIX', 'Operating System :: POSIX',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3 :: Only',
'Topic :: Communications :: Email :: Mail Transport Agents', 'Topic :: Communications :: Email :: Mail Transport Agents',
'Topic :: Communications :: Email :: Filters', 'Topic :: Communications :: Email :: Filters',
'Topic :: Security', 'Topic :: Security',
+1 -1
View File
@@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
python2 -m dkimpy_milter "$@" python3 -m dkimpy_milter "$@"