mirror of
https://github.com/curl/curl.git
synced 2024-11-21 01:16:58 +08:00
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:
parent
7f79b52dae
commit
a777eb3d81
7
CHANGES
7
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.
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
21
lib/http.c
21
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;
|
||||
}
|
||||
|
||||
|
56
lib/url.c
56
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;
|
||||
/* 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
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user