From 4caa45c7cf679cf5f3a356248f38431380747547 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 27 Jul 2019 13:36:42 +0100 Subject: add CONTRIBUTING.rst Signed-off-by: Sean Whitton --- CONTRIBUTING.rst | 15 +++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 CONTRIBUTING.rst diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 0000000..707e2f6 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,15 @@ +Signing off your commits +======================== + +Contributions are accepted upstream under the terms set out in +``debian/copyright`` and in the headers of individual source files. +Completely new scripts can use any DFSG-compatible license. You must +certify the contents of the file ``DEVELOPER-CERTIFICATE`` for your +contribution. To do this, append a ``Signed-off-by`` line to end of +your commit message. An easy way to add this line is to pass the +``-s`` option to git-commit(1). Here is an example of a +``Signed-off-by`` line: + +:: + + Signed-off-by: Sean Whitton diff --git a/debian/changelog b/debian/changelog index 07694b8..0174fd6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +mailscripts (0.10-1) UNRELEASED; urgency=medium + + * Add CONTRIBUTING.rst. + + -- Sean Whitton Sat, 27 Jul 2019 13:35:17 +0100 + mailscripts (0.9-1) unstable; urgency=medium * Fix docstring for notmuch-extract-thread-patches not to say that the -- cgit v1.2.3 From 701c568e78d17f00d44c51201736177323d03e32 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 27 Jul 2019 13:36:59 +0100 Subject: d/copyright: completely new scripts may use any DFSG license Signed-off-by: Sean Whitton --- debian/changelog | 1 + debian/copyright | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0174fd6..3b0cc45 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ mailscripts (0.10-1) UNRELEASED; urgency=medium * Add CONTRIBUTING.rst. + * d/copyright: completely new scripts may use any DFSG-compatible license. -- Sean Whitton Sat, 27 Jul 2019 13:35:17 +0100 diff --git a/debian/copyright b/debian/copyright index b3d860e..129a7bb 100644 --- a/debian/copyright +++ b/debian/copyright @@ -22,8 +22,9 @@ The contents of the notmuch-extract-patch/ directory was imported from https://github.com/aaptel/notmuch-extract-patch/ using git-subtree(1) -Contributions are accepted upstram under the same terms; please sign -off your patches (by writing an approprite Signed-Off-By tag in your +Contributions are accepted upstream under the same terms (or another +DFSG-compatible license for completely new scripts); please sign off +your patches (by writing an approprite Signed-Off-By tag in your commit message or patch submission) to indicate your attestation that the Developer Certificate of Origin (version 1.1) applies. -- cgit v1.2.3 From 5929eabef63e0167ead14a81f30097c9397f7ee4 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Thu, 25 Jul 2019 12:38:52 -0400 Subject: Add email-extract-openpgp-certs Hopefully this tool is useful for other people, not just for myself and Anarcat. Signed-off-by: Daniel Kahn Gillmor --- Makefile | 1 + debian/copyright | 1 + email-extract-openpgp-certs | 99 +++++++++++++++++++++++++++++++++++++++ email-extract-openpgp-certs.1.pod | 57 ++++++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100755 email-extract-openpgp-certs create mode 100644 email-extract-openpgp-certs.1.pod diff --git a/Makefile b/Makefile index 220aa6f..48cb2fa 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ MANPAGES=mdmv.1 mbox2maildir.1 \ notmuch-slurp-debbug.1 notmuch-extract-patch.1 maildir-import-patch.1 \ + email-extract-openpgp-certs.1 \ notmuch-import-patch.1 all: $(MANPAGES) diff --git a/debian/copyright b/debian/copyright index 129a7bb..f6f2e0e 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,6 +3,7 @@ Collection of scripts for manipulating e-mail on Debian Copyright (C)2017 Aurelien Aptel Copyright (C)2017-2019 Sean Whitton +Copyright (C)2019 Daniel Kahn Gillmor These programs are free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/email-extract-openpgp-certs b/email-extract-openpgp-certs new file mode 100755 index 0000000..dfe6138 --- /dev/null +++ b/email-extract-openpgp-certs @@ -0,0 +1,99 @@ +#!/usr/bin/python3 + +'''Extract all OpenPGP certificates from an e-mail message + +This is a simple script that is designed to take an e-mail +(rfc822/message) on standard input, and produces a series of +ASCII-armored OpenPGP certificates on standard output. + +It currently tries to find OpenPGP certificates based on MIME types of +attachments (application/pgp-keys), and by pulling out anything that +looks like an Autocrypt: or Autocrypt-Gossip: header (see +https://autocrypt.org). + +''' + +import email +import sys +import base64 +import binascii +import codecs +from typing import Optional, Generator + +# parse email from stdin +message = email.message_from_binary_file(sys.stdin.buffer) + +def openpgp_ascii_armor_checksum(data: bytes) -> bytearray: + '''OpenPGP ASCII-armor checksum + +(see https://tools.ietf.org/html/rfc4880#section-6.1)''' + + init = 0xB704CE + poly = 0x1864CFB + crc = init + for b in data: + crc ^= b << 16 + for i in range(8): + crc <<= 1 + if crc & 0x1000000: + crc ^= poly + val = crc & 0xFFFFFF + out = bytearray(3) + out[0] = (val >> 16) & 0xFF + out[1] = (val >> 8) & 0xFF + out[2] = val & 0xFF + return out + +def enarmor_certificate(data: bytes) -> str: + '''OpenPGP ASCII-armor + +(see https://tools.ietf.org/html/rfc4880#section-6.2)''' + + cksum = openpgp_ascii_armor_checksum(data) + key = codecs.decode(base64.b64encode(data), 'ascii') + linelen = 64 + key = '\n'.join([key[i:i+linelen] for i in range(0, len(key), linelen)]) + return '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n' +\ + key + \ + '\n=' + codecs.decode(base64.b64encode(cksum), 'ascii') +\ + '\n-----END PGP PUBLIC KEY BLOCK-----\n' + +def get_autocrypt_keys(m: email.message.Message) -> Generator[str, None, None]: + '''Extract all Autocrypt headers from message + +Note that we ignore the addr= property. +''' + hdrs = m.get_all('Autocrypt') + if hdrs is None: # the email.get_all() api is kindn of sad. + hdrs = [] + ghdrs = m.get_all('Autocrypt-Gossip') + if ghdrs is None: # the email.get_all() api is kindn of sad. + ghdrs = [] + for ac in hdrs + ghdrs: + # parse the base64 part + try: + keydata = str(ac).split('keydata=')[1].strip() + keydata = keydata.replace(' ', '').replace('\t', '') + keydatabin = base64.b64decode(keydata) + yield enarmor_certificate(keydatabin) + except (binascii.Error, IndexError) as e: + print("failure to parse Autocrypt header: %s" % e, + file=sys.stderr) + +def extract_attached_keys(m: email.message.Message) -> Generator[str, None, None]: + for part in m.walk(): + if part.get_content_type() == 'application/pgp-keys': + p = part.get_payload(decode=True) + if not isinstance(p, bytes): + raise TypeError('Expected part payload to be bytes') + if p.startswith(b'-----BEGIN PGP PUBLIC KEY BLOCK-----\n'): + yield codecs.decode(p, 'ascii') + else: # this is probably binary-encoded, let's pretend that it is! + yield enarmor_certificate(p) + +# FIXME: should we try to decrypt encrypted messages as well? + +for a in get_autocrypt_keys(message): + print(a, end='') +for a in extract_attached_keys(message): + print(a, end='') diff --git a/email-extract-openpgp-certs.1.pod b/email-extract-openpgp-certs.1.pod new file mode 100644 index 0000000..8b7916e --- /dev/null +++ b/email-extract-openpgp-certs.1.pod @@ -0,0 +1,57 @@ +=head1 NAME + +email-extract-openpgp-certs - extract OpenPGP certificates from an e-mail + +=head1 SYNOPSIS + +B < B | B B<--import> + +=head1 DESCRIPTION + +B extracts all the things it can find +that look like they might be OpenPGP certificates in an e-mail, and +produces them on standard output. + +It currently knows about how to find OpenPGP certificates as +attachments of MIME type application/pgp-keys, and Autocrypt: style +headers. + +=head1 OPTIONS + +None. + +=head1 EXAMPLE + +=over 4 + + $ notmuch show --format-raw id:b7e48905-842f@example.net > test.eml + $ email-extract-openpgp-certs < test.eml | gpg --import + +=back + +=head1 LIMITATIONS + +B currently does not try to decrypt +encrypted e-mails, so it cannot find certificates that are inside the +message's cryptographic envelope. + +B does not attempt to validate the +certificates it finds in any way. It does not ensure that they are +valid OpenPGP certificates, or even that they are of a sane size. It +doeds not try to establish any relationship between the extracted +certificates and the messages in which they are sent. For example, it +does not check the Autocrypt addr= attribute against the message's From: +header. + +Importing certificates extracted from an arbitrary e-mail in this way +into a curated keyring is not a good idea. Better to extract into an +ephemeral location, inspect, filter, and then selectively import. + +=head1 SEE ALSO + +gpg(1), https://autocrypt.org, https://tools.ietf.org/html/rfc4880, https://tools.ietf.org/html/rfc3156 + +=head1 AUTHOR + +B and this manpage were written by Daniel +Kahn Gillmor, with guidance and advice from many others. -- cgit v1.2.3 From 35a621acf6fba68a8fd5045a51e01d67d3786abe Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Mon, 29 Jul 2019 07:38:58 +0100 Subject: add a GPL-3+ copyright header to email-extract-openpgp-certs See . Signed-off-by: Sean Whitton --- email-extract-openpgp-certs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/email-extract-openpgp-certs b/email-extract-openpgp-certs index dfe6138..2a95748 100755 --- a/email-extract-openpgp-certs +++ b/email-extract-openpgp-certs @@ -1,5 +1,20 @@ #!/usr/bin/python3 +# Copyright (C) 2019 Daniel Kahn Gillmor +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + '''Extract all OpenPGP certificates from an e-mail message This is a simple script that is designed to take an e-mail -- cgit v1.2.3 From 35a27626696d3cf5ecddaf9816881429aff805b3 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Mon, 29 Jul 2019 07:40:10 +0100 Subject: email-extract-openpgp-certs(1): Improve redirection readability At least to me. Signed-off-by: Sean Whitton --- email-extract-openpgp-certs.1.pod | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/email-extract-openpgp-certs.1.pod b/email-extract-openpgp-certs.1.pod index 8b7916e..9983de0 100644 --- a/email-extract-openpgp-certs.1.pod +++ b/email-extract-openpgp-certs.1.pod @@ -4,7 +4,7 @@ email-extract-openpgp-certs - extract OpenPGP certificates from an e-mail =head1 SYNOPSIS -B < B | B B<--import> +B | B B<--import> =head1 DESCRIPTION @@ -24,8 +24,8 @@ None. =over 4 - $ notmuch show --format-raw id:b7e48905-842f@example.net > test.eml - $ email-extract-openpgp-certs < test.eml | gpg --import + $ notmuch show --format-raw id:b7e48905-842f@example.net >test.eml + $ email-extract-openpgp-certs Date: Mon, 29 Jul 2019 07:41:26 +0100 Subject: changelog Signed-off-by: Sean Whitton --- debian/changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/changelog b/debian/changelog index 3b0cc45..80bcf82 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,7 @@ mailscripts (0.10-1) UNRELEASED; urgency=medium + * New script: email-extract-openpgp-certs(1). + Thanks to Daniel Kahn Gillmor for the patch. * Add CONTRIBUTING.rst. * d/copyright: completely new scripts may use any DFSG-compatible license. -- cgit v1.2.3 From a2184676e1d6c57fb88f028a4232ee741dde9660 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Mon, 29 Jul 2019 07:43:17 +0100 Subject: install email-extract-openpgp-certs & its manpage to the deb Signed-off-by: Sean Whitton --- debian/mailscripts.install | 1 + debian/mailscripts.manpages | 1 + 2 files changed, 2 insertions(+) diff --git a/debian/mailscripts.install b/debian/mailscripts.install index 36b87ea..d6f69f5 100644 --- a/debian/mailscripts.install +++ b/debian/mailscripts.install @@ -4,3 +4,4 @@ notmuch-slurp-debbug /usr/bin maildir-import-patch /usr/bin notmuch-import-patch /usr/bin notmuch-extract-patch/notmuch-extract-patch /usr/bin +email-extract-openpgp-certs /usr/bin diff --git a/debian/mailscripts.manpages b/debian/mailscripts.manpages index fa878ca..ab761b2 100644 --- a/debian/mailscripts.manpages +++ b/debian/mailscripts.manpages @@ -4,3 +4,4 @@ notmuch-slurp-debbug.1 maildir-import-patch.1 notmuch-import-patch.1 notmuch-extract-patch.1 +email-extract-openpgp-certs.1 -- cgit v1.2.3 From 197931ab76ca5bb620652035a10154ee3e5bd241 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Tue, 30 Jul 2019 13:25:30 +0100 Subject: close bug Signed-off-by: Sean Whitton --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 80bcf82..d8203ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ mailscripts (0.10-1) UNRELEASED; urgency=medium - * New script: email-extract-openpgp-certs(1). + * New script: email-extract-openpgp-certs(1) (Closes: #932993). Thanks to Daniel Kahn Gillmor for the patch. * Add CONTRIBUTING.rst. * d/copyright: completely new scripts may use any DFSG-compatible license. -- cgit v1.2.3 From 1cb54e1d5000856bfedd98c5cf4274aa411e44c3 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Tue, 30 Jul 2019 13:25:41 +0100 Subject: release 0.10 (0.10-1 to Debian unstable) Signed-off-by: Sean Whitton --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d8203ac..379199e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,11 @@ -mailscripts (0.10-1) UNRELEASED; urgency=medium +mailscripts (0.10-1) unstable; urgency=medium * New script: email-extract-openpgp-certs(1) (Closes: #932993). Thanks to Daniel Kahn Gillmor for the patch. * Add CONTRIBUTING.rst. * d/copyright: completely new scripts may use any DFSG-compatible license. - -- Sean Whitton Sat, 27 Jul 2019 13:35:17 +0100 + -- Sean Whitton Tue, 30 Jul 2019 13:25:36 +0100 mailscripts (0.9-1) unstable; urgency=medium -- cgit v1.2.3