mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05: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
|
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)
|
Daniel (2 November 2006)
|
||||||
- James Housley brought support for SCP transfers, based on the libssh2 library
|
- James Housley brought support for SCP transfers, based on the libssh2 library
|
||||||
for the actual network protocol stuff.
|
for the actual network protocol stuff.
|
||||||
|
@ -15,7 +15,7 @@ This release includes the following changes:
|
|||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o
|
o proxy close during CONNECT authentication is now dealt with nicely
|
||||||
|
|
||||||
Other curl-related news:
|
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
|
"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
|
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.
|
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
|
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
|
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,
|
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr,
|
||||||
(size_t)(amount-included_body_bytes), conn);
|
(size_t)(amount-included_body_bytes), conn);
|
||||||
if (included_body_bytes)
|
if (included_body_bytes)
|
||||||
Curl_debug(conn->data, CURLINFO_DATA_OUT,
|
Curl_debug(conn->data, CURLINFO_DATA_OUT,
|
||||||
ptr+amount-included_body_bytes,
|
ptr+amount-included_body_bytes,
|
||||||
(size_t)included_body_bytes, conn);
|
(size_t)included_body_bytes, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,6 +1110,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
curl_socket_t tunnelsocket = conn->sock[sockindex];
|
||||||
send_buffer *req_buffer;
|
send_buffer *req_buffer;
|
||||||
curl_off_t cl=0;
|
curl_off_t cl=0;
|
||||||
|
bool closeConnection = FALSE;
|
||||||
|
|
||||||
#define SELECT_OK 0
|
#define SELECT_OK 0
|
||||||
#define SELECT_ERROR 1
|
#define SELECT_ERROR 1
|
||||||
@ -1117,6 +1118,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
int error = SELECT_OK;
|
int error = SELECT_OK;
|
||||||
|
|
||||||
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
|
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
|
||||||
|
conn->bits.proxy_connect_closed = FALSE;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(data->reqdata.newurl) {
|
if(data->reqdata.newurl) {
|
||||||
@ -1258,7 +1260,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
|
|
||||||
/* output debug if that is requested */
|
/* output debug if that is requested */
|
||||||
if(data->set.verbose)
|
if(data->set.verbose)
|
||||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||||
line_start, (size_t)perline, conn);
|
line_start, (size_t)perline, conn);
|
||||||
|
|
||||||
/* send the header to the callback */
|
/* send the header to the callback */
|
||||||
@ -1310,6 +1312,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
|
cl = curlx_strtoofft(line_start + strlen("Content-Length:"),
|
||||||
NULL, 10);
|
NULL, 10);
|
||||||
}
|
}
|
||||||
|
else if(Curl_compareheader(line_start,
|
||||||
|
"Connection:", "close"))
|
||||||
|
closeConnection = TRUE;
|
||||||
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
|
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
|
||||||
&subversion,
|
&subversion,
|
||||||
&k->httpcode)) {
|
&k->httpcode)) {
|
||||||
@ -1336,11 +1341,21 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
headers. 'newurl' is set to a new URL if we must loop. */
|
headers. 'newurl' is set to a new URL if we must loop. */
|
||||||
Curl_http_auth_act(conn);
|
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);
|
} while(data->reqdata.newurl);
|
||||||
|
|
||||||
if(200 != k->httpcode) {
|
if(200 != k->httpcode) {
|
||||||
failf(data, "Received HTTP code %d from proxy after CONNECT",
|
failf(data, "Received HTTP code %d from proxy after CONNECT",
|
||||||
k->httpcode);
|
k->httpcode);
|
||||||
|
|
||||||
|
if (closeConnection && data->reqdata.newurl)
|
||||||
|
conn->bits.proxy_connect_closed = TRUE;
|
||||||
|
|
||||||
return CURLE_RECV_ERROR;
|
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
|
/* it has started, possibly even completed but that knowledge isn't stored
|
||||||
in this bit! */
|
in this bit! */
|
||||||
conn->bits.protoconnstart = TRUE;
|
if (!result)
|
||||||
|
conn->bits.protoconnstart = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result; /* pass back status */
|
return result; /* pass back status */
|
||||||
@ -3957,30 +3958,41 @@ static CURLcode SetupConnection(struct connectdata *conn,
|
|||||||
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
|
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
|
||||||
#endif /* CURL_DO_LINEEND_CONV */
|
#endif /* CURL_DO_LINEEND_CONV */
|
||||||
|
|
||||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
for(;;) {
|
||||||
bool connected = FALSE;
|
/* loop for CURL_SERVER_CLOSED_CONNECTION */
|
||||||
|
|
||||||
/* Connect only if not already connected! */
|
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||||
result = ConnectPlease(data, conn, hostaddr, &connected);
|
bool connected = FALSE;
|
||||||
|
|
||||||
if(connected) {
|
/* Connect only if not already connected! */
|
||||||
result = Curl_protocol_connect(conn, protocol_done);
|
result = ConnectPlease(data, conn, hostaddr, &connected);
|
||||||
if(CURLE_OK == result)
|
|
||||||
conn->bits.tcpconnect = TRUE;
|
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
|
else {
|
||||||
conn->bits.tcpconnect = FALSE;
|
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||||
|
conn->bits.tcpconnect = TRUE;
|
||||||
|
*protocol_done = TRUE;
|
||||||
if(CURLE_OK != result)
|
if(data->set.verbose)
|
||||||
return result;
|
verboseconnect(conn);
|
||||||
}
|
}
|
||||||
else {
|
/* Stop the loop now */
|
||||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
break;
|
||||||
conn->bits.tcpconnect = TRUE;
|
|
||||||
*protocol_done = TRUE;
|
|
||||||
if(data->set.verbose)
|
|
||||||
verboseconnect(conn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
|
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
|
when Curl_done() is called, to prevent Curl_done() to
|
||||||
get invoked twice when the multi interface is
|
get invoked twice when the multi interface is
|
||||||
used. */
|
used. */
|
||||||
bool stream_was_rewound; /* Indicates that the stream was rewound after a request
|
bool stream_was_rewound; /* Indicates that the stream was rewound after a
|
||||||
read past the end of its response byte boundary */
|
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 {
|
struct hostname {
|
||||||
|
Loading…
Reference in New Issue
Block a user