Don't log message content by default.

Right now, it is quite easy to end up logging the whole message in the
log when verifying signatures. This can result in wasted resources
writing the log to disk and increasing memory usage. This can also be
a private data leak if logging is put in DEBUG in a production
environment.
This commit is contained in:
Jonathan Bastien-Filiatrault
2018-12-12 15:30:47 -05:00
parent 882d14c514
commit 82bef5983b
+18 -11
View File
@@ -112,13 +112,15 @@ CV_None = b'none'
class HashThrough(object): class HashThrough(object):
def __init__(self, hasher): def __init__(self, hasher, debug=False):
self.data = [] self.data = []
self.hasher = hasher self.hasher = hasher
self.name = hasher.name self.name = hasher.name
self.debug = debug
def update(self, data): def update(self, data):
self.data.append(data) if self.debug:
self.data.append(data)
return self.hasher.update(data) return self.hasher.update(data)
def digest(self): def digest(self):
@@ -460,11 +462,12 @@ class DomainSigner(object):
#: @param logger: a logger to which debug info will be written (default None) #: @param logger: a logger to which debug info will be written (default None)
#: @param signature_algorithm: the signing algorithm to use when signing #: @param signature_algorithm: the signing algorithm to use when signing
def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256', def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256',
minkey=1024): minkey=1024, debug_content=False):
self.set_message(message) self.set_message(message)
if logger is None: if logger is None:
logger = get_default_logger() logger = get_default_logger()
self.logger = logger self.logger = logger
self.debug_content = debug_content and logger.isEnabledFor(logging.DEBUG)
if signature_algorithm not in HASH_ALGORITHMS: if signature_algorithm not in HASH_ALGORITHMS:
raise ParameterError( raise ParameterError(
"Unsupported signature algorithm: "+signature_algorithm) "Unsupported signature algorithm: "+signature_algorithm)
@@ -610,13 +613,14 @@ class DomainSigner(object):
header_value = fold(header_value, namelen=len(header_name)) header_value = fold(header_value, namelen=len(header_name))
header_value = RE_BTAG.sub(b'\\1',header_value) header_value = RE_BTAG.sub(b'\\1',header_value)
header = (header_name, b' ' + header_value) header = (header_name, b' ' + header_value)
h = HashThrough(self.hasher()) h = HashThrough(self.hasher(), self.debug_content)
sig = dict(fields) sig = dict(fields)
headers = canon_policy.canonicalize_headers(self.headers) headers = canon_policy.canonicalize_headers(self.headers)
self.signed_headers = hash_headers( self.signed_headers = hash_headers(
h, canon_policy, headers, include_headers, header, sig) h, canon_policy, headers, include_headers, header, sig)
self.logger.debug("sign %s headers: %r" % (header_name, h.hashed())) if self.debug_content:
self.logger.debug("sign %s headers: %r" % (header_name, h.hashed()))
if self.signature_algorithm == b'rsa-sha256' or self.signature_algorithm == b'rsa-sha1': if self.signature_algorithm == b'rsa-sha256' or self.signature_algorithm == b'rsa-sha1':
try: try:
@@ -662,13 +666,14 @@ class DomainSigner(object):
# validate body if present # validate body if present
if b'bh' in sig: if b'bh' in sig:
h = HashThrough(hasher()) h = HashThrough(hasher(), self.debug_content)
body = canon_policy.canonicalize_body(self.body) body = canon_policy.canonicalize_body(self.body)
if b'l' in sig: if b'l' in sig:
body = body[:int(sig[b'l'])] body = body[:int(sig[b'l'])]
h.update(body) h.update(body)
self.logger.debug("body hashed: %r" % h.hashed()) if self.debug_content:
self.logger.debug("body hashed: %r" % h.hashed())
bodyhash = h.digest() bodyhash = h.digest()
self.logger.debug("bh: %s" % base64.b64encode(bodyhash)) self.logger.debug("bh: %s" % base64.b64encode(bodyhash))
@@ -687,12 +692,13 @@ class DomainSigner(object):
# generalized to check for extras of other singleton headers. # generalized to check for extras of other singleton headers.
if b'from' in include_headers: if b'from' in include_headers:
include_headers.append(b'from') include_headers.append(b'from')
h = HashThrough(hasher()) h = HashThrough(hasher(), self.debug_content)
headers = canon_policy.canonicalize_headers(self.headers) headers = canon_policy.canonicalize_headers(self.headers)
self.signed_headers = hash_headers( self.signed_headers = hash_headers(
h, canon_policy, headers, include_headers, sig_header, sig) h, canon_policy, headers, include_headers, sig_header, sig)
self.logger.debug("signed for %s: %r" % (sig_header[0], h.hashed())) if self.debug_content:
self.logger.debug("signed for %s: %r" % (sig_header[0], h.hashed()))
signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b'])) signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b']))
if ktag == b'rsa': if ktag == b'rsa':
try: try:
@@ -1008,9 +1014,10 @@ class ARC(DomainSigner):
canon_policy = CanonicalizationPolicy.from_c_value(b'relaxed/relaxed') canon_policy = CanonicalizationPolicy.from_c_value(b'relaxed/relaxed')
self.hasher = HASH_ALGORITHMS[self.signature_algorithm] self.hasher = HASH_ALGORITHMS[self.signature_algorithm]
h = HashThrough(self.hasher()) h = HashThrough(self.hasher(), self.debug_content)
h.update(canon_policy.canonicalize_body(self.body)) h.update(canon_policy.canonicalize_body(self.body))
self.logger.debug("sign ams body hashed: %r" % h.hashed()) if self.debug_content:
self.logger.debug("sign ams body hashed: %r" % h.hashed())
bodyhash = base64.b64encode(h.digest()) bodyhash = base64.b64encode(h.digest())
# Compute ARC-Message-Signature # Compute ARC-Message-Signature