From: Pascal Scheffers Date: Fri, 27 Nov 2009 12:32:57 +0000 (+0000) Subject: Provide support for the CONNECT method for the http proxy. X-Git-Tag: v2.6~8 X-Git-Url: http://privyetmir.co.uk/gitweb.cgi?a=commitdiff_plain;h=e4dfe1159d71c96c1cbe8cd0aacd7c45d5561ee2;p=sockspy Provide support for the CONNECT method for the http proxy. Applied sourceforge patch #1076720 with modifications to make it work right. Signed-off-by: Pat Thoyts --- diff --git a/bin/sockspy.tcl b/bin/sockspy.tcl index f094b78..f3f2605 100644 --- a/bin/sockspy.tcl +++ b/bin/sockspy.tcl @@ -604,16 +604,35 @@ proc sockReadable {fromSock toSock who} { # to forward to. # proc ProxyConnect {fromSock data} { + set skip 0 set line1 [string range $data 0 [string first "\n" $data]] set line1 [string trimright $line1 "\r\n"] INFO "proxy request \"$line1\"" meta2 - set bad [regexp {^([^ ]+) +([^ ]+)} $line1 -> method uri] - if {$bad == 0} { + if {![regexp {^([^ ]+) +([^ ]+)} $line1 -> method uri]} { return -code error "failed to parse a uri from '$line1'" } + + set method [string trim [string toupper $method]] + if {$method eq "CONNECT"} { + foreach {host port} [split $uri :] break + if {$port eq ""} {set port 443} + set uri "https://$host:$port" + # Find the end of headers - if we do not have that yet then + # we will have to do some reading until we have that. + set pos [string first \r\n\r\n $data] + if { $pos == -1 } { + INFO "waiting for additional headers for CONNECT proxying" + set skip 1 + } else { + incr pos 4 + set data [string range $data $pos end] + INFO "[string length $data] bytes to send for CONNECT" + } + } + set state(uri) $uri ;# For debugging array set URI [::uri::split $uri] - if {$URI(scheme) != "http"} { + if {[lsearch -nocase {http https} $URI(scheme)] == -1} { return -code error "cannot proxy the '$URI(scheme)' protocol" } if {$URI(port) == ""} { set URI(port) 80 } @@ -621,16 +640,64 @@ proc ProxyConnect {fromSock data} { if {$bad} { return -code error "cannot connect to $URI(host):$URI(port) => $reason" } + if {$method eq "CONNECT"} { + # We must send an HTTP response header to the client + set s "HTTP/1.1 200 OK\nServer: SockSpy/$::state(version)\n" + insertData meta $s + puts $fromSock $s + } INFO "fowarding $method request to $URI(host):$URI(port)" meta2 - fileevent $fromSock readable \ - [list sockReadable $fromSock $sockServ client] + if {$skip} { + fileevent $fromSock readable \ + [list ProxySkip $fromSock $sockServ] + } else { + fileevent $fromSock readable \ + [list sockReadable $fromSock $sockServ client] + } fconfigure $sockServ -blocking 0 -buffering none -translation binary fileevent $sockServ readable \ [list sockReadable $sockServ $fromSock server] + puts -nonewline $sockServ $data return } +##+########################################################################## +# +# ProxySkip +# +# Called from a new CONNECT proxy connection when we still need to skip the +# http header. +# +proc ProxySkip {fromSock toSock} { + global state + set data [read $fromSock] + if {[string length $data] == 0} { + close $fromSock + catch { close $toSock } + INFO "----- closed connection -----" + INFO "waiting for new connection..." + return + } + set pos [string first \r\n\r\n $data] + if { $pos == -1 } { + # Just drop the data. + return + } + incr pos 4 + set data [string range $data $pos end] + if { [string length $data] > 0 } { + # Forward the real payload + catch { puts -nonewline $toSock $data } ; + insertData client $data + } + # And let the normal data handler do the rest: + fileevent $fromSock readable \ + [list sockReadable $fromSock $toSock client] + + update +} + ##+########################################################################## # # clntConnect -- Called when we get a new client connection