summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Fieber <sebastian.fieber@web.de>2021-12-24 10:43:52 +0100
committerLars Ingebrigtsen <larsi@gnus.org>2021-12-24 10:43:52 +0100
commitb6fac9aaaf21c12a25e1cbec9cb8b8d14d2dc8a8 (patch)
treef50a3eaf22d8e4b0b862982473dd085c85866e54
parentb9015606d169d3a70c0c690e8107b894fe62b7cb (diff)
downloademacs-b6fac9aaaf21c12a25e1cbec9cb8b8d14d2dc8a8.tar.gz
verify signed content in smime encrypted and signed message
* lisp/gnus/gnus-art.el (gnus-mime-display-part): Parse pkcs7 parts (bug#40397). (gnus-mime-security-verify-or-decrypt): (gnus-insert-mime-security-button): Handle these parts. * lisp/gnus/mm-decode.el (mm-verify-function-alist): Add pkcs7 functions. (mm-decrypt-function-alist): Handle them. (mm-possibly-verify-or-decrypt): Ditto. * lisp/gnus/mm-view.el (mm-view-pkcs7-decrypt): Handle pkcs7. Changes: - structure the result of mm-dissect-buffer of application/pkcs7-mime like a multipart mail so there is no loosing of information of verification and decryption results which can now be displayed by gnus-mime-display-security - adjust gnus-mime-display-part to handle application/pkcs7-mime like multipart/encrypted or multipart/signed - add dummy entries to mm-verify-function-alist and mm-decrypt-function-alist so gnus-mime-display-security correctly displays "S/MIME" and not "unknown protocol" - don't just check for multipart/signed in gnus-insert-mime-security-button but also for the pkcs7-mime mimetypes to print "Encrypted" or "Signed" accordingly in the security button - adjust mm-possibly-verify-or-decrypt to check for smime-type to ask wether to verify or decrypt the part and not to always ask to decrypt - adjust mm-view-pkcs7-decrypt and verify to call mm-sec-status so success information can be displayed by gnus-mime-display-security - adjust gnus-mime-security-verify-or-decrypt to handle pkcs7-mime right with the done changes
-rw-r--r--lisp/gnus/gnus-art.el83
-rw-r--r--lisp/gnus/mm-decode.el131
-rw-r--r--lisp/gnus/mm-view.el13
3 files changed, 157 insertions, 70 deletions
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index b7701f10a5e..3b3564fc30a 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -6084,6 +6084,34 @@ If nil, don't show those extra buttons."
((equal (car handle) "multipart/encrypted")
(gnus-add-wash-type 'encrypted)
(gnus-mime-display-security handle))
+ ;; pkcs7-mime handling:
+ ;;
+ ;; although not really multipart these are structured internally by
+ ;; mm-dissect-buffer like multipart to not discard the decryption
+ ;; and verification results
+ ;;
+ ;; application/pkcs7-mime
+ ((and (equal (car handle) "application/pkcs7-mime")
+ (equal (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/pkcs7-mime_signed-data"))
+ (gnus-add-wash-type 'signed)
+ (gnus-mime-display-security handle))
+ ((and (equal (car handle) "application/pkcs7-mime")
+ (equal (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/pkcs7-mime_enveloped-data"))
+ (gnus-add-wash-type 'encrypted)
+ (gnus-mime-display-security handle))
+ ;; application/x-pkcs7-mime
+ ((and (equal (car handle) "application/x-pkcs7-mime")
+ (equal (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/x-pkcs7-mime_signed-data"))
+ (gnus-add-wash-type 'signed)
+ (gnus-mime-display-security handle))
+ ((and (equal (car handle) "application/x-pkcs7-mime")
+ (equal (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/x-pkcs7-mime_enveloped-data"))
+ (gnus-add-wash-type 'encrypted)
+ (gnus-mime-display-security handle))
;; Other multiparts are handled like multipart/mixed.
(t
(gnus-mime-display-mixed (cdr handle)))))
@@ -8833,11 +8861,19 @@ For example:
(setq point (point))
(with-current-buffer (mm-handle-multipart-original-buffer handle)
(let* ((mm-verify-option 'known)
- (mm-decrypt-option 'known)
- (nparts (mm-possibly-verify-or-decrypt (cdr handle) handle)))
- (unless (eq nparts (cdr handle))
- (mm-destroy-parts (cdr handle))
- (setcdr handle nparts))))
+ (mm-decrypt-option 'known)
+ (pkcs7-mime-p (or (equal (car handle) "application/pkcs7-mime")
+ (equal (car handle) "application/x-pkcs7-mime")))
+ (nparts (if pkcs7-mime-p
+ (list (mm-possibly-verify-or-decrypt
+ (cadr handle) (cadadr handle)))
+ (mm-possibly-verify-or-decrypt (cdr handle) handle))))
+ (unless (eq nparts (cdr handle))
+ ;; if pkcs7-mime don't destroy the parts as the buffer in
+ ;; the cdr still needs to be accessible
+ (when (not pkcs7-mime-p)
+ (mm-destroy-parts (cdr handle)))
+ (setcdr handle nparts))))
(gnus-mime-display-security handle)
(when region
(delete-region (point) (cdr region))
@@ -8891,14 +8927,35 @@ For example:
(let* ((protocol (mm-handle-multipart-ctl-parameter handle 'protocol))
(gnus-tmp-type
(concat
- (or (nth 2 (assoc protocol mm-verify-function-alist))
- (nth 2 (assoc protocol mm-decrypt-function-alist))
- "Unknown")
- (if (equal (car handle) "multipart/signed")
- " Signed" " Encrypted")
- " Part"))
- (gnus-tmp-info
- (or (mm-handle-multipart-ctl-parameter handle 'gnus-info)
+ (or (nth 2 (assoc protocol mm-verify-function-alist))
+ (nth 2 (assoc protocol mm-decrypt-function-alist))
+ "Unknown")
+ (cond ((equal (car handle) "multipart/signed") " Signed")
+ ((equal (car handle) "multipart/encrypted") " Encrypted")
+ ((and (equal (car handle) "application/pkcs7-mime")
+ (equal
+ (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/pkcs7-mime_signed-data"))
+ " Signed")
+ ((and (equal (car handle) "application/pkcs7-mime")
+ (equal
+ (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/pkcs7-mime_enveloped-data"))
+ " Encrypted")
+ ;; application/x-pkcs7-mime
+ ((and (equal (car handle) "application/x-pkcs7-mime")
+ (equal
+ (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/x-pkcs7-mime_signed-data"))
+ " Signed")
+ ((and (equal (car handle) "application/x-pkcs7-mime")
+ (equal
+ (mm-handle-multipart-ctl-parameter handle 'protocol)
+ "application/x-pkcs7-mime_enveloped-data"))
+ " Encrypted"))
+ " Part"))
+ (gnus-tmp-info
+ (or (mm-handle-multipart-ctl-parameter handle 'gnus-info)
"Undecided"))
(gnus-tmp-details
(mm-handle-multipart-ctl-parameter handle 'gnus-details))
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index d781407cdcd..d2889a50c0a 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -474,6 +474,7 @@ The file will be saved in the directory `mm-tmp-directory'.")
(autoload 'mml2015-verify-test "mml2015")
(autoload 'mml-smime-verify "mml-smime")
(autoload 'mml-smime-verify-test "mml-smime")
+(autoload 'mm-view-pkcs7-verify "mm-view")
(defvar mm-verify-function-alist
'(("application/pgp-signature" mml2015-verify "PGP" mml2015-verify-test)
@@ -482,7 +483,15 @@ The file will be saved in the directory `mm-tmp-directory'.")
("application/pkcs7-signature" mml-smime-verify "S/MIME"
mml-smime-verify-test)
("application/x-pkcs7-signature" mml-smime-verify "S/MIME"
- mml-smime-verify-test)))
+ mml-smime-verify-test)
+ ("application/x-pkcs7-signature" mml-smime-verify "S/MIME"
+ mml-smime-verify-test)
+ ;; these are only used for security-buttons and contain the
+ ;; smime-type after the underscore
+ ("application/pkcs7-mime_signed-data" mm-view-pkcs7-verify "S/MIME"
+ nil)
+ ("application/x-pkcs7-mime_signed-data" mml-view-pkcs7-verify "S/MIME"
+ nil)))
(defcustom mm-verify-option 'never
"Option of verifying signed parts.
@@ -501,11 +510,17 @@ result of the verification."
(autoload 'mml2015-decrypt "mml2015")
(autoload 'mml2015-decrypt-test "mml2015")
+(autoload 'mm-view-pkcs7-decrypt "mm-view")
(defvar mm-decrypt-function-alist
'(("application/pgp-encrypted" mml2015-decrypt "PGP" mml2015-decrypt-test)
("application/x-gnus-pgp-encrypted" mm-uu-pgp-encrypted-extract-1 "PGP"
- mm-uu-pgp-encrypted-test)))
+ mm-uu-pgp-encrypted-test)
+ ;; these are only used for security-buttons and contain the
+ ;; smime-type after the underscore
+ ("application/pkcs7-mime_enveloped-data" mm-view-pkcs7-decrypt "S/MIME" nil)
+ ("application/x-pkcs7-mime_enveloped-data"
+ mm-view-pkcs7-decrypt "S/MIME" nil)))
(defcustom mm-decrypt-option nil
"Option of decrypting encrypted parts.
@@ -682,18 +697,35 @@ MIME-Version header before proceeding."
'start start)
(car ctl))
(cons (car ctl) (mm-dissect-multipart ctl from))))
- (t
- (mm-possibly-verify-or-decrypt
- (mm-dissect-singlepart
- ctl
- (and cte (intern (downcase (mail-header-strip-cte cte))))
- no-strict-mime
- (and cd (mail-header-parse-content-disposition cd))
- description id)
- ctl from))))
- (when id
- (when (string-match " *<\\(.*\\)> *" id)
- (setq id (match-string 1 id)))
+ (t
+ (let* ((handle
+ (mm-dissect-singlepart
+ ctl
+ (and cte (intern (downcase (mail-header-strip-cte cte))))
+ no-strict-mime
+ (and cd (mail-header-parse-content-disposition cd))
+ description id))
+ (intermediate-result
+ (mm-possibly-verify-or-decrypt handle ctl from)))
+ (when (and (equal type "application")
+ (or (equal subtype "pkcs7-mime")
+ (equal subtype "x-pkcs7-mime")))
+ (add-text-properties
+ 0 (length (car ctl))
+ (list 'protocol
+ (concat (substring-no-properties (car ctl))
+ "_"
+ (cdr (assoc 'smime-type ctl))))
+ (car ctl))
+ ;; If this is a pkcs7-mime lets treat this special and
+ ;; more like multipart so the pkcs7-mime part does not
+ ;; get ignored.
+ (setq intermediate-result
+ (cons (car ctl) (list intermediate-result))))
+ intermediate-result))))
+ (when id
+ (when (string-match " *<\\(.*\\)> *" id)
+ (setq id (match-string 1 id)))
(push (cons id result) mm-content-id-alist))
result))))
@@ -1677,43 +1709,40 @@ If RECURSIVE, search recursively."
(cond
((or (equal type "application/x-pkcs7-mime")
(equal type "application/pkcs7-mime"))
- (with-temp-buffer
- (when (and (cond
- ((equal smime-type "signed-data") t)
- ((eq mm-decrypt-option 'never) nil)
- ((eq mm-decrypt-option 'always) t)
- ((eq mm-decrypt-option 'known) t)
- (t (y-or-n-p "Decrypt (S/MIME) part? ")))
- (mm-view-pkcs7 parts from))
- (goto-char (point-min))
- ;; The encrypted document is a MIME part, and may use either
- ;; CRLF (Outlook and the like) or newlines for end-of-line
- ;; markers. Translate from CRLF.
- (while (search-forward "\r\n" nil t)
- (replace-match "\n"))
- ;; Normally there will be a Content-type header here, but
- ;; some mailers don't add that to the encrypted part, which
- ;; makes the subsequent re-dissection fail here.
- (save-restriction
- (mail-narrow-to-head)
- (unless (mail-fetch-field "content-type")
- (goto-char (point-max))
- (insert "Content-type: text/plain\n\n")))
- (setq parts
- (if (equal smime-type "signed-data")
- (list (propertize
- "multipart/signed"
- 'protocol "application/pkcs7-signature"
- 'gnus-info
- (format
- "%s:%s"
- (get-text-property 0 'gnus-info
- (car mm-security-handle))
- (get-text-property 0 'gnus-details
- (car mm-security-handle))))
- (mm-dissect-buffer t)
- parts)
- (mm-dissect-buffer t))))))
+ (add-text-properties 0 (length (car ctl))
+ (list 'buffer (car parts))
+ (car ctl))
+ (let* ((envelope-p (string= smime-type "enveloped-data"))
+ (decrypt-or-verify-option (if envelope-p
+ mm-decrypt-option
+ mm-verify-option))
+ (question (if envelope-p
+ "Decrypt (S/MIME) part? "
+ "Verify signed (S/MIME) part? ")))
+ (with-temp-buffer
+ (when (and (cond
+ ((equal smime-type "signed-data") t)
+ ((eq decrypt-or-verify-option 'never) nil)
+ ((eq decrypt-or-verify-option 'always) t)
+ ((eq decrypt-or-verify-option 'known) t)
+ (t (y-or-n-p (format question))))
+ (mm-view-pkcs7 parts from))
+
+ (goto-char (point-min))
+ ;; The encrypted document is a MIME part, and may use either
+ ;; CRLF (Outlook and the like) or newlines for end-of-line
+ ;; markers. Translate from CRLF.
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n"))
+ ;; Normally there will be a Content-type header here, but
+ ;; some mailers don't add that to the encrypted part, which
+ ;; makes the subsequent re-dissection fail here.
+ (save-restriction
+ (mail-narrow-to-head)
+ (unless (mail-fetch-field "content-type")
+ (goto-char (point-max))
+ (insert "Content-type: text/plain\n\n")))
+ (setq parts (mm-dissect-buffer t))))))
((equal subtype "signed")
(unless (and (setq protocol
(mm-handle-multipart-ctl-parameter ctl 'protocol))
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index d2a6d2cf5d3..319bc745ff8 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -634,12 +634,9 @@ If MODE is not set, try to find mode automatically."
(context (epg-make-context 'CMS)))
(prog1
(epg-verify-string context part)
- (let ((result (car (epg-context-result-for context 'verify))))
+ (let ((result (epg-context-result-for context 'verify)))
(mm-sec-status
- 'gnus-info (epg-signature-status result)
- 'gnus-details
- (format "%s:%s" (epg-signature-validity result)
- (epg-signature-key-id result))))))))
+ 'gnus-info (epg-verify-result-to-string result)))))))
(with-temp-buffer
(insert "MIME-Version: 1.0\n")
(mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m")
@@ -659,7 +656,11 @@ If MODE is not set, try to find mode automatically."
;; Use EPG/gpgsm
(let ((part (base64-decode-string (buffer-string))))
(erase-buffer)
- (insert (epg-decrypt-string (epg-make-context 'CMS) part)))
+ (insert
+ (let ((context (epg-make-context 'CMS)))
+ (prog1
+ (epg-decrypt-string context part)
+ (mm-sec-status 'gnus-info "OK")))))
;; Use openssl
(insert "MIME-Version: 1.0\n")
(mm-insert-headers "application/pkcs7-mime" "base64" "smime.p7m")