From 34706cad6476aadad3dcb59cf33e03572739a1b3 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 20 Sep 2012 12:35:00 -0400 Subject: [PATCH] mailpipe: don't bail if a message is signed by a subkey. Also strips off a leading '0x' before matching fingerprint tails. You should normally be using primary keys in the `pgp_key` field of the course configuration file. Before this commit, messages signed by a subkey would raise WrongSignatureMessage (i.e. we were looking for a signature by your primary key, but we only got a signature from your subkey). Now we look for the listed signature not only in the signing keys but also in their primaries. This requires pgp-mime commit: commit eab8b88fe3f4940a9f8285cfb8b88070cd5c0050 Author: W. Trevor King Date: Thu Sep 20 12:24:27 2012 -0400 key: add pgp_mime.key wrapping gpgme-tool's KEYLIST command. --- pygrader/mailpipe.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pygrader/mailpipe.py b/pygrader/mailpipe.py index 1a0bd6e..281839b 100644 --- a/pygrader/mailpipe.py +++ b/pygrader/mailpipe.py @@ -26,6 +26,7 @@ import re as _re import sys as _sys import pgp_mime as _pgp_mime +import pgp_mime.key as _pgp_mime_key from . import LOG as _LOG from .email import construct_email as _construct_email @@ -76,13 +77,14 @@ class AmbiguousAddress (_InvalidMessage): class WrongSignatureMessage (_InsecureMessage): - def __init__(self, pgp_key=None, signatures=None, decrypted=None, - **kwargs): + def __init__(self, pgp_key=None, signatures=None, fingerprints=None, + decrypted=None, **kwargs): if 'error' not in kwargs: kwargs['error'] = 'not signed by the expected key' super(WrongSignatureMessage, self).__init__(**kwargs) self.pgp_key = pgp_key self.signatures = signatures + self.fingerprints = fingerprints self.decrypted = decrypted @@ -939,11 +941,22 @@ def _get_verified_message(message, pgp_key): for signature in signatures: _LOG.debug(signature.dumps()) match = None - matches = [s for s in signatures if s.fingerprint.endswith(pgp_key)] + fingerprints = dict((s.fingerprint, s) for s in signatures) + for s in signatures: + for key in _pgp_mime_key.lookup_keys([s.fingerprint]): + if key.fingerprint != s.fingerprint: + # the signature was made with a subkey. Add the primary. + fingerprints[key.fingerprint] = s + if pgp_key.startswith('0x'): + key_tail = pgp_key[len('0x'):] + else: + key_tail = pgp_key + matches = [fingerprints[f] for f in fingerprints.keys() + if f.endswith(key_tail)] if len(matches) == 0: raise WrongSignatureMessage( message=message, pgp_key=pgp_key, signatures=signatures, - decrypted=decrypted) + fingerprints=fingerprints, decrypted=decrypted) signature = matches[0] if not verified: if signature.get_summary() != 0: -- 2.26.2