Hi,
I need to contact HTTPS servers through a proxy. I've managed to get this to work by having the http-request function issue an HTTP CONNECT commmand in order to tunnel SSL through the proxy: the patch is below (against 0.11.5). On the downside, it only works for Lispworks.
Cheers, Dave
--- a/request.lisp +++ b/request.lisp @@ -416,7 +416,8 @@ LispWorks 5.0 or higher." (t (setq content (alist-to-url-encoded-string parameters external-format-out) content-type "application/x-www-form-urlencoded"))))) - (let (http-stream must-close done) + (let ((proxying-https? (and proxy (eq :https (puri:uri-scheme uri)))) + http-stream raw-http-stream must-close done) (unwind-protect (progn (let ((host (or (and proxy (first proxy)) @@ -424,8 +425,8 @@ LispWorks 5.0 or higher." (port (cond (proxy (second proxy)) ((uri-port uri)) (t (default-port uri)))) - (use-ssl (or force-ssl - (eq (uri-scheme uri) :https)))) + (use-ssl (and (not proxying-https?) + (or force-ssl (eq (uri-scheme uri) :https))))) #+(and :lispworks5.0 :mswindows (not :lw-does-not-have-write-timeout)) (when use-ssl @@ -445,6 +446,7 @@ LispWorks 5.0 or higher." #-:lispworks (usocket:socket-stream (usocket:socket-connect host port :element-type 'octet)))) + (setq raw-http-stream http-stream) (when (and use-ssl ;; don't attach SSL to existing streams (not stream)) @@ -473,6 +475,24 @@ LispWorks 5.0 or higher." (format http-stream "~?~C~C" fmt args #\Return #\Linefeed)) (write-header (name value-fmt &rest value-args) (write-http-line "~A: ~?" name value-fmt value-args))) + (when proxying-https? + ;; Setup a tunnel through the proxy server to the + ;; final destination. + (write-http-line "CONNECT ~A:~A HTTP/1.1" (puri:uri-host uri) + (or (puri:uri-port uri) 443)) + (write-http-line "Host: ~A:~A" (puri:uri-host uri) + (or (puri:uri-port uri) 443)) + (write-http-line "") + (force-output http-stream) + ;; Check we get a 200 response before proceeding. + (let ((line (read-status-line http-stream *header-stream*))) + (unless (eq (second line) 200) + (error "Unable to establish HTTPS tunnel through proxy."))) + ;; Got a connection. We have to read a blank line, + ;; turn on SSL, and then we can transmit. + (read-line* http-stream) + #+:lispworks + (comm:attach-ssl raw-http-stream :ssl-side :client)) (when (and (not parameters-used-p) parameters) (setf (uri-query uri)
On Mon, 19 May 2008 15:57:21 +0100, "Dave Lambert" d.j.lambert@gmail.com wrote:
I need to contact HTTPS servers through a proxy. I've managed to get this to work by having the http-request function issue an HTTP CONNECT commmand in order to tunnel SSL through the proxy: the patch is below (against 0.11.5). On the downside, it only works for Lispworks.
Thanks. Is this based on some standard or does it cater to one specific server? Drakma's (limited) proxy functionality didn't work for you?
--- a/request.lisp +++ b/request.lisp
Whatever email app you used ruined the patch. Can you send it as an attachment or with another program?
Cheers, Edi.
2008/5/19 Edi Weitz edi@agharta.de:
On Mon, 19 May 2008 15:57:21 +0100, "Dave Lambert" d.j.lambert@gmail.com wrote:
I need to contact HTTPS servers through a proxy. I've managed to get this to work by having the http-request function issue an HTTP CONNECT commmand in order to tunnel SSL through the proxy: the patch is below (against 0.11.5). On the downside, it only works for Lispworks.
Drakma's (limited) proxy functionality didn't work for you?
Drakma's HTTP proxy support is just great, but I also need to create an HTTPS connection from behind a firewall. This patch adds just that HTTPS functionality.
There was a previous request for this on the mailing list:
http://common-lisp.net/pipermail/drakma-devel/2007-November/000212.html
Is this based on some standard or does it cater to one specific server?
The approach is standard: Use the HTTP CONNECT method to get a tunnel through the proxy, and then send SSL on the same connection. It's covered in HTTP 1.1: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.9
I've tested it on my local proxy, and a couple of HTTPS end points.
Whatever email app you used ruined the patch. Can you send it as an attachment or with another program?
That's a shame (it's Gmail). Patch attached this time.
Cheers, Dave
On Mon, 19 May 2008 17:14:25 +0100, "Dave Lambert" d.j.lambert@open.ac.uk wrote:
There was a previous request for this on the mailing list:
http://common-lisp.net/pipermail/drakma-devel/2007-November/000212.html
Yup. Seems I forgot... :)
The approach is standard: Use the HTTP CONNECT method to get a tunnel through the proxy, and then send SSL on the same connection. It's covered in HTTP 1.1: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.9
I've tested it on my local proxy, and a couple of HTTPS end points.
Thanks. I'll look into this and will likely integrate something like this into the next release.
Cheers, Edi.