Continue refactoring

- Add more encryption strategies.
- Replace tuples (email + key) with dedicated objects.
This commit is contained in:
Piotr F. Mieszkowski 2022-09-27 22:35:38 +02:00 committed by Gitea
parent 8963eee47f
commit ce6a0c5466
2 changed files with 50 additions and 24 deletions

View File

@ -34,7 +34,7 @@ from M2Crypto import BIO, SMIME, X509
import logging
import lacre.text as text
import lacre.config as conf
from lacre.mailop import KeepIntact, OpenPGPEncrypt
from lacre.mailop import KeepIntact, InlineOpenPGPEncrypt, MimeOpenPGPEncrypt
LOG = logging.getLogger(__name__)
@ -93,26 +93,31 @@ def _sort_gpg_recipients(gpg_to):
gpg_to_cmdline_inline.extend(rcpt.key().split(','))
else:
# Log message only if an unknown style is defined
if conf.config_item_set('pgp_style', rcpt[0]):
LOG.debug("Style %s for recipient %s is not known. Use default as fallback." % (conf.get_item("pgp_style", rcpt[0]), rcpt[0]))
if conf.config_item_set('pgp_style', rcpt.email()):
LOG.debug("Style %s for recipient %s is not known. Use default as fallback." % (conf.get_item("pgp_style", rcpt.email()), rcpt.email()))
# If no style is in settings defined for recipient, use default from settings
if default_to_pgp_mime:
gpg_to_smtp_mime.append(rcpt[0])
gpg_to_cmdline_mime.extend(rcpt[1].split(','))
gpg_to_smtp_mime.append(rcpt.email())
gpg_to_cmdline_mime.extend(rcpt.key().split(','))
else:
gpg_to_smtp_inline.append(rcpt[0])
gpg_to_cmdline_inline.extend(rcpt[1].split(','))
gpg_to_smtp_inline.append(rcpt.email())
gpg_to_cmdline_inline.extend(rcpt.key().split(','))
return gpg_to_smtp_mime, gpg_to_cmdline_mime, gpg_to_smtp_inline, gpg_to_cmdline_inline
def _gpg_encrypt_and_deliver(message, cmdline, to, encrypt_f):
def _gpg_encrypt_and_return(message, cmdline, to, encrypt_f):
msg_copy = copy.deepcopy(message)
_customise_headers(msg_copy)
encrypted_payloads = encrypt_f(msg_copy, cmdline)
msg_copy.set_payload(encrypted_payloads)
send_msg(msg_copy.as_string(), to)
return msg_copy.as_string()
def _gpg_encrypt_and_deliver(message, cmdline, to, encrypt_f):
out = _gpg_encrypt_and_return(message, cmdline, to, encrypt_f)
send_msg(out, to)
def _customise_headers(msg_copy):
@ -179,7 +184,7 @@ def _identify_gpg_recipients(recipients):
# GnuPG keys found in our keyring.
keys = _load_keys()
LOG.info(f'Processisng recipients: {recipients!r}')
LOG.info(f'Processisng recipients: {recipients!r}; keys: {keys!r}')
for to in recipients:
LOG.info(f"At to={to!r}")
own_key = _try_configured_key(to, keys)
@ -515,8 +520,8 @@ def delivery_plan(recipients):
keyhome = conf.get_item('gpg', 'keyhome')
return [OpenPGPEncrypt(gpg_mime_to, gpg_mime_cmd, keyhome),
OpenPGPEncrypt(gpg_inline_to, gpg_inline_cmd, keyhome),
return [MimeOpenPGPEncrypt(gpg_mime_to, gpg_mime_cmd, keyhome),
InlineOpenPGPEncrypt(gpg_inline_to, gpg_inline_cmd, keyhome),
KeepIntact(ungpg_to)]

View File

@ -14,7 +14,7 @@ There are 3 operations available:
"""
import logging
import GnuPG
import lacre.mailgate as mailgate
LOG = logging.getLogger(__name__)
@ -52,20 +52,41 @@ class OpenPGPEncrypt(MailOperation):
self._key = key
self._keyhome = keyhome
def perform(self, message):
"""Encrypt MESSAGE with the given key."""
enc = GnuPG.GPGEncryptor(self._keyhome)
enc.update(message)
encrypted, err = enc.encrypt()
if err:
LOG.error(f"Unable to encrypt message, delivering cleartext (gpg exit code: {err})")
return message
else:
return encrypted
def extend_keys(self, keys):
"""Register GPG keys to encrypt this message for."""
self._keys.extend(keys)
def __repr__(self):
"""Generate a representation with just method and key."""
return f"<OpenPGP {self._recipients} {self._key}>"
return f"<{type(self).__name__} {self._recipients} {self._key}>"
class InlineOpenPGPEncrypt(OpenPGPEncrypt):
"""Inline encryption strategy."""
def perform(self, msg):
"""Encrypt with PGP Inline."""
LOG.debug('Sending PGP/Inline...')
return mailgate._gpg_encrypt_and_return(msg,
self._keys, self._recipients,
mailgate._encrypt_all_payloads_inline)
class MimeOpenPGPEncrypt(OpenPGPEncrypt):
"""MIME encryption strategy."""
def __init__(self, recipients, keys, keyhome):
"""Initialise strategy object."""
super().__init__(recipients)
self._keys = keys
self._keyhome = keyhome
def perform(self, msg):
"""Encrypt with PGP MIME."""
LOG.debug('Sending PGP/MIME...')
return mailgate._gpg_encrypt_and_return(msg,
self._keys, self._recipients,
mailgate._encrypt_all_payloads_mime)
class SMimeEncrypt(MailOperation):