From 829fe7e073a13eaf991e04e90b1e731b1ccce0c2 Mon Sep 17 00:00:00 2001 From: Jens Lechtenboerger Date: Mon, 28 Dec 2015 01:35:02 +0000 Subject: [PATCH] Identify unsafe combinations of Bcc and encryption * gnus-util.el (gnus-subsetp): New function. * mml-sec.el: Fix warnings by adding autoloads (bug#18718). (mml-secure-safe-bcc-list): New variable. (mml-secure-is-encrypted-p, mml-secure-bcc-is-safe): New functions. --- lisp/ChangeLog | 8 ++++++++ lisp/gnus-util.el | 10 ++++++++++ lisp/mml-sec.el | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 058e47a23..382657782 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,11 @@ +2015-12-27 Jens Lechtenboerger + + * gnus-util.el (gnus-subsetp): New function. + + * mml-sec.el: Fix warnings by adding autoloads (bug#18718). + (mml-secure-safe-bcc-list): New variable. + (mml-secure-is-encrypted-p, mml-secure-bcc-is-safe): New functions. + 2015-12-23 Katsumi Yamaoka Fix `gnus-union' so as to behave like `cl-union'. diff --git a/lisp/gnus-util.el b/lisp/gnus-util.el index 6759c0715..63ae2e628 100644 --- a/lisp/gnus-util.el +++ b/lisp/gnus-util.el @@ -1996,6 +1996,16 @@ to case differences." (defun gnus-timer--function (timer) (elt timer 5))) +(defun gnus-subsetp (list1 list2) + "Return t if LIST1 is a subset of LIST2. +Similar to `subsetp' but use member for element test so that this works for +lists of strings." + (when (and (listp list1) (listp list2)) + (if list1 + (and (member (car list1) list2) + (gnus-subsetp (cdr list1) list2)) + t))) + (provide 'gnus-util) ;;; gnus-util.el ends here diff --git a/lisp/mml-sec.el b/lisp/mml-sec.el index 45da9371a..4f57cb76c 100644 --- a/lisp/mml-sec.el +++ b/lisp/mml-sec.el @@ -25,10 +25,13 @@ (eval-when-compile (require 'cl)) +(autoload 'gnus-subsetp "gnus-util") +(autoload 'mail-strip-quoted-names "mail-utils") (autoload 'mml2015-sign "mml2015") (autoload 'mml2015-encrypt "mml2015") (autoload 'mml1991-sign "mml1991") (autoload 'mml1991-encrypt "mml1991") +(autoload 'message-fetch-field "message") (autoload 'message-goto-body "message") (autoload 'mml-insert-tag "mml") (autoload 'mml-smime-sign "mml-smime") @@ -122,6 +125,21 @@ Whether the passphrase is cached at all is controlled by :group 'message :type 'integer) +(defcustom mml-secure-safe-bcc-list nil + "List of e-mail addresses that are safe to use in Bcc headers. +EasyPG encrypts e-mails to Bcc addresses, and the encrypted e-mail +by default identifies the used encryption keys, giving away the +Bcc'ed identities. Clearly, this contradicts the original goal of +*blind* copies. +For an academic paper explaining the problem, see URL +`http://crypto.stanford.edu/portia/papers/bb-bcc.pdf'. +Use this variable to specify e-mail addresses whose owners do not +mind if they are identifiable as recipients. This may be useful if +you use Bcc headers to encrypt e-mails to yourself." + :version "25.1" + :group 'message + :type '(repeat string)) + ;;; Configuration/helper functions (defun mml-signencrypt-style (method &optional style) @@ -272,6 +290,37 @@ Use METHOD if given. Else use `mml-secure-method' or (interactive) (mml-secure-part "smime")) +(defun mml-secure-is-encrypted-p () + "Check whether secure encrypt tag is present." + (save-excursion + (goto-char (point-min)) + (re-search-forward + (concat "^" (regexp-quote mail-header-separator) "\n" + "<#secure[^>]+encrypt") + nil t))) + +(defun mml-secure-bcc-is-safe () + "Check whether usage of Bcc is safe (or absent). +Bcc usage is safe in two cases: first, if the current message does +not contain an MML secure encrypt tag; +second, if the Bcc addresses are a subset of `mml-secure-safe-bcc-list'. +In all other cases, ask the user whether Bcc usage is safe. +Raise error if user answers no. +Note that this function does not produce a meaningful return value: +either an error is raised or not." + (when (mml-secure-is-encrypted-p) + (let ((bcc (mail-strip-quoted-names (message-fetch-field "bcc")))) + (when bcc + ;; Split recipients at "," boundary, omit empty strings (t), + ;; and strip whitespace. + (let ((bcc-list (split-string bcc "," t "\\s-+"))) + (unless (gnus-subsetp bcc-list mml-secure-safe-bcc-list) + (unless (yes-or-no-p "Message for encryption contains Bcc header.\ + This may give away all Bcc'ed identities to all recipients.\ + Are you sure that this is safe?\ + (Customize `mml-secure-safe-bcc-list' to avoid this warning.) ") + (error "Aborted")))))))) + ;; defuns that add the proper <#secure ...> tag to the top of the message body (defun mml-secure-message (method &optional modesym) (let ((mode (prin1-to-string modesym)) -- 2.25.1