aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Fang2016-04-04 22:21:21 +0200
committerLars Magne Ingebrigtsen2016-04-04 22:21:34 +0200
commit3c623c26ae7d695746e05d8a2e16a67a6256b024 (patch)
tree1839346cd9cdc14cd3436048a298d12d9f65c9ed
parent17cb263adb7c37803140604f0a2e4df8a38fbcff (diff)
downloademacs-3c623c26ae7d695746e05d8a2e16a67a6256b024.tar.gz
emacs-3c623c26ae7d695746e05d8a2e16a67a6256b024.zip
Allow URL using HTTPS proxies using CONNECT
* lisp/url/url-http.el (url-http-find-free-connection): Allow using proxies (bug#11788). (url-http-end-of-document-sentinel): Ditto. (url-http): The protocol may change from http to https and vice versa. (url-https-proxy-connect): Allow using CONNECT proxies for https.
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/url/url-http.el110
2 files changed, 97 insertions, 15 deletions
diff --git a/etc/NEWS b/etc/NEWS
index e6b18bff2ec..6cc1c5ae01c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1225,6 +1225,8 @@ plist will contain a :peer element that has the output of
1225programmatically delete all cookies, or cookies from a specific 1225programmatically delete all cookies, or cookies from a specific
1226domain. 1226domain.
1227 1227
1228*** The URL package now support https over proxies supporting CONNECT.
1229
1228** Tramp 1230** Tramp
1229 1231
1230+++ 1232+++
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index 33f6d11eef3..1fe9ac25555 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -27,6 +27,7 @@
27 27
28(require 'cl-lib) 28(require 'cl-lib)
29(require 'puny) 29(require 'puny)
30(require 'nsm)
30(eval-when-compile 31(eval-when-compile
31 (require 'subr-x)) 32 (require 'subr-x))
32 33
@@ -136,6 +137,8 @@ request.")
136 (507 insufficient-storage "Insufficient storage")) 137 (507 insufficient-storage "Insufficient storage"))
137 "The HTTP return codes and their text.") 138 "The HTTP return codes and their text.")
138 139
140(defconst url-https-default-port 443 "Default HTTPS port.")
141
139;(eval-when-compile 142;(eval-when-compile
140;; These are all macros so that they are hidden from external sight 143;; These are all macros so that they are hidden from external sight
141;; when the file is byte-compiled. 144;; when the file is byte-compiled.
@@ -197,7 +200,14 @@ request.")
197 ;; `url-open-stream' needs a buffer in which to do things 200 ;; `url-open-stream' needs a buffer in which to do things
198 ;; like authentication. But we use another buffer afterwards. 201 ;; like authentication. But we use another buffer afterwards.
199 (unwind-protect 202 (unwind-protect
200 (let ((proc (url-open-stream host buf host port gateway-method))) 203 (let ((proc (url-open-stream host buf
204 (if url-using-proxy
205 (url-host url-using-proxy)
206 host)
207 (if url-using-proxy
208 (url-port url-using-proxy)
209 port)
210 gateway-method)))
201 ;; url-open-stream might return nil. 211 ;; url-open-stream might return nil.
202 (when (processp proc) 212 (when (processp proc)
203 ;; Drop the temp buffer link before killing the buffer. 213 ;; Drop the temp buffer link before killing the buffer.
@@ -477,6 +487,7 @@ work correctly."
477 ) 487 )
478 488
479(declare-function gnutls-peer-status "gnutls.c" (proc)) 489(declare-function gnutls-peer-status "gnutls.c" (proc))
490(declare-function gnutls-negotiate "gnutls.el")
480 491
481(defun url-http-parse-headers () 492(defun url-http-parse-headers ()
482 "Parse and handle HTTP specific headers. 493 "Parse and handle HTTP specific headers.
@@ -925,7 +936,13 @@ should be shown to the user."
925 (erase-buffer) 936 (erase-buffer)
926 (let ((url-request-method url-http-method) 937 (let ((url-request-method url-http-method)
927 (url-request-extra-headers url-http-extra-headers) 938 (url-request-extra-headers url-http-extra-headers)
928 (url-request-data url-http-data)) 939 (url-request-data url-http-data)
940 (url-using-proxy (url-find-proxy-for-url
941 url-current-object
942 (url-host url-current-object))))
943 (when url-using-proxy
944 (setq url-using-proxy
945 (url-generic-parse-url url-using-proxy)))
929 (url-http url-current-object url-callback-function 946 (url-http url-current-object url-callback-function
930 url-callback-arguments (current-buffer))))) 947 url-callback-arguments (current-buffer)))))
931 ((url-http-parse-headers) 948 ((url-http-parse-headers)
@@ -1209,17 +1226,20 @@ The return value of this function is the retrieval buffer."
1209 (nsm-noninteractive (or url-request-noninteractive 1226 (nsm-noninteractive (or url-request-noninteractive
1210 (and (boundp 'url-http-noninteractive) 1227 (and (boundp 'url-http-noninteractive)
1211 url-http-noninteractive))) 1228 url-http-noninteractive)))
1212 (connection (url-http-find-free-connection host port gateway-method)) 1229 (connection (url-http-find-free-connection (url-host url)
1230 (url-port url)
1231 gateway-method))
1213 (mime-accept-string url-mime-accept-string) 1232 (mime-accept-string url-mime-accept-string)
1214 (buffer (or retry-buffer 1233 (buffer (or retry-buffer
1215 (generate-new-buffer 1234 (generate-new-buffer
1216 (format " *http %s:%d*" host port))))) 1235 (format " *http %s:%d*" (url-host url) (url-port url))))))
1217 (if (not connection) 1236 (if (not connection)
1218 ;; Failed to open the connection for some reason 1237 ;; Failed to open the connection for some reason
1219 (progn 1238 (progn
1220 (kill-buffer buffer) 1239 (kill-buffer buffer)
1221 (setq buffer nil) 1240 (setq buffer nil)
1222 (error "Could not create connection to %s:%d" host port)) 1241 (error "Could not create connection to %s:%d" (url-host url)
1242 (url-port url)))
1223 (with-current-buffer buffer 1243 (with-current-buffer buffer
1224 (mm-disable-multibyte) 1244 (mm-disable-multibyte)
1225 (setq url-current-object url 1245 (setq url-current-object url
@@ -1275,13 +1295,72 @@ The return value of this function is the retrieval buffer."
1275 (set-process-sentinel connection 'url-http-async-sentinel)) 1295 (set-process-sentinel connection 'url-http-async-sentinel))
1276 (`failed 1296 (`failed
1277 ;; Asynchronous connection failed 1297 ;; Asynchronous connection failed
1278 (error "Could not create connection to %s:%d" host port)) 1298 (error "Could not create connection to %s:%d" (url-host url)
1299 (url-port url)))
1279 (_ 1300 (_
1280 (set-process-sentinel connection 1301 (if (and url-http-proxy (string= "https"
1281 'url-http-end-of-document-sentinel) 1302 (url-type url-current-object)))
1282 (process-send-string connection (url-http-create-request)))))) 1303 (url-https-proxy-connect connection)
1304 (set-process-sentinel connection
1305 'url-http-end-of-document-sentinel)
1306 (process-send-string connection (url-http-create-request)))))))
1283 buffer)) 1307 buffer))
1284 1308
1309(defun url-https-proxy-connect (connection)
1310 (setq url-http-after-change-function 'url-https-proxy-after-change-function)
1311 (process-send-string connection (format (concat "CONNECT %s:%d HTTP/1.1\r\n"
1312 "Host: %s\r\n"
1313 "\r\n")
1314 (url-host url-current-object)
1315 (or (url-port url-current-object)
1316 url-https-default-port)
1317 (url-host url-current-object))))
1318
1319(defun url-https-proxy-after-change-function (st nd length)
1320 (let* ((process-buffer (current-buffer))
1321 (proc (get-buffer-process process-buffer)))
1322 (goto-char (point-min))
1323 (when (re-search-forward "^\r?\n" nil t)
1324 (backward-char 1)
1325 ;; Saw the end of the headers
1326 (setq url-http-end-of-headers (set-marker (make-marker) (point)))
1327 (url-http-parse-response)
1328 (cond
1329 ((null url-http-response-status)
1330 ;; We got back a headerless malformed response from the
1331 ;; server.
1332 (url-http-activate-callback)
1333 (error "Malformed response from proxy, fail!"))
1334 ((= url-http-response-status 200)
1335 (if (gnutls-available-p)
1336 (condition-case e
1337 (let ((tls-connection (gnutls-negotiate
1338 :process proc
1339 :hostname (url-host url-current-object)
1340 :verify-error nil)))
1341 ;; check certificate validity
1342 (setq tls-connection
1343 (nsm-verify-connection tls-connection
1344 (url-host url-current-object)
1345 (url-port url-current-object)))
1346 (with-current-buffer process-buffer (erase-buffer))
1347 (set-process-buffer tls-connection process-buffer)
1348 (setq url-http-after-change-function
1349 'url-http-wait-for-headers-change-function)
1350 (set-process-filter tls-connection 'url-http-generic-filter)
1351 (process-send-string tls-connection
1352 (url-http-create-request)))
1353 (gnutls-error
1354 (url-http-activate-callback)
1355 (error "gnutls-error: %s" e))
1356 (error
1357 (url-http-activate-callback)
1358 (error "error: %s" e)))
1359 (error "error: gnutls support needed!")))
1360 (t
1361 (url-http-activate-callback)
1362 (message "error response: %d" url-http-response-status))))))
1363
1285(defun url-http-async-sentinel (proc why) 1364(defun url-http-async-sentinel (proc why)
1286 ;; We are performing an asynchronous connection, and a status change 1365 ;; We are performing an asynchronous connection, and a status change
1287 ;; has occurred. 1366 ;; has occurred.
@@ -1293,11 +1372,13 @@ The return value of this function is the retrieval buffer."
1293 (url-http-end-of-document-sentinel proc why)) 1372 (url-http-end-of-document-sentinel proc why))
1294 ((string= (substring why 0 4) "open") 1373 ((string= (substring why 0 4) "open")
1295 (setq url-http-connection-opened t) 1374 (setq url-http-connection-opened t)
1296 (condition-case error 1375 (if (and url-http-proxy (string= "https" (url-type url-current-object)))
1297 (process-send-string proc (url-http-create-request)) 1376 (url-https-proxy-connect proc)
1298 (file-error 1377 (condition-case error
1299 (setq url-http-connection-opened nil) 1378 (process-send-string proc (url-http-create-request))
1300 (message "HTTP error: %s" error)))) 1379 (file-error
1380 (setq url-http-connection-opened nil)
1381 (message "HTTP error: %s" error)))))
1301 (t 1382 (t
1302 (setf (car url-callback-arguments) 1383 (setf (car url-callback-arguments)
1303 (nconc (list :error (list 'error 'connection-failed why 1384 (nconc (list :error (list 'error 'connection-failed why
@@ -1458,7 +1539,6 @@ p3p
1458;; with url-http.el on systems with 8-character file names. 1539;; with url-http.el on systems with 8-character file names.
1459(require 'tls) 1540(require 'tls)
1460 1541
1461(defconst url-https-default-port 443 "Default HTTPS port.")
1462(defconst url-https-asynchronous-p t "HTTPS retrievals are asynchronous.") 1542(defconst url-https-asynchronous-p t "HTTPS retrievals are asynchronous.")
1463 1543
1464;; FIXME what is the point of this alias being an autoload? 1544;; FIXME what is the point of this alias being an autoload?