From f9fb01a6b013963e0d8021b5da587cc548c1ea9a Mon Sep 17 00:00:00 2001 From: Jens Lechtenboerger Date: Sun, 27 Dec 2015 16:29:02 +0100 Subject: [PATCH] Identify unsafe combinations of Bcc and encryption --- ChangeLog.2 | 8 ++++++++ lisp/gnus/gnus-util.el | 10 ++++++++++ lisp/gnus/mml-sec.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/ChangeLog.2 b/ChangeLog.2 index 6d72663..971a3b5 100644 --- a/ChangeLog.2 +++ b/ChangeLog.2 @@ -1,3 +1,11 @@ +2015-12-27 Jens Lechtenboerger + + Identify unsafe combinations of Bcc and encryption + + * lisp/gnus/gnus-util.el (gnus-subsetp): New function + * lisp/gnus/mml-sec.el (mml-secure-safe-bcc-list): New variable + * lisp/gnus/mml-sec.el (mml-secure-bcc-is-safe): New function + 2015-12-27 Lars Ingebrigtsen * shr.el (shr-descend): Allow using lambdas in external functions. diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el index 40e2dcf..933387d 100644 --- a/lisp/gnus/gnus-util.el +++ b/lisp/gnus/gnus-util.el @@ -1989,6 +1989,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/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 45da937..dbae280 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -122,6 +122,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 +287,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 hdr "," 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)) -- 1.9.1