piknik

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit 29744928bd6d61d85e39629bf51d8603d7693c65
parent 198ece70a0b1fa06a78fd6c968852d1ce91aade7
Author: lash <dev@holbrook.no>
Date:   Thu, 17 Nov 2022 07:32:58 +0000

Include signature status in show cmd

Diffstat:
Mpiknik/crypto.py | 18++++++++++++++----
Mpiknik/msg.py | 18++++++++++++++++--
Mpiknik/runnable/show.py | 40+++++++++++++++++++++++++++++++++-------
3 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/piknik/crypto.py b/piknik/crypto.py @@ -9,6 +9,7 @@ import gnupg # local imports from piknik.error import VerifyError +from piknik.msg import MessageEnvelope logg = logging.getLogger() logging.getLogger('gnupg').setLevel(logging.ERROR) @@ -52,16 +53,17 @@ class PGPSigner: raise VerifyError('new envelope before previous was verified ({})'.format(self.__envelope_state)) self.__envelope = msg self.__envelope_state = 0 + return MessageEnvelope(msg) def message_callback(self, envelope, msg, message_id): if self.__envelope_state == 0: self.__envelope_state = 1 self.__envelope = msg - return + return (envelope, msg,) if msg.get('Content-Type') != 'application/pgp-signature': - return + return (envelope, msg,) v = self.__envelope.as_string() sig = msg.get_payload() @@ -71,9 +73,17 @@ class PGPSigner: f.close() r = self.gpg.verify_data(fp, v.encode('utf-8')) os.unlink(fp) + if r.key_status != None: raise VerifyError('unexpeced key status {}'.format(r.key_status)) - if r.status != 'signature valid': + if r.status == 'no public key': + logg.warning('public key flr {} not found, cannot verify'.format(r.fingerprint)) + elif r.status != 'signature valid': raise VerifyError('invalid signature') - logg.debug('signature ok') + else: + logg.debug('signature ok from {}'.format(r.fingerprint)) + envelope.valid = True + envelope.sender = r.fingerprint self.__envelope_state = 2 + + return (envelope, msg,) diff --git a/piknik/msg.py b/piknik/msg.py @@ -15,6 +15,20 @@ from email.utils import formatdate logg = logging.getLogger(__name__) +class MessageEnvelope: + + def __init__(self, msg): + self.msg = msg + self.sender = None + self.valid = False + self.resolved = False + + +def rubber_stamp_envelope(envelope, envelope_type): + envelope.valid = True + return + + class IssueMessage: def __init__(self, issue): @@ -28,7 +42,7 @@ class IssueMessage: self.__m.set_boundary(str(uuid.uuid4())) - def __unwrap(self, msg, envelope_callback=None, message_callback=None): + def __unwrap(self, msg, envelope_callback=rubber_stamp_envelope, message_callback=None): message_ids = [] message_id = None envelope = None @@ -36,7 +50,7 @@ class IssueMessage: env_header = m.get('X-Piknik-Envelope') if env_header != None: if envelope_callback != None: - envelope_callback(m, env_header) + m = envelope_callback(m, env_header) envelope = m continue diff --git a/piknik/runnable/show.py b/piknik/runnable/show.py @@ -1,4 +1,5 @@ # standard imports +import os import sys import argparse import logging @@ -14,6 +15,8 @@ from piknik import Issue from piknik.store import FileStoreFactory from piknik.crypto import PGPSigner +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger() argp = argparse.ArgumentParser() argp.add_argument('-d', type=str, help='Data directory') @@ -31,12 +34,15 @@ class PGPWrapper(PGPSigner): def __init__(self, home_dir=None): super(PGPWrapper, self).__init__(home_dir=home_dir) self.message_date = None + self.message = None + self.message_id = None + self.sender = None + self.valid = False - def render_message(self, message, message_id): + def render_message(self, envelope, message, message_id): r = None m = parse_mime_type(message.get_content_type()) - print('content {}'.format(m)) if m[0] == 'text': if m[1] == 'plain': @@ -51,24 +57,44 @@ class PGPWrapper(PGPSigner): sz = 'unknown' r = '[file: ' + message.get_filename() + ', size: ' + sz + ']' - print("message {} - {}\n\t{}\n".format(self.message_date, message_id, r)) + valid = '[++]' + if not self.valid: + valid = '[!!]' + print('message {} from {} {} - {}\n\t{}\n'.format(self.sender, self.message_date, valid, message_id, r)) + + + def envelope_callback(self, envelope, envelope_type): + envelope = super(PGPWrapper, self).envelope_callback(envelope, envelope_type) + envelope.valid = False + return envelope def message_callback(self, envelope, message, message_id): - super(PGPWrapper, self).message_callback(envelope, message, message_id) + (envelope, message) = super(PGPWrapper, self).message_callback(envelope, message, message_id) + + if envelope != None and not envelope.resolved: + self.sender = envelope.sender + self.valid = envelope.valid + self.resolved = True if message_id == None: return if message.get('X-Piknik-Msg-Id') == None: if message.get('Content-Type') == 'application/pgp-signature': - return - self.render_message(message, message_id) + #return + self.render_message(envelope, self.message, self.message_id) + self.message = None + self.message_id = None + else: + self.message = message + self.message_id = message_id else: d = message.get('Date') self.message_date = parsedate_to_datetime(d) -verifier = PGPWrapper() +gpg_home = os.environ.get('GPGHOME') +verifier = PGPWrapper(home_dir=gpg_home) def render_default(b, o, t):