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.
This commit is contained in:
Daniel Stenberg 2006-11-03 12:43:55 +00:00
parent 7f79b52dae
commit a777eb3d81
6 changed files with 66 additions and 33 deletions

View File

@ -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.

View File

@ -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:

View File

@ -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

View File

@ -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;
}

View File

@ -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;
/* 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 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
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);
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

View File

@ -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 {