Decrypt ciphertext using gpgsm if the user has indicated that it's ok.

Signed-off-by: Daniel Kahn Gillmor <d...@fifthhorseman.net>
---
 debian/control                   |  1 +
 email-print-mime-structure       | 31 +++++++++++++++++++++++++++++++
 email-print-mime-structure.1.pod |  8 ++++----
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/debian/control b/debian/control
index 72b57c3..aa44863 100644
--- a/debian/control
+++ b/debian/control
@@ -46,6 +46,7 @@ Recommends:
 Suggests:
  gpg,
  gpg-agent,
+ gpgsm,
 Architecture: all
 Description: collection of scripts for manipulating e-mail on Debian
  This package provides a collection of scripts for manipulating e-mail
diff --git a/email-print-mime-structure b/email-print-mime-structure
index 27fb532..ab90976 100755
--- a/email-print-mime-structure
+++ b/email-print-mime-structure
@@ -81,6 +81,7 @@ class MimePrinter(object):
         cryptopayload:Optional[Message] = None
         ciphertext:Union[List[Message],str,bytes,None] = None
         try_pgp_decrypt:bool = self.args.pgpkey or self.args.use_gpg_agent
+        try_cms_decrypt:bool = self.args.use_gpg_agent
 
         if try_pgp_decrypt and \
            (parent is not None) and \
@@ -99,6 +100,19 @@ class MimePrinter(object):
                 logging.warning(f'Unable to decrypt')
                 return
 
+        if try_cms_decrypt and \
+           cryptopayload is None and \
+           z.get_content_type().lower() == 'application/pkcs7-mime':
+            ciphertext = z.get_payload(decode=True)
+            if not isinstance(ciphertext, bytes):
+                logging.warning('encrypted part was not a leaf mime part 
somehow')
+                return
+            if self.args.use_gpg_agent:
+                cryptopayload = self.gpgsm_decrypt(ciphertext)
+            if cryptopayload is None:
+                logging.warning(f'Unable to decrypt')
+                return
+
         if cryptopayload is not None:
             newprefix = prefix[:-3] + ' '
             print(f'{newprefix}↧ (decrypts to)')
@@ -134,6 +148,23 @@ class MimePrinter(object):
             return email.message_from_bytes(out.stdout)
         return None
 
+    def gpgsm_decrypt(self, ciphertext:bytes) -> Optional[Message]:
+        inp:int
+        outp:int
+        inp, outp = os.pipe()
+        with open(outp, 'wb') as outf:
+            outf.write(ciphertext)
+        try:
+            out:subprocess.CompletedProcess[bytes] = subprocess.run(['gpgsm', 
'--batch', '--decrypt'],
+                                                                    stdin=inp,
+                                                                    
capture_output=True)
+        except Exception as e:
+            logging.warning(f'Failed to decrypt with gpgsm: {e}')
+            return None
+        if out.returncode == 0:
+            return email.message_from_bytes(out.stdout)
+        return None
+
     def print_tree(self, z:Message, prefix:str, parent:Optional[Message], 
num:int) -> None:
         if (z.is_multipart()):
             self.print_part(z, prefix+'┬╴', parent, num)
diff --git a/email-print-mime-structure.1.pod b/email-print-mime-structure.1.pod
index d8545ad..f109997 100644
--- a/email-print-mime-structure.1.pod
+++ b/email-print-mime-structure.1.pod
@@ -35,8 +35,8 @@ do not interact with any local GnuPG keyring.
 =item B<--use-gpg-agent>
 
 If this flag is present, and B<email-print-mime-structure> encounters
-a PGP/MIME-encrypted part, it will try to decrypt the part using the
-secret keys found in the local installation of GnuPG.
+a PGP/MIME- or S/MIME-encrypted part, it will try to decrypt the part
+using the secret keys found in the local installation of GnuPG.
 
 If both B<--pgpkey=>I<KEYFILE> and B<--use-gpg-agent> are
 supplied, I<KEYFILE> arguments will be tried before falling back to
@@ -49,8 +49,8 @@ stderr.
 
 =item B<--no-use-gpg-agent>
 
-Don't try to decrypt PGP/MIME-encrypted parts using secret keys found
-in the local installation of GnuPG.  This is the default.
+Don't try to decrypt PGP/MIME- or S/MIME-encrypted parts using secret
+keys found in the local installation of GnuPG.  This is the default.
 
 =item B<--help>, B<-h>
 
-- 
2.24.0

Reply via email to