all_sign_headers() method to get old behaviour when needed.
This commit is contained in:
+25
-8
@@ -92,6 +92,7 @@ def _remove(s, t):
|
|||||||
|
|
||||||
def select_headers(headers, include_headers):
|
def select_headers(headers, include_headers):
|
||||||
"""Select message header fields to be signed/verified.
|
"""Select message header fields to be signed/verified.
|
||||||
|
|
||||||
>>> h = [('from','biz'),('foo','bar'),('from','baz'),('subject','boring')]
|
>>> h = [('from','biz'),('foo','bar'),('from','baz'),('subject','boring')]
|
||||||
>>> i = ['from','subject','to','from']
|
>>> i = ['from','subject','to','from']
|
||||||
>>> select_headers(h,i)
|
>>> select_headers(h,i)
|
||||||
@@ -116,7 +117,7 @@ def select_headers(headers, include_headers):
|
|||||||
|
|
||||||
def hash_headers(hasher, canonicalize_headers, headers, include_headers,
|
def hash_headers(hasher, canonicalize_headers, headers, include_headers,
|
||||||
sigheaders, sig):
|
sigheaders, sig):
|
||||||
"""Sign message header fields."""
|
"""Update hash for signed message header fields."""
|
||||||
sign_headers = select_headers(headers,include_headers)
|
sign_headers = select_headers(headers,include_headers)
|
||||||
# The call to _remove() assumes that the signature b= only appears
|
# The call to _remove() assumes that the signature b= only appears
|
||||||
# once in the signature header
|
# once in the signature header
|
||||||
@@ -211,6 +212,7 @@ def rfc822_parse(message):
|
|||||||
|
|
||||||
def fold(header):
|
def fold(header):
|
||||||
"""Fold a header line into multiple crlf-separated lines at column 72.
|
"""Fold a header line into multiple crlf-separated lines at column 72.
|
||||||
|
|
||||||
>>> fold(b'foo')
|
>>> fold(b'foo')
|
||||||
'foo'
|
'foo'
|
||||||
>>> fold(b'foo '+b'foo'*24).splitlines()[0]
|
>>> fold(b'foo '+b'foo'*24).splitlines()[0]
|
||||||
@@ -257,10 +259,8 @@ class DKIM(object):
|
|||||||
'dkim-signature'
|
'dkim-signature'
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self,message,logger=None,signature_algorithm=b'rsa-sha256'):
|
def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256'):
|
||||||
(self.headers, self.body) = rfc822_parse(message)
|
self.set_message(message)
|
||||||
self.domain = None
|
|
||||||
self.selector = 'default'
|
|
||||||
if logger is None:
|
if logger is None:
|
||||||
logger = get_default_logger()
|
logger = get_default_logger()
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
@@ -268,18 +268,35 @@ class DKIM(object):
|
|||||||
raise ParameterError(
|
raise ParameterError(
|
||||||
"Unsupported signature algorithm: "+signature_algorithm)
|
"Unsupported signature algorithm: "+signature_algorithm)
|
||||||
self.signature_algorithm = signature_algorithm
|
self.signature_algorithm = signature_algorithm
|
||||||
|
#: Header fields which should be signed. Default from RFC4871
|
||||||
self.should_sign = set(DKIM.SHOULD)
|
self.should_sign = set(DKIM.SHOULD)
|
||||||
|
#: Header fields which should not be signed. Default from RFC4871
|
||||||
self.should_not_sign = set(DKIM.SHOULD_NOT)
|
self.should_not_sign = set(DKIM.SHOULD_NOT)
|
||||||
|
#: Header fields to sign an extra time to prevent additions.
|
||||||
self.frozen_sign = set(DKIM.FROZEN)
|
self.frozen_sign = set(DKIM.FROZEN)
|
||||||
|
|
||||||
def default_include_headers(self):
|
def set_message(self,message):
|
||||||
#include_headers = [x for x,y in self.headers]
|
if message:
|
||||||
|
self.headers, self.body = rfc822_parse(message)
|
||||||
|
else:
|
||||||
|
self.headers, self.body = [],''
|
||||||
|
self.domain = None
|
||||||
|
self.selector = 'default'
|
||||||
|
|
||||||
|
def default_sign_headers(self):
|
||||||
|
"""Return the default list of headers to sign: those in should_sign or
|
||||||
|
frozen_sign, with those in frozen_sign signed an extra time to prevent
|
||||||
|
additions."""
|
||||||
hset = self.should_sign | self.frozen_sign
|
hset = self.should_sign | self.frozen_sign
|
||||||
include_headers = [ x for x,y in self.headers
|
include_headers = [ x for x,y in self.headers
|
||||||
if x.lower() in hset ]
|
if x.lower() in hset ]
|
||||||
return include_headers + [ x for x in include_headers
|
return include_headers + [ x for x in include_headers
|
||||||
if x.lower() in self.frozen_sign]
|
if x.lower() in self.frozen_sign]
|
||||||
|
|
||||||
|
def all_sign_headers(self):
|
||||||
|
"""Return header list of all headers not in should_not_sign."""
|
||||||
|
return [x for x,y in self.headers if x.lower() not in self.should_not_sign]
|
||||||
|
|
||||||
def sign(self, selector, domain, privkey, identity=None,
|
def sign(self, selector, domain, privkey, identity=None,
|
||||||
canonicalize=(b'simple',b'simple'), include_headers=None, length=False):
|
canonicalize=(b'simple',b'simple'), include_headers=None, length=False):
|
||||||
try:
|
try:
|
||||||
@@ -295,7 +312,7 @@ class DKIM(object):
|
|||||||
headers = canon_policy.canonicalize_headers(self.headers)
|
headers = canon_policy.canonicalize_headers(self.headers)
|
||||||
|
|
||||||
if include_headers is None:
|
if include_headers is None:
|
||||||
include_headers = self.default_include_headers()
|
include_headers = self.default_sign_headers()
|
||||||
|
|
||||||
# rfc4871 says FROM is required
|
# rfc4871 says FROM is required
|
||||||
if 'from' not in ( x.lower() for x in include_headers ):
|
if 'from' not in ( x.lower() for x in include_headers ):
|
||||||
|
|||||||
@@ -139,9 +139,9 @@ b/mPfjC0QJTocVBq6Za/PlzfV+Py92VaCak19F4WrbVTK5Gg5tW220MCAwEAAQ=="""
|
|||||||
for body_algo in (b"simple", b"relaxed"):
|
for body_algo in (b"simple", b"relaxed"):
|
||||||
d = dkim.DKIM(message)
|
d = dkim.DKIM(message)
|
||||||
# bug requires a repeated header to manifest
|
# bug requires a repeated header to manifest
|
||||||
d.should_sign.add('received')
|
|
||||||
d.should_not_sign.remove('received')
|
d.should_not_sign.remove('received')
|
||||||
sig = d.sign(b"test", b"example.com", self.key,
|
sig = d.sign(b"test", b"example.com", self.key,
|
||||||
|
include_headers=d.all_sign_headers(),
|
||||||
canonicalize=(header_algo, body_algo))
|
canonicalize=(header_algo, body_algo))
|
||||||
dv = dkim.DKIM(sig + message)
|
dv = dkim.DKIM(sig + message)
|
||||||
res = dv.verify(dnsfunc=self.dnsfunc)
|
res = dv.verify(dnsfunc=self.dnsfunc)
|
||||||
|
|||||||
Reference in New Issue
Block a user