diff options
| -rw-r--r-- | lisp/net/tls.el | 110 |
1 files changed, 81 insertions, 29 deletions
diff --git a/lisp/net/tls.el b/lisp/net/tls.el index 2e890a4a476..789e4bbc34e 100644 --- a/lisp/net/tls.el +++ b/lisp/net/tls.el | |||
| @@ -51,10 +51,45 @@ | |||
| 51 | (autoload 'format-spec "format-spec") | 51 | (autoload 'format-spec "format-spec") |
| 52 | (autoload 'format-spec-make "format-spec")) | 52 | (autoload 'format-spec-make "format-spec")) |
| 53 | 53 | ||
| 54 | (eval-when-compile | ||
| 55 | (require 'rx)) | ||
| 56 | |||
| 54 | (defgroup tls nil | 57 | (defgroup tls nil |
| 55 | "Transport Layer Security (TLS) parameters." | 58 | "Transport Layer Security (TLS) parameters." |
| 56 | :group 'comm) | 59 | :group 'comm) |
| 57 | 60 | ||
| 61 | (defcustom tls-end-of-info | ||
| 62 | (rx | ||
| 63 | (or | ||
| 64 | ;; `openssl s_client` regexp | ||
| 65 | (sequence | ||
| 66 | ;; see ssl/ssl_txt.c lines 219--220 | ||
| 67 | line-start | ||
| 68 | " Verify return code: " | ||
| 69 | (one-or-more not-newline) | ||
| 70 | "\n" | ||
| 71 | ;; according to apps/s_client.c line 1515 this is always the last | ||
| 72 | ;; line that is printed by s_client before the real data | ||
| 73 | "---\n") | ||
| 74 | ;; `gnutls` regexp | ||
| 75 | (sequence | ||
| 76 | ;; see src/cli.c lines 721-- | ||
| 77 | (sequence line-start "- Simple Client Mode:\n") | ||
| 78 | (zero-or-more | ||
| 79 | (or | ||
| 80 | "\n" ; ignore blank lines | ||
| 81 | ;; XXX: we have no way of knowing if the STARTTLS handshake | ||
| 82 | ;; sequence has completed successfully, because `gnutls` will | ||
| 83 | ;; only report failure. | ||
| 84 | (sequence line-start "\*\*\* Starting TLS handshake\n")))))) | ||
| 85 | "Regexp matching end of TLS client informational messages. | ||
| 86 | Client data stream begins after the last character matched by | ||
| 87 | this. The default matches `openssl s_client' (version 0.9.8c) | ||
| 88 | and `gnutls-cli' (version 2.0.1) output." | ||
| 89 | :version "22.2" | ||
| 90 | :type 'regexp | ||
| 91 | :group 'tls) | ||
| 92 | |||
| 58 | (defcustom tls-program '("gnutls-cli -p %p %h" | 93 | (defcustom tls-program '("gnutls-cli -p %p %h" |
| 59 | "gnutls-cli -p %p %h --protocols ssl3" | 94 | "gnutls-cli -p %p %h --protocols ssl3" |
| 60 | "openssl s_client -connect %h:%p -no_ssl2") | 95 | "openssl s_client -connect %h:%p -no_ssl2") |
| @@ -130,35 +165,52 @@ Fourth arg PORT is an integer specifying a port to connect to." | |||
| 130 | process cmd done) | 165 | process cmd done) |
| 131 | (if use-temp-buffer | 166 | (if use-temp-buffer |
| 132 | (setq buffer (generate-new-buffer " TLS"))) | 167 | (setq buffer (generate-new-buffer " TLS"))) |
| 133 | (message "Opening TLS connection to `%s'..." host) | 168 | (save-excursion |
| 134 | (while (and (not done) (setq cmd (pop cmds))) | 169 | (set-buffer buffer) |
| 135 | (message "Opening TLS connection with `%s'..." cmd) | 170 | (message "Opening TLS connection to `%s'..." host) |
| 136 | (let ((process-connection-type tls-process-connection-type) | 171 | (while (and (not done) (setq cmd (pop cmds))) |
| 137 | response) | 172 | (message "Opening TLS connection with `%s'..." cmd) |
| 138 | (setq process (start-process | 173 | (let ((process-connection-type tls-process-connection-type) |
| 139 | name buffer shell-file-name shell-command-switch | 174 | response) |
| 140 | (format-spec | 175 | (setq process (start-process |
| 141 | cmd | 176 | name buffer shell-file-name shell-command-switch |
| 142 | (format-spec-make | 177 | (format-spec |
| 143 | ?h host | 178 | cmd |
| 144 | ?p (if (integerp port) | 179 | (format-spec-make |
| 145 | (int-to-string port) | 180 | ?h host |
| 146 | port))))) | 181 | ?p (if (integerp port) |
| 147 | (while (and process | 182 | (int-to-string port) |
| 148 | (memq (process-status process) '(open run)) | 183 | port))))) |
| 149 | (save-excursion | 184 | (while (and process |
| 150 | (set-buffer buffer) ;; XXX "blue moon" nntp.el bug | 185 | (memq (process-status process) '(open run)) |
| 151 | (goto-char (point-min)) | 186 | (progn |
| 152 | (not (setq done (re-search-forward tls-success nil t))))) | 187 | (goto-char (point-min)) |
| 153 | (unless (accept-process-output process 1) | 188 | (not (setq done (re-search-forward tls-success nil t))))) |
| 154 | (sit-for 1))) | 189 | (unless (accept-process-output process 1) |
| 155 | (message "Opening TLS connection with `%s'...%s" cmd | 190 | (sit-for 1))) |
| 156 | (if done "done" "failed")) | 191 | (message "Opening TLS connection with `%s'...%s" cmd |
| 157 | (if done | 192 | (if done "done" "failed")) |
| 158 | (setq done process) | 193 | (if (not done) |
| 159 | (delete-process process)))) | 194 | (delete-process process) |
| 160 | (message "Opening TLS connection to `%s'...%s" | 195 | ;; advance point to after all informational messages that |
| 161 | host (if done "done" "failed")) | 196 | ;; `openssl s_client' and `gnutls' print |
| 197 | (let ((start-of-data nil)) | ||
| 198 | (while | ||
| 199 | (not (setq start-of-data | ||
| 200 | ;; the string matching `tls-end-of-info' | ||
| 201 | ;; might come in separate chunks from | ||
| 202 | ;; `accept-process-output', so start the | ||
| 203 | ;; search where `tls-success' ended | ||
| 204 | (save-excursion | ||
| 205 | (if (re-search-forward tls-end-of-info nil t) | ||
| 206 | (match-end 0))))) | ||
| 207 | (accept-process-output process 1)) | ||
| 208 | (if start-of-data | ||
| 209 | ;; move point to start of client data | ||
| 210 | (goto-char start-of-data))) | ||
| 211 | (setq done process)))) | ||
| 212 | (message "Opening TLS connection to `%s'...%s" | ||
| 213 | host (if done "done" "failed"))) | ||
| 162 | (when use-temp-buffer | 214 | (when use-temp-buffer |
| 163 | (if done (set-process-buffer process nil)) | 215 | (if done (set-process-buffer process nil)) |
| 164 | (kill-buffer buffer)) | 216 | (kill-buffer buffer)) |