diff options
Diffstat (limited to 'src/mailman_pgp/rules/signature.py')
| -rw-r--r-- | src/mailman_pgp/rules/signature.py | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/mailman_pgp/rules/signature.py b/src/mailman_pgp/rules/signature.py index 5a89ab1..0ffd76b 100644 --- a/src/mailman_pgp/rules/signature.py +++ b/src/mailman_pgp/rules/signature.py @@ -30,45 +30,90 @@ from mailman_pgp.model.list import PGPMailingList from mailman_pgp.pgp.wrapper import PGPWrapper +def _record_action(msgdata, action, sender, reason): + msgdata['moderation_action'] = action + msgdata['moderation_sender'] = sender + msgdata.setdefault('moderation_reasons', []).append(reason) + + @public @implementer(IRule) class Signature: - """""" + """The signature checking rule.""" name = 'signature' - description = _( - """ - """) - + """A rule which enforces PGP enabled list signature configuration.""") record = True - def _record_action(self, msgdata, action, sender, reason): - msgdata['moderation_action'] = action - msgdata['moderation_sender'] = sender - msgdata.setdefault('moderation_reasons', []).append(reason) - def check(self, mlist, msg, msgdata): """See `IRule`.""" + # Find the `PGPMailingList` this is for. enc_list = query(PGPMailingList).filter_by( list_id=mlist.list_id).first() if enc_list is None: raise ValueError('PGP enabled mailing list not found.') + # Wrap the message to work with it. wrapped = PGPWrapper(msg) + # Take unsigned_msg_action if unsigned. if not wrapped.is_signed(): action = enc_list.unsigned_msg_action if action is not None: - self._record_action(msgdata, action, msg.sender, - 'The message is unsigned.') + _record_action(msgdata, action, msg.sender, + 'The message is unsigned.') return True + # Take `inline_pgp_action` if inline signed. if wrapped.is_inline_signed(): action = enc_list.inline_pgp_action if action is not None: - self._record_action(msgdata, action, msg.sender, - 'Inline PGP is not allowed.') + _record_action(msgdata, action, msg.sender, + 'Inline PGP is not allowed.') + return True + + # Lookup the address by sender, and its corresponding `PGPAddress`. + user_manager = getUtility(IUserManager) + sender = msg.sender + address = user_manager.get_address(sender) + enc_address = PGPAddress.query().filter_by( + email=address.email).first() + if enc_address is None: + raise ValueError('PGP enabled address not found.') + + # See if we have a key. + key = enc_address.key + if key is None: + # TODO: how to handle this? + raise ValueError('No key?') + + # Verify, this gives us stuff we need to check. + verification = wrapped.verify(key) + + # Take the `invalid_sig_action` if the verification failed. + if not verification: + action = enc_list.invalid_sig_action + if action is not None: + _record_action(msgdata, action, msg.sender, + 'Signature did not verify.') + return True + + # TODO: handle more signatures here? + sig_obj = next(verification.good_signatures) + sig_key = sig_obj.by + sig_sig = sig_obj.signature + + # Take the `expired_sig_action` if either he signature or the key + # is expired. + if sig_sig.is_expired or sig_key.is_expired: + action = enc_list.expired_sig_action + if action is not None: + _record_action(msgdata, action, msg.sender, + 'Signature or key expired.') return True - # TODO finish this
\ No newline at end of file + # XXX: we need to track key revocation separately to use it here + # TODO: check key revocation here + + return False |
