aboutsummaryrefslogtreecommitdiff
path: root/src/mailman_pgp/commands/eml_key.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman_pgp/commands/eml_key.py')
-rw-r--r--src/mailman_pgp/commands/eml_key.py97
1 files changed, 96 insertions, 1 deletions
diff --git a/src/mailman_pgp/commands/eml_key.py b/src/mailman_pgp/commands/eml_key.py
index 46303c3..a298ea7 100644
--- a/src/mailman_pgp/commands/eml_key.py
+++ b/src/mailman_pgp/commands/eml_key.py
@@ -22,6 +22,7 @@ from email.mime.text import MIMEText
from mailman.email.message import UserNotification
from mailman.interfaces.command import ContinueProcessing, IEmailCommand
+from mailman.interfaces.member import MemberRole
from mailman.interfaces.pending import IPendings
from mailman.interfaces.subscriptions import ISubscriptionManager
from mailman.interfaces.usermanager import IUserManager
@@ -351,7 +352,101 @@ def _cmd_revoke(pgp_list, mlist, msg, msgdata, arguments, results):
def _cmd_sign(pgp_list, mlist, msg, msgdata, arguments, results):
# List public key attached, signed by the users current key.
- pass
+ if len(arguments) != 1:
+ print('Extraneous argument/s: ' + ','.join(arguments[1:]),
+ file=results)
+ return ContinueProcessing.no
+
+ email = get_email(msg)
+ if not email:
+ print('No email.', file=results)
+ return ContinueProcessing.no
+
+ pgp_address = PGPAddress.for_email(email)
+ if pgp_address is None:
+ print('A pgp enabled address not found.', file=results)
+ return ContinueProcessing.no
+
+ key = pgp_address.key
+ if key is None:
+ print("You currently don't have a key set.", file=results)
+ return ContinueProcessing.no
+
+ if not pgp_address.key_confirmed:
+ print('Your key is currently not confirmed.', file=results)
+ return ContinueProcessing.no
+
+ wrapped = PGPWrapper(msg)
+ if wrapped.is_encrypted():
+ decrypted = wrapped.try_decrypt(pgp_list.key)
+ wrapped = PGPWrapper(decrypted)
+
+ if not wrapped.has_keys():
+ print('No keys attached? Send a key.', file=results)
+ return ContinueProcessing.no
+
+ keys = list(wrapped.keys())
+ if len(keys) != 1:
+ print('More than one key! Send only one key.', file=results)
+ return ContinueProcessing.no
+ key = keys.pop()
+
+ allowed_signers = pgp_list.key_signing_allowed
+ roster_map = {
+ MemberRole.member: mlist.members,
+ MemberRole.owner: mlist.owners,
+ MemberRole.moderator: mlist.moderators,
+ MemberRole.nonmember: mlist.nonmembers
+ }
+ allowed = False
+ for allowed_role in allowed_signers:
+ allowed_roster = roster_map[allowed_role]
+ if allowed_roster.get_member(email) is not None:
+ allowed = True
+ break
+
+ if not allowed:
+ print('You are not allowed to sign the list key.', file=results)
+ return ContinueProcessing.no
+
+ if pgp_list.pubkey.key_material != key.key_material:
+ print('You sent a wrong key.', file=results)
+ return ContinueProcessing.no
+
+ uid_map = {}
+ for uid in pgp_list.key.userids:
+ for uid_other in key.userids:
+ if uid == uid_other:
+ uid_map[uid] = uid_other
+
+ if len(uid_map) == 0:
+ print('No signed UIDs found.', file=results)
+ return ContinueProcessing.no
+
+ uid_sigs = {}
+ for uid, uid_other in uid_map.items():
+ for sig in uid_other.signatures:
+ if sig in uid.signatures:
+ continue
+ if sig.signer != pgp_address.key.fingerprint.keyid:
+ continue
+ # sig is a new signature, not currenctly on uid, ans seems to
+ # be made by the pgp_address.key
+ verification = pgp_address.key.verify(uid, sig)
+ if bool(verification):
+ uid_sigs.setdefault(uid, []).append(sig)
+
+ if len(uid_sigs) == 0:
+ print('No new certifications found.', file=results)
+ return ContinueProcessing.no
+
+ for uid, sigs in uid_sigs.items():
+ for sig in sigs:
+ uid |= sig
+ pgp_list.fs_key.save()
+
+ print('List key updated with new signatures.', file=results)
+ return ContinueProcessing.yes
def _cmd_receive(pgp_list, mlist, msg, msgdata, arguments, results):