Skip to content

Latest commit

 

History

History
163 lines (130 loc) · 7.81 KB

notmuch-openssl.org

File metadata and controls

163 lines (130 loc) · 7.81 KB

Copyrights

;; Copyright (C) 2014 Baptiste Fouques
;;
;; Author: Baptiste Fouques
;; Created: February 2014
;; Version: 1.0
;; Keywords: notmuch openssl smime encryption signature
;;
;; Notmuch-Openssl  for Emacs is free software; you  can redistribute  it and/or
;; modify it under the  terms of the GNU General Public  License as published by
;; the Free Software Foundation; either version 3, or (at your option) any later
;; version.
;;
;; Notmuch-Openssl for Emacs is distributed in the hope that it  will be useful,
;; but   WITHOUT  ANY   WARRANTY;   without  even   the   implied  warranty   of
;; MERCHANTABILITY or  FITNESS FOR  A PARTICULAR PURPOSE.   See the  GNU General
;; Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;; Options
;;   customization is found in the groupe 'notmuch-openssl'
;;   M-x customize-group notmuch-openssl

Provides

This package provides operations :

openssl-create-sigstatus
From a notmuch sexp representation of a message and a part, create relevant :sigstatus if message has been signed through x509 mechanism. Typically to be launch at construction of notmuch-show buffer.

It adds openssl-create-sigstatus as before advice to notmuch-show-insert-part-multipart/signed.

Dependencies

No Elisp dependency. Though there is no use whithout using notmuch as mail client.

It suppose that you have a working openssl environment. Openssl executable may be specified in custom group.

Constants and customization

Customization

(defgroup notmuch-openssl nil "Openssl binding for Notmuch")

(defcustom notmuch-openssl/openssl-command "openssl"
  "Command to call openssl base executable. Could be short if in $PATH, or full path."
  :group 'notmuch-openssl
  :type 'string)

(defcustom notmuch-openssl/save-received-cert "~/Mail/certs"
  "If non nil, save received S/Mime certificate (in valid signed messages for example) in given path"
  :group 'notmuch-openssl
  :type  '(restricted-sexp :match-alternatives (stringp 'nil)))

Verify X.509 S/Mime signature

(defun notmuch-openssl/create-sigstatus-from-openssl (msg part content-type nth depth button)
  "If message is signed and sigstatus is nil, try to create sigstatus with openssl"
  (let ((tag-signed (member "signed" (plist-get msg :tags)))
        (signed (plist-member part :sigstatus))
        (sigstatus (plist-get part :sigstatus)))
    (cond ((and tag-signed signed (or (not sigstatus) (equal sigstatus '((:status "error" :errors 2)))))
           
           (let* ((filename (plist-get msg :filename))
                  (openssl-usercert-file (make-temp-file "openssl-signer"))
                  (args (list "smime" "-verify" "-in" filename "-signer" openssl-usercert-file "-out" "/dev/null"))
                  (args-noverify (list "smime" "-verify" "-noverify" "-in" filename "-signer" openssl-usercert-file "-out" "/dev/null"))
                  (good "")
                  (self "")
                  (new_status '()))
             (with-temp-buffer
               (apply #'call-process notmuch-openssl/openssl-command nil '(t t) nil args)
               (delete-char -1)
               (setq good (string= (buffer-string) "Verification successful")))
             (with-temp-buffer
               (apply #'call-process notmuch-openssl/openssl-command nil '(t t) nil args-noverify)
               (delete-char -1)
               (setq self (string= (buffer-string) "Verification successful")))
             
             (cond 
              ((or good self)
               (setq new_status (plist-put new_status :status "good"))

               (let ((args-email (list "x509" "-email" "-noout" "-in" openssl-usercert-file))
                     (args-serial (list "x509" "-serial" "-noout" "-in" openssl-usercert-file ))
                     (email "")
                     (serial ""))
                 (with-temp-buffer
                   (notmuch-check-exit-status (apply #'call-process notmuch-openssl/openssl-command nil '(t t) nil args-email)
                                              (cons notmuch-openssl/openssl-command args)
                                              (buffer-string))
                   (delete-char -1)
                   (setq email (buffer-string)))
                 (with-temp-buffer
                   (notmuch-check-exit-status (apply #'call-process notmuch-openssl/openssl-command nil '(t t) nil args-serial)
                                              (cons notmuch-openssl/openssl-command args)
                                              (buffer-string))
                   (delete-char -1) (goto-char (point-min)) (delete-char 7)
                   (setq serial (buffer-string)))

                 (if notmuch-openssl/save-received-cert
                     (let ((save-cert-filename 
                            (concat (file-name-as-directory notmuch-openssl/save-received-cert) email "-" serial ".pem")))
                       (copy-file openssl-usercert-file save-cert-filename t)
                       (setq new_status (plist-put new_status :cert-file save-cert-filename))))
                 (if good
                     (setq new_status (plist-put new_status :userid (concat email " - " serial)))
                   (setq new_status (plist-put new_status :fingerprint (concat serial " self signed for " email))))))

              ((setq new_status (plist-put new_status :status "error"))))

             (setq part (plist-put part :sigstatus (list new_status)))
             (delete-file openssl-usercert-file)))
          (nil))))

Add sigstatus creation as advice to notmuch-show-insert-part-multipart/signed

(defadvice notmuch-show-insert-part-multipart/signed (before notmuch-openssl/advice-create-sigstatus-from-openssl
                                                             (msg part content-type nth depth button))
  (notmuch-openssl/create-sigstatus-from-openssl msg part content-type nth depth button))

(ad-activate 'notmuch-show-insert-part-multipart/signed nil)

Show signature information

(defun notmuch-openssl/sigstatus-good-callback (button)
  (let* ((sigstatus (button-get button :notmuch-sigstatus))
         (cert-file (expand-file-name (plist-get sigstatus :cert-file)))
         (buffer (get-buffer-create "*notmuch-crypto-gpg-out*")))
    (with-current-buffer buffer
      (goto-char (point-max))
      (if cert-file
          (call-process notmuch-openssl/openssl-command nil '(t t) t "x509" "-in" cert-file "-text")))))

Add certificate information display is advice to notmuch-crypto-sigstatus-good-callback

(defadvice notmuch-crypto-sigstatus-good-callback (after notmuch-openssl/advice-sigstatus-good-callback (button))
  (notmuch-openssl/sigstatus-good-callback button))

(ad-activate 'notmuch-crypto-sigstatus-good-callback  nil)

Provide

(provide 'notmuch-openssl)