Here's my patch for 5.47, and Chris Hiner's patch for 5.48. I haven't yet
tried Chris's patch, though.
-----Original Message-----
From: Ashley Jones [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, August 16, 2000 11:19 AM
To: [EMAIL PROTECTED]
Subject: SSL through proxy
Does anyone have the patch by David Worenklien titled:
[PATCH] LWP 5.47, Keep-Alive, and HTTPS through a
proxy server
mentioned in earlier posts.
I'm still having trouble with getting through the
proxy server and would like to try this
implementation.
Thanks
Ashley Jones
BellSouth
__________________________________________________
Do You Yahoo!?
Send instant messages & get email alerts with Yahoo! Messenger.
http://im.yahoo.com/
I've merged Scott Gifford's "Keep-Alive" patch with my own "HTTPS through a
proxy server", and applied them to libwww-perl-5.47. The resulting diff is
attached.
I've included Scott's original e-mail that describes his changes. My
change is simple: saying
GET 'https://some.site'
will now cause LWP to connect to the proxy server, issue a "CONNECT
some.site::443 HTTP/1.0" request, and then pass SSL messages through the
resulting connection.
<<libwww-perl-5.47.patch>> <<Persistent connections patch for
libwww-perl>>
libwww-perl-5.47.patch
Hello,
I just finished patching up libwww-perl to handle persistent
connections, and thought I'd pop onto this list to post my patch and
make sure it works. Apologies if this duplicates somebody else's
efforts; I just threw it together for a project, without checking if
anybody else was working on it.
The patch adds a 'connection_cache' method to LWP::UserAgent, which
takes a boolean argument to turn connection caching on or off. When
it is on, a connection cache is maintained as part of the UserAgent
object. It is passed in to protocol handlers that support it (right
now just http), and they can access and modify the cache. When it is
off, LWP behaves identically to before the patch.
The bulk of the work is done in LWP::Protocol::http. The
_new_socket method has been changed to check the cache first, and
store opened connections in the cache. The request method has been
rearranged a little bit, to build all the headers and the request line
before connecting the socket. This made it easier to wrap the whole
connect/send request/read response code inside a block and an eval, so
we can detect a cached connection we thought was open that wasn't, and
retry the whole thing if we need to. If connection caching is
activated, we add a "Connection: Keep-Alive" header to our request,
and if we get the same back in our response, we look at the
Content-Length, and only read that may bytes before returning, leaving
the connection open. We never explicitly close the socket now; we
rely on Perl to close it correctly when all references to it have
disappeared. This makes managing the cached connections much simpler.
This patch implements HTTP/1.0 style connection caching. It works
correctly with or without proxies. It never shuts connections down
for the lifetime of the UserAgent unless there is an error or the
server requests it; this could be considered a bug.
Let me know if you have any problems with this patch. I have tried
to make the changes as straightforward as possible, and as transparent
as possible if you don't turn on the connection_cache option.
-----ScottG.
libwww-perl-keepalive.patch
I dug through the archives, and didn't find a patch that would apply to
5.48 to fix these problems. So I decided to dig in, and see what was
broken. As mentioned before, one problem was that it was trying to do a
GET https://some.example.com/ to the proxy, instead of the CONNECT
syntax that Netscape and IE use.
After fixing that, I discovered another bug, that prevented POST's from
working properly. It was sending headers and such on the CONNECT, which
were confusing the web server when it was expecting SSL negotiation.
This patch contains modified versions of http.pm and https.pm as applied
to libwww-perl-5.48. It enables HTTPS connections to work through a proxy
server. I've tested it using an Apache proxy server. GETs and POSTs both
work correctly for the things I needed them for. I don't know if my hacks
break anything for direct connections, or if it breaks anything like client
certificates. I'm not much of a Perl hacker yet, so I've probably done
things suboptimally... But it works for what I am using it for.
I hope someone fixes this problem properly, and gets it put into the next
version of libwww.
Chris Hiner
[EMAIL PROTECTED]
It is partially based on a patch by:
WORENKLEIN, David, GCM ([EMAIL PROTECTED]) titled:
[PATCH] LWP 5.47, Keep-Alive, and HTTPS through a proxy server
on Wed, 5 Apr 2000 16:12:22 -0400
Which is in turn based on a patch by Scott Gifford <[EMAIL PROTECTED]>
diff -N -c5 -r -w libwww-perl-5.48/lib/LWP/Protocol/http.pm
libwww-perl-5.48.mine/lib/LWP/Protocol/http.pm
*** libwww-perl-5.48/lib/LWP/Protocol/http.pm Sun Apr 9 15:06:46 2000
--- libwww-perl-5.48.mine/lib/LWP/Protocol/http.pm Sun Aug 6 23:34:24 2000
***************
*** 111,123 ****
$port = $url->port;
$fullpath = $url->path_query;
$fullpath = "/" unless length $fullpath;
}
# connect to remote site
! my $socket = $self->_new_socket($host, $port, $timeout);
$self->_check_sock($request, $socket);
my $sel = IO::Select->new($socket) if $timeout;
my $request_line = "$method $fullpath HTTP/1.0$CRLF";
--- 111,128 ----
$port = $url->port;
$fullpath = $url->path_query;
$fullpath = "/" unless length $fullpath;
}
+ my $socket;
# connect to remote site
! if(defined ($request->{client_socket})) {
! $socket=$request->{client_socket};
! } else {
! $socket = $self->_new_socket($host, $port, $timeout);
$self->_check_sock($request, $socket);
+ }
my $sel = IO::Select->new($socket) if $timeout;
my $request_line = "$method $fullpath HTTP/1.0$CRLF";
***************
*** 142,157 ****
--- 147,171 ----
$self->_fixup_header($h, $url);
my $buf = $request_line . $h->as_string($CRLF) . $CRLF;
my $n; # used for return value from syswrite/sysread
+
+ # CH This seems to fix the HTTPS PROXY POST problems
+ if ($method eq "CONNECT") {
+ $buf = $request_line . $CRLF . $CRLF;
+ }
+
die "write timeout" if $timeout && !$sel->can_write($timeout);
$n = $socket->syswrite($buf, length($buf));
die $! unless defined($n);
die "short write" unless $n == length($buf);
LWP::Debug::conns($buf);
+ # CH This seems to fix the HTTPS PROXY POST problems
+ if ($method ne "CONNECT") {
+
if ($ctype eq 'CODE') {
while ( ($buf = &$cont_ref()), defined($buf) && length($buf)) {
die "write timeout" if $timeout && !$sel->can_write($timeout);
$n = $socket->syswrite($buf, length($buf));
die $! unless defined($n);
***************
*** 164,174 ****
$n = $socket->syswrite($$cont_ref, length($$cont_ref));
die $! unless defined($n);
die "short write" unless $n == length($$cont_ref);
LWP::Debug::conns($buf);
}
!
# read response line from server
LWP::Debug::debug('reading response');
my $response;
$buf = '';
--- 178,188 ----
$n = $socket->syswrite($$cont_ref, length($$cont_ref));
die $! unless defined($n);
die "short write" unless $n == length($$cont_ref);
LWP::Debug::conns($buf);
}
! }
# read response line from server
LWP::Debug::debug('reading response');
my $response;
$buf = '';
diff -N -c5 -r -w libwww-perl-5.48/lib/LWP/Protocol/https.pm
libwww-perl-5.48.mine/lib/LWP/Protocol/https.pm
*** libwww-perl-5.48/lib/LWP/Protocol/https.pm Sun Apr 9 15:06:07 2000
--- libwww-perl-5.48.mine/lib/LWP/Protocol/https.pm Sun Aug 6 23:35:07 2000
***************
*** 68,73 ****
--- 68,130 ----
$res->header("Client-SSL-Cert-Issuer" => $cert->issuer_name);
}
$res->header("Client-SSL-Warning" => "Peer certificate not verified");
}
+ # proxy connect patch
+ sub request
+ {
+ my $self = shift;
+ my($request, $proxy, $arg, $size, $timeout) = @_;
+ LWP::Debug::trace('()');
+
+ return $self->SUPER::request(@_)
+ unless ($proxy);
+
+ # We need to get through the proxy server with a regular
+ # http connection, then we transmogrify the connection into
+ # a secure socket.
+
+ my $url = $request->url;
+ my $host = $url->host;
+ my $port = $url->port;
+
+ my $socket;
+
+ my $proxy_request = $request->clone;
+ $proxy_request->method("CONNECT");
+ # $proxy_request->uri(new URI("$host:$port"));
+
+ my $proxy_protocol = LWP::Protocol::create('http');
+
+ LWP::Debug::trace("Trying to CONNECT through the proxy server");
+
+ my $proxy_response = $proxy_protocol->request($proxy_request, $proxy, $arg,
+$size, $timeout);
+
+ # Did we get through the proxy server?
+ return $proxy_response
+ unless($proxy_response->code == 200);
+
+ $socket=$proxy_response->{client_socket};
+
+ # Turn the socket into an SSL socket
+ LWP::Debug::trace("Transmogrifying our socket");
+ bless $socket, "Net::SSL";
+ *$socket->{'ssl_ctx'} = Net::SSL::_default_context();
+ my $ssl = Crypt::SSLeay::Conn->new(*$socket->{'ssl_ctx'}, $socket);
+ if ($ssl->connect <= 0) {
+ # XXX should obtain the real SSLeay error message
+ LWP::Debug::trace("SSL error:".$ssl->connect);
+ $socket->_error("SSL negotiation failed");
+ return new HTTP::Response &HTTP::Status::RC_INTERNAL_SERVER_ERROR,
+ 'SSL negotiation failed.';
+ }
+ *$socket->{'ssl_ssl'} = $ssl;
+
+ $request->{client_socket} = $socket; # so it can be picked up
+
+ return $self->SUPER::request($request, undef, $arg, $size, $timeout);
+ }
+
+
+
1;