Convert __init__.py to python3
The main work here is about bytes vs. strings. This work was confusing for several reasons: * pymilter thinks that headers are all strings, but body is bytes * dkimpy wants to deal with bytes objects generally (though it accepts a string object as an ed25519 secret key for some reason, despite requiring bytes as an RSA secret key) * authres.AuthenticationResultsHeader object converts easily to a string, but has no direct bytes conversion. meanwhile, it wants its arguments as strings, but will accept them if they are bytes and convert them with something like str(), which leaves weird cruft like "header.a=b'ed25519-sha256'" * dkimpy_milter/utils.py contains fold() which expects bytes * self.fp needs to accumulate the on-the-wire version of the message as a whole (so it needs to be bytes). That means converting the headers. Header names and values are US-ASCII, per §2.2 of RFC 5322, so they should be convertible cleanly, but we still have to convert them explicitly so that python knows the right thing to do. At any rate, tests/runtests all passes with these changes, and the output for both Authentication-Results: and DKIM-Signature headers looks the same.
This commit is contained in:
+30
-31
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user