diff options
| author | J08nY | 2017-06-18 02:08:19 +0200 |
|---|---|---|
| committer | J08nY | 2017-06-18 02:08:19 +0200 |
| commit | b8767a634966b2c4ea9b2c8a71174ca49e3c2f2f (patch) | |
| tree | ab55c0fc3f44342e7161245c015061ca306b593c /src | |
| parent | aa407033bdb43cf09b1eeff2aa06a80a78ee00d7 (diff) | |
| download | mailman-pgp-b8767a634966b2c4ea9b2c8a71174ca49e3c2f2f.tar.gz mailman-pgp-b8767a634966b2c4ea9b2c8a71174ca49e3c2f2f.tar.zst mailman-pgp-b8767a634966b2c4ea9b2c8a71174ca49e3c2f2f.zip | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman_pgp/config/mailman_pgp.cfg | 17 | ||||
| -rw-r--r-- | src/mailman_pgp/model/list.py | 33 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/__init__.py | 22 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/keygen.py | 29 | ||||
| -rw-r--r-- | src/mailman_pgp/plugin.py | 2 |
5 files changed, 89 insertions, 14 deletions
diff --git a/src/mailman_pgp/config/mailman_pgp.cfg b/src/mailman_pgp/config/mailman_pgp.cfg index 0abb026..de87ca1 100644 --- a/src/mailman_pgp/config/mailman_pgp.cfg +++ b/src/mailman_pgp/config/mailman_pgp.cfg @@ -6,7 +6,7 @@ url = sqlite:////$DATA_DIR/pgp.db [gpg] -# GPG homedir +# GPG homedir. homedir = $DATA_DIR/gpg/ # Keyring used to store user keys. (GPG pubring) @@ -15,11 +15,22 @@ keyring = $DATA_DIR/gpg/pubring.gpg # Keyring used to store list keypairs. (GPG secring) secring = $DATA_DIR/gpg/secring.gpg +# The GPG binary to use. +binary = gpg + [keypairs] -size = 4096 +# +key_length = 4096 + +# +key_type = RSA + +# +subkey_length = 4096 -type = RSA +# +subkey_type = RSA [queues] diff --git a/src/mailman_pgp/model/list.py b/src/mailman_pgp/model/list.py index d6384af..4699599 100644 --- a/src/mailman_pgp/model/list.py +++ b/src/mailman_pgp/model/list.py @@ -1,11 +1,14 @@ """""" +from mailman.config import config as mailman_config from mailman.database.types import Enum, SAUnicode from mailman.interfaces.action import Action +from mailman.model.mailinglist import MailingList from public import public from sqlalchemy import Boolean, Column, Integer from mailman_pgp.model.base import Base +from mailman_pgp.pgp.keygen import KeyGenerator @public @@ -14,7 +17,7 @@ class EncryptedMailingList(Base): id = Column(Integer, primary_key=True) list_id = Column(SAUnicode, index=True) - key_fingerprint = Column(SAUnicode) + _key_fingerprint = Column('key_fingerprint', SAUnicode) unsigned_msg_action = Column(Enum(Action)) nonencrypted_msg_action = Column(Enum(Action)) strip_original_signature = Column(Boolean) @@ -23,10 +26,28 @@ class EncryptedMailingList(Base): def __init__(self, mlist): super().__init__() self.list_id = mlist.list_id - self._list_key = None + + self._key_generator = self._create_generator(mlist) + self._key_generator.start() + + def _create_generator(self, mlist): + return KeyGenerator(mlist.list_id, mlist.fqdn_listname) + + @property + def key_fingerprint(self): + if self._key_fingerprint is None: + if self._key_generator.has_key: + self._key_fingerprint = self._key_generator.key_fingerprint + else: + if not self._key_generator.is_alive(): + # TODO this is not the best solution, we should lookup the + # key by mlist.fqdn_listname, if it actually got created + # and key generator didn't receive it. + self._key_generator = self._create_generator(self.mlist) + self._key_generator.start() + return self._key_fingerprint @property - def list_key(self): - if self._list_key is not None: - return self._list_key - pass + def mlist(self): + return mailman_config.db.query(MailingList).filter_by( + _list_id=self.list_id).first() diff --git a/src/mailman_pgp/pgp/__init__.py b/src/mailman_pgp/pgp/__init__.py index c96d1b0..ec31b2d 100644 --- a/src/mailman_pgp/pgp/__init__.py +++ b/src/mailman_pgp/pgp/__init__.py @@ -1,5 +1,7 @@ """""" +from pathlib import Path + import gpgmime from mailman.config import config as mailman_config from mailman.utilities.string import expand @@ -8,15 +10,27 @@ from public import public from mailman_pgp.config import config GPG_CONFIG_PATHS = ['homedir', 'keyring', 'secring', 'binary'] +KEYPAIR_CONFIG_VARIABLES = ['key_type', 'key_length', + 'subkey_type', 'subkey_length'] @public class GPG(gpgmime.GPG): def __init__(self): - self.list_key_size = config.getint('keypairs', 'size') - self.list_key_type = config.get('keypairs', 'type') + # Get all the [keypairs] config variables. + self.keypair_config = dict( + (k, config.get('keypairs', k)) for k in KEYPAIR_CONFIG_VARIABLES) + self.keypair_config['key_usage'] = 'auth,sign,cert' + self.keypair_config['subkey_usage'] = 'enc' - gpg_config = dict( + # Get and expand all [gpg] config paths against Mailman's directories. + self.gpg_config = dict( (k, expand(config.get('gpg', k), None, mailman_config.paths)) for k in GPG_CONFIG_PATHS) - super().__init__(**gpg_config) + + # Ensure that the homedir path is a directory before passing it to GPG. + # If it's actually a file this raises FileExistsError. + homedir_path = Path(self.gpg_config['homedir']) + homedir_path.mkdir(parents=True, exist_ok=True) + + super().__init__(**self.gpg_config) diff --git a/src/mailman_pgp/pgp/keygen.py b/src/mailman_pgp/pgp/keygen.py new file mode 100644 index 0000000..b15dbf6 --- /dev/null +++ b/src/mailman_pgp/pgp/keygen.py @@ -0,0 +1,29 @@ +"""""" + +import threading + +from mailman_pgp.config import config + + +class KeyGenerator(threading.Thread): + def __init__(self, name, email, comment=None): + super().__init__(daemon=True) + self._name = name + self._comment = comment + self._email = email + self.key_fingerprint = None + + def run(self): + default_config = config.gpg.keypair_config + key_config = dict(default_config) + key_config.update(dict(name_real=self._name, + name_email=self._email)) + if self._comment is not None: + key_config['name_comment'] = self._comment + key_input = config.gpg.gen_key_input(**key_config) + key = config.gpg.gen_key(key_input) + self.key_fingerprint = key.fingerprint + + @property + def has_key(self): + return self.key_fingerprint is not None diff --git a/src/mailman_pgp/plugin.py b/src/mailman_pgp/plugin.py index 6921095..5245a95 100644 --- a/src/mailman_pgp/plugin.py +++ b/src/mailman_pgp/plugin.py @@ -37,4 +37,4 @@ def on_delete(mlist): if encrypted_list: with transaction(): config.db.session.delete(encrypted_list) - # delete the keypairs here + # TODO delete the keypairs here |
