diff options
Diffstat (limited to 'memoryhole/protection.py')
-rw-r--r-- | memoryhole/protection.py | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/memoryhole/protection.py b/memoryhole/protection.py index 2f2d704..da99ddf 100644 --- a/memoryhole/protection.py +++ b/memoryhole/protection.py @@ -5,6 +5,8 @@ try: except ImportError: from io import StringIO from email.mime.application import MIMEApplication +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText from email.utils import getaddresses from copy import deepcopy @@ -18,7 +20,11 @@ from memoryhole.rfc3156 import ( class ProtectConfig(object): PROTECTED_HEADERS = ('subject', 'message-id', 'date', 'to', 'from') - OBSCURED_HEADERS = ('subject', 'message-id', 'date', 'to', 'from') + OBSCURED_HEADERS = { + 'subject': 'encrypted email', + 'message-id': 'C@memoryhole.example', + 'date': 'Thu, 1 Jan 1970 00:00:00 +0000', + } def __init__(self, openpgp=None, protected_headers=PROTECTED_HEADERS, obscured_headers=OBSCURED_HEADERS): @@ -28,10 +34,13 @@ class ProtectConfig(object): :param openpgp: the implementation of openpgp to use for encryption and/or signature :type openpgp: IOpenPGP - :param protected_headers: list of headers to protect + :param protected_headers: list of headers to protect in the signed + part, they need to be in lower case :type protected_headers: [str] - :param obscured_headers: list of headers to obscure - :type obscured_headers: [str] + :param obscured_headers: list of headers to obscure replacing it by + a predefined value in the email headers, + the headers need to be in lower case + :type obscured_headers: {str: str} """ if openpgp is None: openpgp = Gnupg() @@ -43,8 +52,8 @@ class ProtectConfig(object): def protect(msg, encrypt=True, config=None): """ - Protect an email with memory hole. It will protect the PROTECTED_HEADERS - and if obscure=True will obscure the OBSCURED_HEADERS + Protect an email with memory hole. It will protect the + config.protected_headers and will obscure the config.obscured_headers :param msg: the email to be protected :type msg: Message @@ -66,8 +75,10 @@ def protect(msg, encrypt=True, config=None): def _encrypt_mime(msg, config): encraddr = _recipient_addresses(msg) - newmsg, part = _fix_headers( + newmsg, part = _protect_headers( msg, MultipartEncrypted('application/pgp-encrypted'), config) + if config.obscured_headers: + newmsg, part = _obscure_headers(newmsg, part, config) encstr = config.openpgp.encrypt(part.as_string(unixfrom=False), encraddr) encmsg = MIMEApplication( @@ -85,7 +96,7 @@ def _encrypt_mime(msg, config): def _sign_mime(msg, config): - newmsg, part = _fix_headers( + newmsg, part = _protect_headers( msg, MultipartSigned('application/pgp-signature', 'pgp-sha512'), config) @@ -109,19 +120,30 @@ def _sign_mime(msg, config): return newmsg -def _fix_headers(oldmsg, newmsg, config): - part = deepcopy(oldmsg) - for hkey, hval in part.items(): - newmsg.add_header(hkey, hval) - del(part[hkey]) - _protect_headers(newmsg, part, config.protected_headers) - return newmsg, part +def _obscure_headers(msg, part, config): + headers = "" + for header, value in msg.items(): + if header.lower() in config.obscured_headers: + headers += header + ": " + value + "\n" + headerspart = MIMEText(headers, 'rfc822-headers') + # TODO: should this be an attachment???? + newpart = MIMEMultipart('mixed', _subparts=[headerspart, part]) + + for header, value in config.obscured_headers.items(): + if header in msg: + del(msg[header]) + if value: + msg.add_header(header, value) + return msg, newpart -def _protect_headers(orig, dest, headers): - for header in headers: - if header in orig: - dest.add_header(header, orig[header]) +def _protect_headers(oldmsg, newmsg, config): + part = deepcopy(oldmsg) + for header, value in part.items(): + newmsg.add_header(header, value) + if header.lower() not in config.protected_headers: + del(part[header]) + return newmsg, part def _recipient_addresses(msg): |