From f23c1474ffc7ae9d71d1f43e19d0cf902eeaa2b5 Mon Sep 17 00:00:00 2001 From: Konstantin Ryabitsev Date: Tue, 11 May 2021 17:46:02 -0400 Subject: Rudimentary support for showing patatt key info I expect that we'll have better keyring management tooling in the future, but for now show some rudimentary information about patatt keys used in a thread via --show-keys, e.g.: b4 mbox --show-keys 20210511143536.743919-1-konstantin@linuxfoundation.org b4 mbox --show-keys 20210507181322.172569-1-konstantin@linuxfoundation.org Signed-off-by: Konstantin Ryabitsev --- b4/__init__.py | 3 ++- b4/command.py | 2 ++ b4/mbox.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/b4/__init__.py b/b4/__init__.py index 59dfccf..12afe94 100644 --- a/b4/__init__.py +++ b/b4/__init__.py @@ -1027,7 +1027,8 @@ class LoreMessage: attestations = patatt.validate_message(self.msg.as_bytes(), sources) for passing, identity, signtime, keysrc, keyalgo, errors in attestations: - attestor = LoreAttestorPatatt(passing, identity, signtime, keysrc, keyalgo, errors) + signdt = LoreAttestor.parse_ts(signtime) + attestor = LoreAttestorPatatt(passing, identity, signdt, keysrc, keyalgo, errors) self._attestors.append(attestor) def get_attestation_trailers(self, attpolicy: str, maxdays: int = 0) -> Tuple[str, list, bool]: diff --git a/b4/command.py b/b4/command.py index ff457dd..12c7354 100644 --- a/b4/command.py +++ b/b4/command.py @@ -84,6 +84,8 @@ def cmd(): cmd_mbox_common_opts(sp_mbox) sp_mbox.add_argument('-f', '--filter-dupes', dest='filterdupes', action='store_true', default=False, help='When adding messages to existing maildir, filter out duplicates') + sp_mbox.add_argument('--show-keys', dest='showkeys', action='store_true', default=False, + help='Show all developer keys from the thread') sp_mbox.set_defaults(func=cmd_mbox) # b4 am diff --git a/b4/mbox.py b/b4/mbox.py index 275a42a..7804535 100644 --- a/b4/mbox.py +++ b/b4/mbox.py @@ -16,6 +16,7 @@ import time import json import fnmatch import shutil +import pathlib import urllib.parse import xml.etree.ElementTree @@ -534,6 +535,78 @@ def main(cmdargs): return mbx = mailbox.mbox(threadfile) + + if cmdargs.showkeys: + logger.info('---') + try: + import patatt + except ModuleNotFoundError: + logger.info('--show-keys requires patatt library') + sys.exit(1) + + keydata = set() + for msg in mbx: + xdk = msg.get('x-developer-key') + xds = msg.get('x-developer-signature') + if not xdk or not xds: + continue + # grab the selector they used + kdata = b4.LoreMessage.get_parts_from_header(xdk) + sdata = b4.LoreMessage.get_parts_from_header(xds) + algo = kdata.get('a') + identity = kdata.get('i') + selector = sdata.get('s', 'default') + if algo == 'openpgp': + keyinfo = kdata.get('fpr') + elif algo == 'ed25519': + keyinfo = kdata.get('pk') + else: + logger.debug('Unknown key type: %s', algo) + continue + keydata.add((identity, algo, selector, keyinfo)) + if not keydata: + logger.info('No keys found in the thread.') + sys.exit(0) + krpath = os.path.join(b4.get_data_dir(), 'keyring') + pgp = False + ecc = False + for identity, algo, selector, keyinfo in keydata: + keypath = patatt.make_pkey_path(algo, identity, selector) + fullpath = os.path.join(krpath, keypath) + if os.path.exists(fullpath): + status = 'known' + else: + if algo == 'openpgp': + uids = b4.get_gpg_uids(keyinfo) + if len(uids): + status = 'in default keyring' + else: + status = 'unknown' + else: + status = 'unknown' + pathlib.Path(os.path.dirname(fullpath)).mkdir(parents=True, exist_ok=True) + + logger.info('%s: (%s)', identity, status) + logger.info(' keytype: %s', algo) + if algo == 'openpgp': + pgp = True + logger.info(' keyid: %s', keyinfo[-16:]) + logger.info(' fpr: %s', ':'.join(re.findall(r'.{4}', keyinfo))) + else: + ecc = True + logger.info(' pubkey: %s', keyinfo) + logger.info(' krpath: %s', keypath) + logger.info(' fullpath: %s', fullpath) + logger.info('---') + if pgp: + logger.info('For openpgp keys:') + logger.info(' gpg --recv-key [keyid]') + logger.info(' gpg -a --export [keyid] > [fullpath]') + if ecc: + logger.info('For ed25519 keys:') + logger.info(' echo [pubkey] > [fullpath]') + sys.exit(0) + logger.info('%s messages in the thread', len(mbx)) if cmdargs.outdir == '-': mbx.close() -- cgit v1.2.3