cURL / Mailing Lists / curl-library / Single Mail

curl-library

connection reuse with proxies and ssl

From: Gautam Kachroo <gk4curl_at_gmail.com>
Date: Wed, 23 Jan 2008 12:49:43 -0800

Hi. There seems to be an issue with connection re-use: we can end up sending
requests over a CONNECT tunnel that lacks an SSL connection.

This state is reachable when using the multi (async) interface if a proxy
tunnel connection is reset before the SSL connection is established, e.g.
when conn->bits.tunnel_connecting is TRUE. This connection can be re-used
for another request, but the SSL connection will not be established for the
re-used connection. The new request will be sent over the connection in the
clear since the SSL connection was not established.

This stems from the fact that a connection can be re-used even if the
protocol specific initialization wasn't finished *and* the protocol specific
initialization isn't performed on the re-used connection.
SetupConnection only calls Curl_protocol_connect if conn->sock[FIRSTSOCKET]
is CURL_SOCKET_BAD. This isn't true if the connection was re-used so the
protocol init gets skipped.

SSL connections are established via a protocol init function
(Curl_https_connect), so skipping the protocol init on re-used connections
means no SSL connection is made over the CONNECT tunnel.

Example flow:
* Connected to proxy (10.12.16.20) port 3128 (#0)
* Establish HTTP proxy tunnel to example.com:443
> CONNECT example.com:443 HTTP/1.0

[reset the connection before an SSL connection is made with the destination
host but don't tear it down]

* Re-using existing connection! (#0) with host proxy
* Connected to proxy (10.12.16.20) port 3128 (#0)
> GET / HTTP/1.1
<---- this won't be using SSL

A diff against 7.17.1 is at the end.
It works by changing the re-use logic in ConnnectionExists for proxy SSL
tunnels so it skips connections that haven't got a valid SSL connection, i.e.
those don't have ssl_connect_data::use as true.

The use flag seemed like a better thing to check than the tunnel_connecting
bit since it's more directly tied to the SSL state. It wasn't possible to
use connecting_state (for openssl) since it's reset to ssl_connect_1 when
the SSL connection is made.

Probably better would be looking at protocol_done, but I didn't see a
protocol_done bit in the connection struct -- it's a local variable in
places like Curl_do.

Another alternative was changing Curl_done to not re-use connections that
didn't have a successful SSL connection, but you might want to keep those
connection around if you start doing protocol initialization on re-used
connections.

--- orig/curl-7.17.1/lib/url.c 2007-10-26 15:25:19.000000000 -0700
+++ curl-7.17.1/lib/url.c 2008-01-23 07:25:20.546875000 -0800
@@ -2423,6 +2423,15 @@
                   "can't reuse\n",
                   check->connectindex );
             continue;
+ } else {
+ struct ssl_connect_data *connssl = &check->ssl[FIRSTSOCKET];
+ if(check->bits.tunnel_proxy && !connssl->use) {
+ infof(data,
+ "Connection #%ld has not started ssl connect, "
+ "can't reuse\n",
+ check->connectindex );
+ continue;
+ }
           }
         }
         if((needle->protocol & PROT_FTP) ||

thanks,
-gk
Received on 2008-01-23