From 466d093a92f3e8ccbb8af026e786bc41708caba6 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Sep 2006 22:52:42 +0000 Subject: [PATCH] - "Dortik" (http://curl.haxx.se/bug/view.cgi?id=1551412) provided a patch that while not fixing things very nicely, it does make the SOCKS5 proxy connection slightly better as it now acknowledges the timeout for connection and it no longer segfaults in the case when SOCKS requires authentication and you did not specify username:password. --- CHANGES | 7 ++++++ RELEASE-NOTES | 2 ++ docs/KNOWN_BUGS | 8 +++++-- lib/url.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 1d8c39b..29ede8c 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,13 @@ Changelog +Daniel (4 September 2006) +- "Dortik" (http://curl.haxx.se/bug/view.cgi?id=1551412) provided a patch that + while not fixing things very nicely, it does make the SOCKS5 proxy + connection slightly better as it now acknowledges the timeout for connection + and it no longer segfaults in the case when SOCKS requires authentication + and you did not specify username:password. + Daniel (31 August 2006) - Dmitriy Sergeyev found and fixed a multi interface flaw when using asynch name resolves. It could get stuck in the wrong state. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 05fe3b1..6ac3a39 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -18,6 +18,8 @@ This release includes the following changes: This release includes the following bugfixes: + o SOCKS5 proxy connects can now time-out + o SOCKS5 connects that require auth no longer segfaults when auth not given o multi interface using asynch resolves could get stuck in wrong state o the 'running_handles' counter wasn't always updated properly when curl_multi_remove_handle() was used diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS index 38c657f..d16fdbb 100644 --- a/docs/KNOWN_BUGS +++ b/docs/KNOWN_BUGS @@ -3,7 +3,11 @@ join in and help us correct one or more of these! Also be sure to check the changelog of the current development status, as one or more of these problems may have been fixed since this was written! -34. The SOCKS connection codes don't properly acknowledge (connect) timeouts. +35. Both SOCKS5 and SOCKS4 proxy connections are done blocking, which is very + bad when used with the multi interface. + +34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts. + Also see #12. 33. Doing multi-pass HTTP authentication on a non-default port does not work. This happens because the multi-pass code abuses the redirect following code @@ -92,7 +96,7 @@ may have been fixed since this was written! 12. When connecting to a SOCKS proxy, the (connect) timeout is not properly acknowledged after the actual TCP connect (during the SOCKS "negotiate" - phase). Pointed out by Lucas. Fix: need to select() and timeout properly. + phase). 11. Using configure --disable-[protocol] may cause 'make test' to fail for tests using the disabled protocol(s). diff --git a/lib/url.c b/lib/url.c index aaf5913..6833979 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2115,14 +2115,49 @@ static int handleSock5Proxy(const char *proxy_name, int result; CURLcode code; curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct SessionHandle *data = conn->data; + long timeout; - Curl_nonblock(sock, FALSE); + /* get timeout */ + if(data->set.timeout && data->set.connecttimeout) { + if (data->set.timeout < data->set.connecttimeout) + timeout = data->set.timeout*1000; + else + timeout = data->set.connecttimeout*1000; + } + else if(data->set.timeout) + timeout = data->set.timeout*1000; + else if(data->set.connecttimeout) + timeout = data->set.connecttimeout*1000; + else + timeout = DEFAULT_CONNECT_TIMEOUT; + + Curl_nonblock(sock, TRUE); + + /* wait until socket gets connected */ + result = Curl_select(CURL_SOCKET_BAD, sock, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5: no connection here"); + return 1; + } + else if(0 == result) { + failf(conn->data, "SOCKS5: connection timeout"); + return 1; + } + + if(result & CSELECT_ERR) { + failf(conn->data, "SOCKS5: error occured during connection"); + return 1; + } socksreq[0] = 5; /* version */ socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */ socksreq[2] = 0; /* no authentication */ socksreq[3] = 2; /* username/password */ + Curl_nonblock(sock, FALSE); + code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), &written); if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) { @@ -2130,6 +2165,26 @@ static int handleSock5Proxy(const char *proxy_name, return 1; } + Curl_nonblock(sock, TRUE); + + result = Curl_select(sock, CURL_SOCKET_BAD, timeout); + + if(-1 == result) { + failf(conn->data, "SOCKS5 nothing to read"); + return 1; + } + else if(0 == result) { + failf(conn->data, "SOCKS5 read timeout"); + return 1; + } + + if(result & CSELECT_ERR) { + failf(conn->data, "SOCKS5 read error occured"); + return 1; + } + + Curl_nonblock(sock, FALSE); + result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread); if ((result != CURLE_OK) || (actualread != 2)) { failf(conn->data, "Unable to receive initial SOCKS5 response."); @@ -2146,10 +2201,16 @@ static int handleSock5Proxy(const char *proxy_name, } else if (socksreq[1] == 2) { /* Needs user name and password */ - int userlen, pwlen, len; - - userlen = (int)strlen(proxy_name); - pwlen = proxy_password?(int)strlen(proxy_password):0; + size_t userlen, pwlen; + int len; + if(proxy_name && proxy_password) { + userlen = strlen(proxy_name); + pwlen = proxy_password?strlen(proxy_password):0; + } + else { + userlen = 0; + pwlen = 0; + } /* username/password request looks like * +----+------+----------+------+----------+ @@ -4209,4 +4270,3 @@ CURLcode Curl_do_more(struct connectdata *conn) return result; } - -- 2.7.4