Reported by: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net>
Date: Fri, 16 May 2025 03:57:02 UTC
Severity: normal
Found in version 30.1
Message #38 received at 78448 <at> debbugs.gnu.org (full text, mbox):
From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> To: Robert Pluim <rpluim <at> gmail.com> Cc: eric <at> ericabrahamsen.net, 78448 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org>, rms <at> gnu.org Subject: Re: bug#78448: 30.1; mml: Produce Unobtrusive Signatures Date: Mon, 09 Jun 2025 18:54:01 -0400
[Message part 1 (text/plain, inline)]
On Mon 2025-06-09 14:45:23 +0200, Robert Pluim wrote: > I just tried it, I needed the small patch below to get it to compile > without warnings. […] > diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el > index 972f1bce0a1..cfe4709f275 100644 > --- a/lisp/gnus/mml.el > +++ b/lisp/gnus/mml.el > @@ -494,6 +494,9 @@ mml-inhibit-compute-boundary > (declare-function libxml-parse-html-region "xml.c" > (start end &optional base-url discard-comments)) > > +(defvar message-ignored-mail-headers) > +(declare-function message-cleanup-headers "message") > + > (defun mml-get-likely-headers () > "Get likely final headers from the existing message" > (save-excursion Thanks for this! I've updated the patch series to include your feedback, and to drop the Signed-off-by: lines that were interfering with the project expectations. I'm including the three revised patches here. Please let me know if you notice anything else that needs improvement. Regards, --dkg
[0001-mml-Pass-likely-headers-through-to-mml-sec-functions.patch (text/x-diff, inline)]
From 3a27bb0ce3a18eff2fd965a1f7da6a97a45a6744 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 21:49:32 -0400 Subject: [PATCH 1/3] mml: Pass likely headers through to mml-sec functions By pre-computing the likely headers for an outbound message, and passing them along as a tag in mml-parse, we create an opportunity to provide Header Protection as described in https://datatracker.ietf.org/doc/draft-ietf-lamps-header-protection/ --- lisp/gnus/mml.el | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 51d8d2c3769..8e37dbe0bf6 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -265,6 +265,8 @@ part. This is for the internal use, you should never modify the value.") (apply #'mml-insert-tag secure-mode `(,@tags + ,"likely-headers" + ,(mml-get-likely-headers) ,(if keyfile "keyfile") ,keyfile ,@(apply #'append @@ -492,6 +494,24 @@ If MML is non-nil, return the buffer up till the correspondent mml tag." (declare-function libxml-parse-html-region "xml.c" (start end &optional base-url discard-comments)) +(defvar message-ignored-mail-headers) +(declare-function message-cleanup-headers "message") + +(defun mml-get-likely-headers () + "Get likely final headers from the existing message" + (save-excursion + (save-restriction + (message-narrow-to-headers-or-head) + (let ((x (buffer-substring (point-min) (point-max)))) + (with-temp-buffer + (insert x) + (message-remove-header "Bcc") + (message-remove-header message-ignored-mail-headers t) + (mail-encode-encoded-word-buffer) + (message-cleanup-headers) + (buffer-string) + ))))) + (defun mml-generate-mime (&optional multipart-type content-type) "Generate a MIME message based on the current MML document. MULTIPART-TYPE defaults to \"mixed\", but can also -- 2.47.2
[0002-mml-Enable-production-of-Unobtrusive-Signatures-via-.patch (text/x-diff, inline)]
From 9b4beb63f36c7af2f7b5b63c8fd81f2ac7bc877e Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 21:54:06 -0400 Subject: [PATCH 2/3] mml: Enable production of Unobtrusive Signatures via epg https://datatracker.ietf.org/doc/draft-gallagher-email-invisible-signatures/ describes a mechanism to produce cleartext signatures over MIME messages that are less likely to cause problems than traditional PGP/MIME. With this patch, it's possible to produce those signatures with: (mml-secure-message "unobtrusive" 'sign) This patch only works with epg, not with mailcrypt or pgg, because epg is what i'm familiar with and what i can easily test. --- lisp/gnus/mml-sec.el | 6 ++++++ lisp/gnus/mml2015.el | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 8dffcf872f3..6fb82836e9a 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -34,6 +34,7 @@ (autoload 'mail-strip-quoted-names "mail-utils") (autoload 'mml2015-sign "mml2015") (autoload 'mml2015-encrypt "mml2015") +(autoload 'mml-unobtrusive-sign "mml2015") (autoload 'mml1991-sign "mml1991") (autoload 'mml1991-encrypt "mml1991") (autoload 'message-fetch-field "message") @@ -56,6 +57,7 @@ '(("smime" mml-smime-sign-buffer mml-smime-sign-query) ("pgp" mml-pgp-sign-buffer list) ("pgpauto" mml-pgpauto-sign-buffer list) + ("unobtrusive" mml-unobtrusive-sign-buffer list) ("pgpmime" mml-pgpmime-sign-buffer list)) "Alist of MIME signer functions.") @@ -198,6 +200,10 @@ You can also customize or set `mml-signencrypt-style-alist' instead." (or (mml2015-sign cont) (error "Signing failed... inspect message logs for errors"))) +(defun mml-unobtrusive-sign-buffer (cont) + (or (mml-unobtrusive-sign cont) + (error "Signing failed... inspect message logs for errors"))) + (defun mml-pgpmime-encrypt-buffer (cont &optional sign) (or (mml2015-encrypt cont sign) (error "Encryption failed... inspect message logs for errors"))) diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el index a46aa68f56a..bbe6cec589f 100644 --- a/lisp/gnus/mml2015.el +++ b/lisp/gnus/mml2015.el @@ -25,6 +25,9 @@ ;; RFC 2015 is updated by RFC 3156, this file should be compatible ;; with both. +;; This is also capable of producing unobtrusive signatures based on +;; draft-gallagher-email-unobtrusive-signatures + ;;; Code: (eval-when-compile (require 'cl-lib)) @@ -945,6 +948,42 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." (insert (format "--%s--\n" boundary)) (goto-char (point-max)))) +;;; Unobtrusive Signatures, see: +;;; https://datatracker.ietf.org/doc/draft-gallagher-email-unobtrusive-signatures/ + +; convert ASCII-armored PGP SIGNATURE block to base64-encoded with FWS +; at the start of each line: +(defun pgpsig-armor-to-wrapped-b64 (s) + (string-join + (string-split + (string-trim-right + (string-trim-left s "-----BEGIN PGP SIGNATURE-----\n\\(?:[^\n]+\n\\)*\n") + "\n\\(?:=....\n\\)?-----END PGP SIGNATURE-----\n?") + "\n") + "\n ")) + +(defun mml-unobtrusive-sign (cont) + (goto-char (point-min)) + (insert (cdr (assq 'likely-headers cont))) + (re-search-forward "^Content-Type: [^\n]*\\(\n[ \t][^\n]*$\\)*") + (insert "; hp=\"clear\"") + (forward-line 1) + (let* ((pair (mml-secure-epg-sign 'OpenPGP t)) + (signature (car pair))) + (unless (stringp signature) + (error "Signature failed")) + (goto-char (point-min)) + (insert (format "Sig: t=p; b=%s\n" + (pgpsig-armor-to-wrapped-b64 signature))) + (let ((boundary (mml-compute-boundary cont))) + (goto-char (point-min)) + (insert (format "Content-Type: multipart/mixed; boundary=\"%s\";\n" + boundary)) + (insert (format "\n--%s\n" boundary)) + (goto-char (point-max)) + (insert (format "\n--%s--\n" boundary)) + (goto-char (point-max))))) + ;;; General wrapper (autoload 'gnus-buffer-live-p "gnus-util") -- 2.47.2
[0003-mml-Add-C-c-RET-s-u-to-make-Unobtrusive-Signature.patch (text/x-diff, inline)]
From 8ec14c812328ae1b4180656f8813211d83215b42 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 22:03:25 -0400 Subject: [PATCH 3/3] mml: Add C-c RET s u to make Unobtrusive Signature This adds to the default keymap to make it relatively easy to make an Unobtrusive Signature when sending mail. Unobtrusive Signatures are defined on a per-message basis, and explicitly ignored per-part, so we do not facilitate part-based signing. --- lisp/gnus/mml-sec.el | 5 +++++ lisp/gnus/mml.el | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 6fb82836e9a..71913c8e8cc 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -399,6 +399,11 @@ Use METHOD if given. Else use `mml-secure-method' or (or method mml-secure-method mml-default-sign-method) 'encrypt)) +(defun mml-secure-message-sign-unobtrusive () + "Add MML tag to encrypt/sign the entire message." + (interactive nil mml-mode) + (mml-secure-message "unobtrusive" 'sign)) + (defun mml-secure-message-sign-smime () "Add MML tag to encrypt/sign the entire message." (interactive nil mml-mode) diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 8e37dbe0bf6..0667c937803 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -1181,7 +1181,8 @@ If HANDLES is non-nil, use it instead reparsing the buffer." "s" (define-keymap "p" #'mml-secure-message-sign-pgpmime "o" #'mml-secure-message-sign-pgp - "s" #'mml-secure-message-sign-smime) + "s" #'mml-secure-message-sign-smime + "u" #'mml-secure-message-sign-unobtrusive) "S" (define-keymap "p" #'mml-secure-sign-pgpmime "o" #'mml-secure-sign-pgp -- 2.47.2
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.