diff options
| author | Lars Magne Ingebrigtsen | 2011-06-21 22:39:08 +0200 |
|---|---|---|
| committer | Lars Magne Ingebrigtsen | 2011-06-21 22:39:08 +0200 |
| commit | 4ea31e074dc3505bcddc5be99a67cd3eab8cf389 (patch) | |
| tree | 062a9c811663a114469208f3c9849bfb09bd8fe0 /lisp/net | |
| parent | 065ec2c78bedd587cbaccf5491f262b0b3fa6da0 (diff) | |
| download | emacs-4ea31e074dc3505bcddc5be99a67cd3eab8cf389.tar.gz emacs-4ea31e074dc3505bcddc5be99a67cd3eab8cf389.zip | |
Add support for client certificates for built-in and external STARTTLS.
Diffstat (limited to 'lisp/net')
| -rw-r--r-- | lisp/net/network-stream.el | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el index b17b9ae805c..9c4ca80104d 100644 --- a/lisp/net/network-stream.el +++ b/lisp/net/network-stream.el | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | (require 'tls) | 45 | (require 'tls) |
| 46 | (require 'starttls) | 46 | (require 'starttls) |
| 47 | (require 'auth-source) | ||
| 47 | 48 | ||
| 48 | (declare-function gnutls-negotiate "gnutls" t t) ; defun* | 49 | (declare-function gnutls-negotiate "gnutls" t t) ; defun* |
| 49 | 50 | ||
| @@ -110,10 +111,17 @@ values: | |||
| 110 | STARTTLS if the server supports STARTTLS, and nil otherwise. | 111 | STARTTLS if the server supports STARTTLS, and nil otherwise. |
| 111 | 112 | ||
| 112 | :always-query-capabilies says whether to query the server for | 113 | :always-query-capabilies says whether to query the server for |
| 113 | capabilities, even if we're doing a `plain' network connection. | 114 | capabilities, even if we're doing a `plain' network connection. |
| 115 | |||
| 116 | :client-certificate should either be a list where the first | ||
| 117 | element is the certificate key file name, and the second | ||
| 118 | element is the certificate file name itself, or `t', which | ||
| 119 | means that `auth-source' will be queried for the key and the | ||
| 120 | certificate. This parameter will only be used when doing TLS | ||
| 121 | or STARTTLS connections. | ||
| 114 | 122 | ||
| 115 | :nowait is a boolean that says the connection should be made | 123 | :nowait is a boolean that says the connection should be made |
| 116 | asynchronously, if possible." | 124 | asynchronously, if possible." |
| 117 | (unless (featurep 'make-network-process) | 125 | (unless (featurep 'make-network-process) |
| 118 | (error "Emacs was compiled without networking support")) | 126 | (error "Emacs was compiled without networking support")) |
| 119 | (let ((type (plist-get parameters :type)) | 127 | (let ((type (plist-get parameters :type)) |
| @@ -152,6 +160,22 @@ asynchronously, if possible." | |||
| 152 | :type (nth 3 result)) | 160 | :type (nth 3 result)) |
| 153 | (car result)))))) | 161 | (car result)))))) |
| 154 | 162 | ||
| 163 | (defun network-stream-certificate (host service parameters) | ||
| 164 | (let ((spec (plist-get :client-certificate parameters))) | ||
| 165 | (cond | ||
| 166 | ((listp spec) | ||
| 167 | ;; Either nil or a list with a key/certificate pair. | ||
| 168 | spec) | ||
| 169 | ((eq spec t) | ||
| 170 | (let* ((auth-info | ||
| 171 | (car (auth-source-search :max 1 | ||
| 172 | :host host | ||
| 173 | :port service))) | ||
| 174 | (key (plist-get auth-info :cert-key)) | ||
| 175 | (cert (plist-get auth-info :cert-cert))) | ||
| 176 | (and key cert | ||
| 177 | (list key cert))))))) | ||
| 178 | |||
| 155 | ;;;###autoload | 179 | ;;;###autoload |
| 156 | (defalias 'open-protocol-stream 'open-network-stream) | 180 | (defalias 'open-protocol-stream 'open-network-stream) |
| 157 | 181 | ||
| @@ -201,14 +225,24 @@ asynchronously, if possible." | |||
| 201 | starttls-extra-arguments | 225 | starttls-extra-arguments |
| 202 | ;; For opportunistic TLS upgrades, we don't really | 226 | ;; For opportunistic TLS upgrades, we don't really |
| 203 | ;; care about the identity of the peer. | 227 | ;; care about the identity of the peer. |
| 204 | (cons "--insecure" starttls-extra-arguments)))) | 228 | (cons "--insecure" starttls-extra-arguments))) |
| 229 | (cert (network-stream-certificate host service parameters))) | ||
| 230 | ;; There are client certificates requested, so add them to | ||
| 231 | ;; the command line. | ||
| 232 | (when cert | ||
| 233 | (setq starttls-extra-arguments | ||
| 234 | (nconc (list "--x509keyfile" (nth 0 cert) | ||
| 235 | "--x509certfile" (nth 1 cert)) | ||
| 236 | starttls-extra-arguments))) | ||
| 205 | (setq stream (starttls-open-stream name buffer host service))) | 237 | (setq stream (starttls-open-stream name buffer host service))) |
| 206 | (network-stream-get-response stream start eoc)) | 238 | (network-stream-get-response stream start eoc)) |
| 207 | (when (string-match success-string | 239 | (when (string-match success-string |
| 208 | (network-stream-command stream starttls-command eoc)) | 240 | (network-stream-command stream starttls-command eoc)) |
| 209 | ;; The server said it was OK to begin STARTTLS negotiations. | 241 | ;; The server said it was OK to begin STARTTLS negotiations. |
| 210 | (if (fboundp 'open-gnutls-stream) | 242 | (if (fboundp 'open-gnutls-stream) |
| 211 | (gnutls-negotiate :process stream :hostname host) | 243 | (let ((cert (network-stream-certificate host service parameters))) |
| 244 | (gnutls-negotiate :process stream :hostname host | ||
| 245 | :keylist (and cert (list cert)))) | ||
| 212 | (unless (starttls-negotiate stream) | 246 | (unless (starttls-negotiate stream) |
| 213 | (delete-process stream))) | 247 | (delete-process stream))) |
| 214 | (if (memq (process-status stream) '(open run)) | 248 | (if (memq (process-status stream) '(open run)) |