aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2006-11-03 12:43:55 +0000
committerDaniel Stenberg <daniel@haxx.se>2006-11-03 12:43:55 +0000
commita777eb3d816dbd437d9b8a9e3b7b52be91d68e3b (patch)
tree4de0aa44aafc8421f7e41ba36ae451257932e4ad
parent7f79b52daef837d0b9ba1e0d75bae0fba9a7f30c (diff)
Olaf Stueben provided a patch that I edited slightly. It fixes the notorious
KNOWN_BUGS #25, which happens when a proxy closes the connection when libcurl has sent CONNECT, as part of an authentication negotiation. Starting now, libcurl will re-connect accordingly and continue the authentication as it should.
-rw-r--r--CHANGES7
-rw-r--r--RELEASE-NOTES2
-rw-r--r--docs/KNOWN_BUGS5
-rw-r--r--lib/http.c21
-rw-r--r--lib/url.c54
-rw-r--r--lib/urldata.h8
6 files changed, 65 insertions, 32 deletions
diff --git a/CHANGES b/CHANGES
index 1865ee78a..d078ccf32 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,13 @@
Changelog
+Daniel (3 November 2006)
+- Olaf Stueben provided a patch that I edited slightly. It fixes the notorious
+ KNOWN_BUGS #25, which happens when a proxy closes the connection when
+ libcurl has sent CONNECT, as part of an authentication negotiation. Starting
+ now, libcurl will re-connect accordingly and continue the authentication as
+ it should.
+
Daniel (2 November 2006)
- James Housley brought support for SCP transfers, based on the libssh2 library
for the actual network protocol stuff.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index aa0d82618..1114d8252 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -15,7 +15,7 @@ This release includes the following changes:
This release includes the following bugfixes:
- o
+ o proxy close during CONNECT authentication is now dealt with nicely
Other curl-related news:
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 713c4515c..e7231b8f6 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -44,11 +44,6 @@ may have been fixed since this was written!
"system context" will make it use wrong(?) user name - at least when compared
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
-25. When doing a CONNECT request with curl it doesn't properly handle if the
- proxy closes the connection within the authentication "negotiation phase".
- Like if you do HTTPS or similar over a proxy and you use perhaps
- --proxy-anyauth.
-
23. We don't support SOCKS for IPv6. We don't support FTPS over a SOCKS proxy.
We don't have any test cases for SOCKS proxy. We probably have even more
bugs and lack of features when a SOCKS proxy is used. And there seem to be a
diff --git a/lib/http.c b/lib/http.c
index e31730e7d..0670f1e78 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -903,8 +903,8 @@ CURLcode add_buffer_send(send_buffer *in,
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
(size_t)(amount-included_body_bytes), conn);
if (included_body_bytes)
- Curl_debug(conn->data, CURLINFO_DATA_OUT,
- ptr+amount-included_body_bytes,
+ Curl_debug(conn->data, CURLINFO_DATA_OUT,
+ ptr+amount-included_body_bytes,
(size_t)included_body_bytes, conn);
}
@@ -1110,6 +1110,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
curl_socket_t tunnelsocket = conn->sock[sockindex];
send_buffer *req_buffer;
curl_off_t cl=0;
+ bool closeConnection = FALSE;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -1117,6 +1118,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
int error = SELECT_OK;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
+ conn->bits.proxy_connect_closed = FALSE;
do {
if(data->reqdata.newurl) {
@@ -1258,7 +1260,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* output debug if that is requested */
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
+ Curl_debug(data, CURLINFO_HEADER_IN,
line_start, (size_t)perline, conn);
/* send the header to the callback */
@@ -1310,6 +1312,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
NULL, 10);
}
+ else if(Curl_compareheader(line_start,
+ "Connection:", "close"))
+ closeConnection = TRUE;
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
&subversion,
&k->httpcode)) {
@@ -1336,11 +1341,21 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
headers. 'newurl' is set to a new URL if we must loop. */
Curl_http_auth_act(conn);
+ if (closeConnection && data->reqdata.newurl) {
+ /* Connection closed by server. Don't use it anymore */
+ sclose(conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ break;
+ }
} while(data->reqdata.newurl);
if(200 != k->httpcode) {
failf(data, "Received HTTP code %d from proxy after CONNECT",
k->httpcode);
+
+ if (closeConnection && data->reqdata.newurl)
+ conn->bits.proxy_connect_closed = TRUE;
+
return CURLE_RECV_ERROR;
}
diff --git a/lib/url.c b/lib/url.c
index 92e4a3b09..73b9debbe 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2394,7 +2394,8 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
/* it has started, possibly even completed but that knowledge isn't stored
in this bit! */
- conn->bits.protoconnstart = TRUE;
+ if (!result)
+ conn->bits.protoconnstart = TRUE;
}
return result; /* pass back status */
@@ -3957,30 +3958,41 @@ static CURLcode SetupConnection(struct connectdata *conn,
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
#endif /* CURL_DO_LINEEND_CONV */
- if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
- bool connected = FALSE;
+ for(;;) {
+ /* loop for CURL_SERVER_CLOSED_CONNECTION */
- /* Connect only if not already connected! */
- result = ConnectPlease(data, conn, hostaddr, &connected);
+ if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
+ bool connected = FALSE;
- if(connected) {
- result = Curl_protocol_connect(conn, protocol_done);
- if(CURLE_OK == result)
- conn->bits.tcpconnect = TRUE;
- }
- else
- conn->bits.tcpconnect = FALSE;
+ /* Connect only if not already connected! */
+ result = ConnectPlease(data, conn, hostaddr, &connected);
+ if(connected) {
+ result = Curl_protocol_connect(conn, protocol_done);
+ if(CURLE_OK == result)
+ conn->bits.tcpconnect = TRUE;
+ }
+ else
+ conn->bits.tcpconnect = FALSE;
- if(CURLE_OK != result)
- return result;
- }
- else {
- Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
- conn->bits.tcpconnect = TRUE;
- *protocol_done = TRUE;
- if(data->set.verbose)
- verboseconnect(conn);
+ /* if the connection was closed by the server while exchanging
+ authentication informations, retry with the new set
+ authentication information */
+ if(conn->bits.proxy_connect_closed)
+ continue;
+
+ if(CURLE_OK != result)
+ return result;
+ }
+ else {
+ Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
+ conn->bits.tcpconnect = TRUE;
+ *protocol_done = TRUE;
+ if(data->set.verbose)
+ verboseconnect(conn);
+ }
+ /* Stop the loop now */
+ break;
}
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
diff --git a/lib/urldata.h b/lib/urldata.h
index a42b09c76..440646d08 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -485,8 +485,12 @@ struct ConnectBits {
when Curl_done() is called, to prevent Curl_done() to
get invoked twice when the multi interface is
used. */
- bool stream_was_rewound; /* Indicates that the stream was rewound after a request
- read past the end of its response byte boundary */
+ bool stream_was_rewound; /* Indicates that the stream was rewound after a
+ request read past the end of its response byte
+ boundary */
+ bool proxy_connect_closed; /* set true if a proxy disconnected the
+ connection in a CONNECT request with auth, so
+ that libcurl should reconnect and continue. */
};
struct hostname {