diff options
author | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2020-02-28 16:41:41 -0500 |
---|---|---|
committer | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2020-02-28 16:41:41 -0500 |
commit | 6eb2ee3aa89f80b41766753030426c7c0b1471db (patch) | |
tree | 1f52198c9815d0d716a8e45181d6d019cd93772e | |
parent | b234a9ecd7b3ce8c75d2bdfabc1e3fd176a0b74e (diff) | |
download | korg-helpers-6eb2ee3aa89f80b41766753030426c7c0b1471db.tar.gz |
A few updates to attest-patches.py
- Attempt to deliver via mail.kernel.org:587
- Accept patch from Kees Cook to set custom From: header
- If we find a cover letter, set attestation subject to match
Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
-rwxr-xr-x | attest-patches.py | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/attest-patches.py b/attest-patches.py index dfe05b6..f9b6325 100755 --- a/attest-patches.py +++ b/attest-patches.py @@ -21,6 +21,7 @@ import email.utils import mailbox import urllib import requests +import smtplib from tempfile import mkstemp @@ -190,11 +191,21 @@ def get_patch_hash(diff): def create_attestation(cmdargs): attlines = list() + subject = 'Patch attestation' for patchfile in cmdargs.attest: with open(patchfile, 'rb') as fh: - ihash, mhash, phash = get_mailinfo_hashes(fh.read()) + content = fh.read() + ihash, mhash, phash = get_mailinfo_hashes(content) if not phash: logger.info('SKP | %s', os.path.basename(patchfile)) + # See if it's a cover letter + matches = re.search(r'^Subject:\s*\[([^\]]*)\s+0{1,3}/(\d{1,3})([^\]]*)]\s+(.*)', + content.decode('utf-8'), re.I | re.M) + if matches: + mgr = matches.groups() + # Set the subject to match cover letter + subject = '[%s %s/%s%s] %s' % (mgr[0].replace('PATCH', 'PSIGN'), 'X' * len(mgr[1]), + mgr[1], mgr[2], mgr[3]) continue logger.info('ADD | %s', os.path.basename(patchfile)) attid = '%s-%s-%s' % (ihash[:8], mhash[:8], phash[:8]) @@ -222,19 +233,38 @@ def create_attestation(cmdargs): att_msg = email.message.EmailMessage() att_msg.set_payload(signed.encode('utf-8')) - # GDPR-proofing: we don't care about the envelope. - # All we need is in the hashes and in the PGP payload - att_msg['From'] = '<devnull@kernel.org>' + sender = cmdargs.sender + if '>' not in sender: + sender = '<%s>' % sender + att_msg['From'] = sender att_msg['To'] = '<signatures@kernel.org>' att_msg['Message-Id'] = email.utils.make_msgid(domain='kernel.org') - att_msg['Subject'] = 'Patch attestation' + att_msg['Subject'] = subject - # Future iterations will be able to submit this to a RESTful URL at git.kernel.org, - # in order not to depend on avaialbility of SMTP gateways + logger.info('---') + # Try to deliver it via mail.kernel.org + try: + mailserver = smtplib.SMTP('mail.kernel.org', 587) + # identify ourselves to smtp gmail client + mailserver.ehlo() + # secure our email with tls encryption + mailserver.starttls() + # re-identify ourselves as an encrypted connection + mailserver.ehlo() + logger.info('Delivering via mail.kernel.org') + if cmdargs.dryrun: + raise Exception('Dry-run, not delivering mail.') + mailserver.sendmail('devnull@kernel.org', 'signatures@kernel.org', att_msg.as_string()) + mailserver.quit() + sys.exit(0) + except Exception as ex: + logger.info('Could not deliver: %s', ex) + + # Future iterations will also be able to submit this to a RESTful URL + # at git.kernel.org, in order not to depend on avaialbility of SMTP gateways with open(cmdargs.output, 'wb') as fh: fh.write(att_msg.as_bytes()) - logger.info('---') logger.info('Wrote %s', cmdargs.output) logger.info('You can send it using:') logger.info(' sendmail -oi signatures@kernel.org < %s', cmdargs.output) @@ -484,23 +514,32 @@ if __name__ == '__main__': parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter ) - parser.add_argument('-a', '--attest', nargs='+', + parser.add_argument('-q', '--quiet', action='store_true', default=False, + help='Only output errors to the stdout') + parser.add_argument('-v', '--verbose', action='store_true', default=False, + help='Be more verbose in logging output') + # Attestation arguments + agroup = parser.add_argument_group('attestation', 'Attestation parameters') + agroup.add_argument('-a', '--attest', nargs='+', help='Create attestation for patches') - parser.add_argument('-o', '--output', default='attestation.eml', + # GDPR-proofing: by default, we add as little PII-sensitive info as possible + agroup.add_argument('-f', '--from', dest='sender', default='devnull@kernel.org', + help='Use custom From field (use with -a)') + agroup.add_argument('-o', '--output', default='attestation.eml', help='Save attestation message in this file (use with -a)') - parser.add_argument('-c', '--check', + agroup.add_argument('-d', '--dry-run', dest='dryrun', action='store_true', default=False, + help='Do not send any mail') + # Verification arguments + vgroup = parser.add_argument_group('verification', 'Verification parameters') + vgroup.add_argument('-c', '--check', help='Check attestation for patches in an mbox file') - parser.add_argument('-i', '--attestation-file', dest='attfile', + vgroup.add_argument('-i', '--attestation-file', dest='attfile', help='Use this file for attestation data instead of querying lore.kernel.org') - parser.add_argument('-t', '--tofu', action='store_true', default=False, + vgroup.add_argument('-t', '--tofu', action='store_true', default=False, help='Force TOFU trust model (otherwise uses your global GnuPG setting)') - parser.add_argument('-X', '--no-fast-exit', dest='nofast', action='store_true', default=False, + vgroup.add_argument('-X', '--no-fast-exit', dest='nofast', action='store_true', default=False, help='Do not exit after first failure') - parser.add_argument('-F', '--ignore-from-mismatch', dest='ignorefrom', action='store_true', + vgroup.add_argument('-F', '--ignore-from-mismatch', dest='ignorefrom', action='store_true', default=False, help='Ignore mismatches between From: and PGP uid data') - parser.add_argument('-q', '--quiet', action='store_true', default=False, - help='Only output errors to the stdout') - parser.add_argument('-v', '--verbose', action='store_true', default=False, - help='Be more verbose in logging output') main(parser.parse_args()) |