summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2017-08-21 18:18:07 +0200
committerJ08nY2017-08-21 18:18:07 +0200
commit8f105928b6d79a5bd56ae20bec0dd288136ddf9f (patch)
tree43eac4fe1f8015f55898e54f1ec76c63f9677891 /src
parentc74e96f813542d94592bf80c24afdec5d6988b2a (diff)
downloadmailman-pgp-8f105928b6d79a5bd56ae20bec0dd288136ddf9f.tar.gz
mailman-pgp-8f105928b6d79a5bd56ae20bec0dd288136ddf9f.tar.zst
mailman-pgp-8f105928b6d79a5bd56ae20bec0dd288136ddf9f.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman_pgp/rules/signature.py9
-rw-r--r--src/mailman_pgp/rules/tests/test_signature.py31
-rw-r--r--src/mailman_pgp/utils/pgp.py72
3 files changed, 87 insertions, 25 deletions
diff --git a/src/mailman_pgp/rules/signature.py b/src/mailman_pgp/rules/signature.py
index b7d4b5c..ae27bb5 100644
--- a/src/mailman_pgp/rules/signature.py
+++ b/src/mailman_pgp/rules/signature.py
@@ -35,7 +35,7 @@ from mailman_pgp.model.sighash import PGPSigHash
from mailman_pgp.pgp.wrapper import PGPWrapper
from mailman_pgp.utils.email import get_email
from mailman_pgp.utils.moderation import record_action
-from mailman_pgp.utils.pgp import hashes, verifies, expired
+from mailman_pgp.utils.pgp import hashes, verifies, expired, revoked
@public
@@ -106,6 +106,13 @@ class Signature:
'Signature is expired.')
return True
+ if revoked(verifications):
+ action = pgp_list.revoked_sig_action
+ if action != Action.defer:
+ record_action(msg, msgdata, action, email,
+ 'Signature is made by a revoked key.')
+ return True
+
# Take the `invalid_sig_action` if the verification failed.
if not verifies(verifications):
action = pgp_list.invalid_sig_action
diff --git a/src/mailman_pgp/rules/tests/test_signature.py b/src/mailman_pgp/rules/tests/test_signature.py
index 72f2c70..ec49a18 100644
--- a/src/mailman_pgp/rules/tests/test_signature.py
+++ b/src/mailman_pgp/rules/tests/test_signature.py
@@ -37,6 +37,7 @@ from mailman_pgp.database import mm_transaction, transaction
from mailman_pgp.model.address import PGPAddress
from mailman_pgp.model.list import PGPMailingList
from mailman_pgp.model.sighash import PGPSigHash
+from mailman_pgp.pgp.inline import InlineWrapper
from mailman_pgp.pgp.mime import MIMEWrapper
from mailman_pgp.pgp.wrapper import PGPWrapper
from mailman_pgp.rules.signature import Signature
@@ -181,6 +182,36 @@ To: test@example.com
self.assertTrue(matches)
self.assertAction(msgdata, Action.hold, ['Signature is expired.'])
+ msgdata = {}
+ wrapped = InlineWrapper(self.msg_clear)
+ msg = wrapped.sign(self.sender_key, expires=timedelta(seconds=1))
+ time.sleep(2)
+ matches = self.rule.check(self.mlist, msg, msgdata)
+
+ self.assertTrue(matches)
+ self.assertAction(msgdata, Action.hold, ['Signature is expired.'])
+
+ def test_revoked_sig_action(self):
+ with transaction():
+ self.pgp_list.unsigned_msg_action = Action.defer
+ self.pgp_list.inline_pgp_action = Action.defer
+ self.pgp_list.expired_sig_action = Action.defer
+ self.pgp_list.revoked_sig_action = Action.hold
+ self.pgp_list.invalid_sig_action = Action.defer
+ self.pgp_list.duplicate_sig_action = Action.defer
+
+ rsig = self.sender_key.revoke(self.pgp_sender.key)
+ self.pgp_sender.key |= rsig
+
+ msgdata = {}
+ wrapped = MIMEWrapper(self.msg_clear)
+ msg = wrapped.sign(self.sender_key)
+ matches = self.rule.check(self.mlist, msg, msgdata)
+
+ self.assertTrue(matches)
+ self.assertAction(msgdata, Action.hold,
+ ['Signature is made by a revoked key.'])
+
def test_invalid_sig_action(self):
with transaction():
self.pgp_list.unsigned_msg_action = Action.defer
diff --git a/src/mailman_pgp/utils/pgp.py b/src/mailman_pgp/utils/pgp.py
index c44a27e..46fc797 100644
--- a/src/mailman_pgp/utils/pgp.py
+++ b/src/mailman_pgp/utils/pgp.py
@@ -31,7 +31,19 @@ def expired(verifications):
:param verifications:
:return:
"""
- return any(any(sigsubj.signature.is_expired
+ return any(any(sigsubj.signature.is_expired or sigsubj.by.is_expired
+ for sigsubj in verification.good_signatures)
+ for verification in verifications)
+
+
+@public
+def revoked(verifications):
+ """
+
+ :param verifications:
+ :return:
+ """
+ return any(any(key_revoked(sigsubj.by)
for sigsubj in verification.good_signatures)
for verification in verifications)
@@ -114,16 +126,43 @@ def revoc_from_blob(blob):
@public
-def key_flags(key):
- if key.is_expired:
- return set()
+def key_revoked(key):
+ """
+
+ :param key:
+ :type key: pgpy.PGPKey
+ :return:
+ :rtype: bool
+ """
+ if key.is_primary:
+ verifier = key
+ else:
+ verifier = key.parent
+
for revoc in key.revocation_signatures:
try:
- verified = key.verify(key, revoc)
+ verified = verifier.verify(key, revoc)
except PGPError:
continue
if bool(verified):
- return set()
+ return True
+
+ return False
+
+
+@public
+def key_flags(key):
+ """
+
+ :param key:
+ :type key: pgpy.PGPKey
+ :return:
+ :rtype: Set[pgpy.constants.KeyFlags]
+ """
+ if key.is_expired:
+ return set()
+ if key_revoked(key):
+ return set()
usage_flags = set()
uids = (uid for uid in key.userids if uid.is_primary)
@@ -151,17 +190,7 @@ def key_flags(key):
if subkey.is_expired:
continue
- valid = True
- for revoc in subkey.revocation_signatures:
- try:
- verified = key.verify(subkey, revoc)
- except PGPError:
- continue
- if bool(verified):
- valid = False
- break
-
- if valid:
+ if not key_revoked(subkey):
usage_flags |= subkey.usage_flags()
return usage_flags
@@ -183,13 +212,8 @@ def key_usable(key, flags_required):
"""
if key.is_expired:
return False
- for revoc in key.revocation_signatures:
- try:
- verified = key.verify(key, revoc)
- except PGPError:
- continue
- if bool(verified):
- return False
+ if key_revoked(key):
+ return False
return flags_required.issubset(key_flags(key))