;; This library perform S/MIME operations from within Emacs.
;;
;; Functions for fetching certificates from public repositories are
-;; NOT provided (yet).
+;; provided, currently only from DNS. LDAP support (via EUDC) is planned.
;;
-;; It uses OpenSSL (tested with version 0.9.5a) for signing,
+;; It uses OpenSSL (tested with version 0.9.5a and 0.9.6) for signing,
;; encryption and decryption.
;;
;; Some general knowledge of S/MIME, X.509, PKCS#12, PEM etc is
;;; Code:
+(require 'dig)
+(eval-when-compile (require 'cl))
+
(defgroup smime nil
"S/MIME configuration.")
:type 'directory
:group 'smime)
-(defcustom smime-openssl-program "openssl"
+(defcustom smime-openssl-program
+ (and (condition-case ()
+ (eq 0 (call-process "openssl" nil nil nil "version"))
+ (error nil))
+ "openssl")
"Name of OpenSSL binary."
:type 'string
:group 'smime)
+(defcustom smime-dns-server nil
+ "DNS server to query certificates from.
+If nil, use system defaults."
+ :type '(choice (const :tag "System defaults")
+ string)
+ :group 'dig)
+
+(defvar smime-details-buffer "*S/MIME OpenSSL output*")
+
;; OpenSSL wrappers.
(defun smime-call-openssl-region (b e buf &rest args)
(when (looking-at "^MIME-Version: 1.0$")
(delete-region (point) (progn (forward-line 1) (point))))
t)
+ (with-current-buffer (get-buffer-create smime-details-buffer)
+ (goto-char (point-max))
+ (insert-buffer buffer))
(kill-buffer buffer))))
(defun smime-encrypt-region (b e certfiles)
(when (looking-at "^MIME-Version: 1.0$")
(delete-region (point) (progn (forward-line 1) (point))))
t)
+ (with-current-buffer (get-buffer-create smime-details-buffer)
+ (goto-char (point-max))
+ (insert-buffer buffer))
(kill-buffer buffer))))
;; Sign+encrypt buffer
(message "S/MIME message verified succesfully.")
(message "S/MIME message NOT verified successfully.")
nil)
+ (with-current-buffer (get-buffer-create smime-details-buffer)
+ (goto-char (point-max))
+ (insert-buffer buffer))
(kill-buffer buffer))))
(defun smime-decrypt-region (b e keyfile)
"-recip" keyfile)
)
+ (with-current-buffer (get-buffer-create smime-details-buffer)
+ (goto-char (point-max))
+ (insert-buffer buffer))
(kill-buffer buffer)))
;; Verify+Decrypt buffer
(and (listp (car-safe smime-keys))
(caar smime-keys))))))))
+;; Find certificates
+
+(defun smime-mail-to-domain (mailaddr)
+ (if (string-match "@" mailaddr)
+ (replace-match "." 'fixedcase 'literal mailaddr)
+ mailaddr))
+
+(defun smime-cert-by-dns (mail)
+ (let* ((dig-dns-server smime-dns-server)
+ (digbuf (dig-invoke (smime-mail-to-domain mail) "cert" nil nil "+vc"))
+ (retbuf (generate-new-buffer (format "*certificate for %s*" mail)))
+ (certrr (with-current-buffer digbuf
+ (dig-extract-rr (smime-mail-to-domain mail) "cert")))
+ (cert (and certrr (dig-rr-get-pkix-cert certrr))))
+ (if cert
+ (with-current-buffer retbuf
+ (insert "-----BEGIN CERTIFICATE-----\n")
+ (let ((i 0) (len (length cert)))
+ (while (> (- len 64) i)
+ (insert (substring cert i (+ i 64)) "\n")
+ (setq i (+ i 64)))
+ (insert (substring cert i len) "\n"))
+ (insert "-----END CERTIFICATE-----\n"))
+ (kill-buffer retbuf)
+ (setq retbuf nil))
+ (kill-buffer digbuf)
+ retbuf))
+
;; User interface.
(defvar smime-buffer "*SMIME*")