diff options
Diffstat (limited to 'src/mailman_pgp/commands/eml_key.py')
| -rw-r--r-- | src/mailman_pgp/commands/eml_key.py | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/src/mailman_pgp/commands/eml_key.py b/src/mailman_pgp/commands/eml_key.py index 9514f48..b280603 100644 --- a/src/mailman_pgp/commands/eml_key.py +++ b/src/mailman_pgp/commands/eml_key.py @@ -16,11 +16,21 @@ # this program. If not, see <http://www.gnu.org/licenses/>. """The key email command.""" +from email.utils import parseaddr from mailman.interfaces.command import ContinueProcessing, IEmailCommand +from mailman.interfaces.subscriptions import ISubscriptionManager +from mailman.interfaces.usermanager import IUserManager from public import public +from zope.component import getUtility from zope.interface import implementer +from mailman_pgp.database import transaction +from mailman_pgp.model.address import PGPAddress +from mailman_pgp.model.list import PGPMailingList +from mailman_pgp.pgp.wrapper import PGPWrapper +from mailman_pgp.workflows.base import CONFIRM_REQUEST + @public @implementer(IEmailCommand) @@ -28,7 +38,7 @@ class KeyCommand: """The `key` command.""" name = 'key' - argument_description = '<change|revoke|sign>' + argument_description = '<set|confirm|change|revoke|sign>' short_description = '' description = '' @@ -38,7 +48,78 @@ class KeyCommand: print('No sub-command specified,' ' must be one of <change|revoke|sign>.', file=results) return ContinueProcessing.no - if arguments[0] == 'change': + + pgp_list = PGPMailingList.for_list(mlist) + if pgp_list is None: + print('This mailing list doesnt have pgp enabled.', file=results) + return ContinueProcessing.yes # XXX: What does this even mean? + + if arguments[0] == 'set': + if len(arguments) != 2: + print('Missing token', file=results) + return ContinueProcessing.no + + wrapped = PGPWrapper(msg) + if not wrapped.has_keys(): + print('No keys here?') + return ContinueProcessing.no + + keys = list(wrapped.keys()) + if len(keys) != 1: + print('More than one key! Which one is yours?') + return ContinueProcessing.no + + with transaction() as t: + pgp_address = PGPAddress(self.address) + pgp_address.key = keys.pop() + t.add(pgp_address) + + token = arguments[1] + ISubscriptionManager(mlist).confirm(token) + # XXX finish this + elif arguments[0] == 'confirm': + if len(arguments) != 2: + print('Missing token', file=results) + return ContinueProcessing.no + + display_name, email = parseaddr(msg['from']) + # Address could be None or the empty string. + if not email: + email = msg.sender + if not email: + print('No email to subscribe with.', file=results) + return ContinueProcessing.no + um = getUtility(IUserManager) + + pgp_address = PGPAddress.for_address(um.get_address(email)) + if pgp_address is None: + # TODO + pass + + wrapped = PGPWrapper(msg) + if wrapped.is_encrypted(): + decrypted = wrapped.decrypt(pgp_list.key) + wrapped = PGPWrapper(decrypted) + + if not wrapped.is_signed(): + print('Message not signed, ignoring.', file=results) + return ContinueProcessing.no + + if not wrapped.verifies(pgp_address.key): + print('Message failed to verify.', file=results) + return ContinueProcessing.no + + token = arguments[1] + + expecting = CONFIRM_REQUEST.format(pgp_address.key.pubkey, + token) + if wrapped.get_signed() == expecting: + ISubscriptionManager(mlist).confirm(token) + else: + # TODO + pass + + elif arguments[0] == 'change': # New public key in attachment, requires to be signed with current # key pass @@ -52,4 +133,5 @@ class KeyCommand: else: print('Wrong sub-command specified,' ' must be one of <change|revoke|sign>.', file=results) - return ContinueProcessing.no + + return ContinueProcessing.no |
