2010-10-04 01:16:00 +00:00
|
|
|
;;; gnutls.el --- Support SSL/TLS connections through GnuTLS
|
2010-11-01 05:53:15 +00:00
|
|
|
|
2011-01-25 04:08:28 +00:00
|
|
|
;; Copyright (C) 2010-2011 Free Software Foundation, Inc.
|
2010-09-26 06:06:28 +00:00
|
|
|
|
|
|
|
;; Author: Ted Zlatanov <tzz@lifelogs.com>
|
|
|
|
;; Keywords: comm, tls, ssl, encryption
|
|
|
|
;; Originally-By: Simon Josefsson (See http://josefsson.org/emacs-security/)
|
2010-10-04 01:16:00 +00:00
|
|
|
;; Thanks-To: Lars Magne Ingebrigtsen <larsi@gnus.org>
|
2010-09-26 06:06:28 +00:00
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
|
|
;; GNU 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 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; GNU 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. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; This package provides language bindings for the GnuTLS library
|
2011-04-25 01:31:45 +00:00
|
|
|
;; using the corresponding core functions in gnutls.c. It should NOT
|
|
|
|
;; be used directly, only through open-protocol-stream.
|
2010-09-26 06:06:28 +00:00
|
|
|
|
|
|
|
;; Simple test:
|
|
|
|
;;
|
2010-10-04 01:16:00 +00:00
|
|
|
;; (open-gnutls-stream "tls" "tls-buffer" "yourserver.com" "https")
|
|
|
|
;; (open-gnutls-stream "tls" "tls-buffer" "imap.gmail.com" "imaps")
|
2010-09-26 06:06:28 +00:00
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
2011-05-04 01:44:58 +00:00
|
|
|
(eval-when-compile (require 'cl))
|
|
|
|
|
2010-09-27 16:44:31 +00:00
|
|
|
(defgroup gnutls nil
|
|
|
|
"Emacs interface to the GnuTLS library."
|
|
|
|
:prefix "gnutls-"
|
|
|
|
:group 'net-utils)
|
|
|
|
|
2011-07-15 17:21:57 +00:00
|
|
|
(defcustom gnutls-algorithm-priority nil
|
|
|
|
"If non-nil, this should be a TLS priority string.
|
|
|
|
For instance, if you want to skip the \"dhe-rsa\" algorithm,
|
|
|
|
set this variable to \"normal:-dhe-rsa\"."
|
|
|
|
:type '(choice (const nil)
|
|
|
|
string))
|
|
|
|
|
2011-07-15 17:41:24 +00:00
|
|
|
;;;###autoload
|
|
|
|
(defcustom gnutls-min-prime-bits nil
|
|
|
|
"The minimum number of bits to be used in Diffie-Hellman key exchange.
|
|
|
|
|
|
|
|
This sets the minimum accepted size of the key to be used in a
|
|
|
|
client-server handshake. If the server sends a prime with fewer than
|
|
|
|
the specified number of bits the handshake will fail.
|
|
|
|
|
|
|
|
A value of nil says to use the default gnutls value."
|
|
|
|
:type '(choice (const :tag "Use default value" nil)
|
|
|
|
(integer :tag "Number of bits" 512))
|
|
|
|
:group 'gnutls)
|
|
|
|
|
2010-10-04 01:16:00 +00:00
|
|
|
(defun open-gnutls-stream (name buffer host service)
|
|
|
|
"Open a SSL/TLS connection for a service to a host.
|
2010-09-26 06:06:28 +00:00
|
|
|
Returns a subprocess-object to represent the connection.
|
|
|
|
Input and output work as for subprocesses; `delete-process' closes it.
|
|
|
|
Args are NAME BUFFER HOST SERVICE.
|
|
|
|
NAME is name for process. It is modified if necessary to make it unique.
|
|
|
|
BUFFER is the buffer (or `buffer-name') to associate with the process.
|
|
|
|
Process output goes at end of that buffer, unless you specify
|
|
|
|
an output stream or filter function to handle the output.
|
|
|
|
BUFFER may be also nil, meaning that this process is not associated
|
|
|
|
with any buffer
|
|
|
|
Third arg is name of the host to connect to, or its IP address.
|
|
|
|
Fourth arg SERVICE is name of the service desired, or an integer
|
2010-10-04 01:16:00 +00:00
|
|
|
specifying a port number to connect to.
|
|
|
|
|
2011-04-25 01:31:45 +00:00
|
|
|
Usage example:
|
|
|
|
|
|
|
|
\(with-temp-buffer
|
|
|
|
\(open-gnutls-stream \"tls\"
|
|
|
|
\(current-buffer)
|
|
|
|
\"your server goes here\"
|
|
|
|
\"imaps\"))
|
|
|
|
|
2010-10-04 01:16:00 +00:00
|
|
|
This is a very simple wrapper around `gnutls-negotiate'. See its
|
|
|
|
documentation for the specific parameters you can use to open a
|
|
|
|
GnuTLS connection, including specifying the credential type,
|
|
|
|
trust and key files, and priority string."
|
2011-05-04 01:44:58 +00:00
|
|
|
(gnutls-negotiate :process (open-network-stream name buffer host service)
|
|
|
|
:type 'gnutls-x509pki
|
|
|
|
:hostname host))
|
2011-04-25 01:31:45 +00:00
|
|
|
|
|
|
|
(put 'gnutls-error
|
|
|
|
'error-conditions
|
|
|
|
'(error gnutls-error))
|
|
|
|
(put 'gnutls-error
|
|
|
|
'error-message "GnuTLS error")
|
2010-09-26 06:06:28 +00:00
|
|
|
|
2010-11-01 05:53:15 +00:00
|
|
|
(declare-function gnutls-boot "gnutls.c" (proc type proplist))
|
2011-04-25 13:47:23 +00:00
|
|
|
(declare-function gnutls-errorp "gnutls.c" (error))
|
2010-11-01 05:53:15 +00:00
|
|
|
|
2011-05-04 01:44:58 +00:00
|
|
|
(defun* gnutls-negotiate
|
|
|
|
(&rest spec
|
|
|
|
&key process type hostname priority-string
|
2011-07-15 17:41:24 +00:00
|
|
|
trustfiles crlfiles keylist min-prime-bits
|
|
|
|
verify-flags verify-error verify-hostname-error
|
2011-05-04 01:44:58 +00:00
|
|
|
&allow-other-keys)
|
2011-11-25 13:26:30 +00:00
|
|
|
"Negotiate a SSL/TLS connection. Returns proc. Signals gnutls-error.
|
2011-05-04 01:44:58 +00:00
|
|
|
|
|
|
|
Note arguments are passed CL style, :type TYPE instead of just TYPE.
|
|
|
|
|
2010-10-03 22:37:37 +00:00
|
|
|
TYPE is `gnutls-x509pki' (default) or `gnutls-anon'. Use nil for the default.
|
2011-05-04 01:44:58 +00:00
|
|
|
PROCESS is a process returned by `open-network-stream'.
|
2011-04-25 01:31:45 +00:00
|
|
|
HOSTNAME is the remote hostname. It must be a valid string.
|
2010-10-03 22:37:37 +00:00
|
|
|
PRIORITY-STRING is as per the GnuTLS docs, default is \"NORMAL\".
|
|
|
|
TRUSTFILES is a list of CA bundles.
|
2011-05-04 01:44:58 +00:00
|
|
|
CRLFILES is a list of CRL files.
|
|
|
|
KEYLIST is an alist of (client key file, client cert file) pairs.
|
2011-07-15 17:41:24 +00:00
|
|
|
MIN-PRIME-BITS is the minimum acceptable size of Diffie-Hellman keys
|
|
|
|
\(see `gnutls-min-prime-bits' for more information). Use nil for the
|
|
|
|
default.
|
2011-04-25 01:31:45 +00:00
|
|
|
|
|
|
|
When VERIFY-HOSTNAME-ERROR is not nil, an error will be raised
|
|
|
|
when the hostname does not match the presented certificate's host
|
|
|
|
name. The exact verification algorithm is a basic implementation
|
|
|
|
of the matching described in RFC2818 (HTTPS), which takes into
|
|
|
|
account wildcards, and the DNSName/IPAddress subject alternative
|
|
|
|
name PKIX extension. See GnuTLS' gnutls_x509_crt_check_hostname
|
|
|
|
for details. When VERIFY-HOSTNAME-ERROR is nil, only a warning
|
|
|
|
will be issued.
|
|
|
|
|
|
|
|
When VERIFY-ERROR is not nil, an error will be raised when the
|
|
|
|
peer certificate verification fails as per GnuTLS'
|
|
|
|
gnutls_certificate_verify_peers2. Otherwise, only warnings will
|
|
|
|
be shown about the verification failure.
|
|
|
|
|
|
|
|
VERIFY-FLAGS is a numeric OR of verification flags only for
|
|
|
|
`gnutls-x509pki' connections. See GnuTLS' x509.h for details;
|
|
|
|
here's a recent version of the list.
|
|
|
|
|
|
|
|
GNUTLS_VERIFY_DISABLE_CA_SIGN = 1,
|
|
|
|
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT = 2,
|
|
|
|
GNUTLS_VERIFY_DO_NOT_ALLOW_SAME = 4,
|
|
|
|
GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT = 8,
|
|
|
|
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 = 16,
|
|
|
|
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32,
|
|
|
|
GNUTLS_VERIFY_DISABLE_TIME_CHECKS = 64,
|
|
|
|
GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS = 128,
|
|
|
|
GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT = 256
|
|
|
|
|
|
|
|
It must be omitted, a number, or nil; if omitted or nil it
|
|
|
|
defaults to GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT."
|
2010-10-03 22:37:37 +00:00
|
|
|
(let* ((type (or type 'gnutls-x509pki))
|
2011-04-25 01:31:45 +00:00
|
|
|
(default-trustfile "/etc/ssl/certs/ca-certificates.crt")
|
2010-12-13 22:20:32 +00:00
|
|
|
(trustfiles (or trustfiles
|
2011-04-25 01:31:45 +00:00
|
|
|
(when (file-exists-p default-trustfile)
|
|
|
|
(list default-trustfile))))
|
2010-09-26 06:06:28 +00:00
|
|
|
(priority-string (or priority-string
|
|
|
|
(cond
|
2010-10-03 22:37:37 +00:00
|
|
|
((eq type 'gnutls-anon)
|
2010-09-26 06:06:28 +00:00
|
|
|
"NORMAL:+ANON-DH:!ARCFOUR-128")
|
2010-10-03 22:37:37 +00:00
|
|
|
((eq type 'gnutls-x509pki)
|
2011-07-15 17:25:02 +00:00
|
|
|
(if gnutls-algorithm-priority
|
|
|
|
(upcase gnutls-algorithm-priority)
|
|
|
|
"NORMAL")))))
|
2011-07-15 17:41:24 +00:00
|
|
|
(min-prime-bits (or min-prime-bits gnutls-min-prime-bits))
|
2010-10-03 22:37:37 +00:00
|
|
|
(params `(:priority ,priority-string
|
2011-04-25 01:31:45 +00:00
|
|
|
:hostname ,hostname
|
2010-10-03 22:37:37 +00:00
|
|
|
:loglevel ,gnutls-log-level
|
2011-07-15 17:41:24 +00:00
|
|
|
:min-prime-bits ,min-prime-bits
|
2010-10-03 22:37:37 +00:00
|
|
|
:trustfiles ,trustfiles
|
2011-05-04 01:44:58 +00:00
|
|
|
:crlfiles ,crlfiles
|
|
|
|
:keylist ,keylist
|
2011-04-25 01:31:45 +00:00
|
|
|
:verify-flags ,verify-flags
|
|
|
|
:verify-error ,verify-error
|
|
|
|
:verify-hostname-error ,verify-hostname-error
|
2010-10-03 22:37:37 +00:00
|
|
|
:callbacks nil))
|
2010-09-26 06:06:28 +00:00
|
|
|
ret)
|
|
|
|
|
|
|
|
(gnutls-message-maybe
|
2011-05-04 01:44:58 +00:00
|
|
|
(setq ret (gnutls-boot process type params))
|
2011-04-25 01:31:45 +00:00
|
|
|
"boot: %s" params)
|
|
|
|
|
|
|
|
(when (gnutls-errorp ret)
|
|
|
|
;; This is a error from the underlying C code.
|
2011-05-04 01:44:58 +00:00
|
|
|
(signal 'gnutls-error (list process ret)))
|
2010-09-26 06:06:28 +00:00
|
|
|
|
2011-05-04 01:44:58 +00:00
|
|
|
process))
|
2010-09-26 06:06:28 +00:00
|
|
|
|
2010-11-01 05:53:15 +00:00
|
|
|
(declare-function gnutls-error-string "gnutls.c" (error))
|
|
|
|
|
2010-09-26 06:06:28 +00:00
|
|
|
(defun gnutls-message-maybe (doit format &rest params)
|
|
|
|
"When DOIT, message with the caller name followed by FORMAT on PARAMS."
|
|
|
|
;; (apply 'debug format (or params '(nil)))
|
|
|
|
(when (gnutls-errorp doit)
|
|
|
|
(message "%s: (err=[%s] %s) %s"
|
|
|
|
"gnutls.el"
|
|
|
|
doit (gnutls-error-string doit)
|
|
|
|
(apply 'format format (or params '(nil))))))
|
|
|
|
|
|
|
|
(provide 'gnutls)
|
|
|
|
|
|
|
|
;;; gnutls.el ends here
|