summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/socks.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/socks.c')
-rw-r--r--libs/libcurl/src/socks.c319
1 files changed, 180 insertions, 139 deletions
diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c
index b101a0de48..ac4270eacf 100644
--- a/libs/libcurl/src/socks.c
+++ b/libs/libcurl/src/socks.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -33,7 +33,6 @@
#include "urldata.h"
#include "sendf.h"
-#include "strequal.h"
#include "select.h"
#include "connect.h"
#include "timeval.h"
@@ -58,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
ssize_t nread;
ssize_t allread = 0;
int result;
- long timeleft;
+ timediff_t timeleft;
*n = 0;
for(;;) {
timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -67,14 +66,14 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
result = CURLE_OPERATION_TIMEDOUT;
break;
}
- if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
+ if(SOCKET_READABLE(sockfd, timeleft) <= 0) {
result = ~CURLE_OK;
break;
}
result = Curl_read_plain(sockfd, buf, buffersize, &nread);
if(CURLE_AGAIN == result)
continue;
- else if(result)
+ if(result)
break;
if(buffersize == nread) {
@@ -106,20 +105,21 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
-CURLcode Curl_SOCKS4(const char *proxy_name,
+CURLcode Curl_SOCKS4(const char *proxy_user,
const char *hostname,
int remote_port,
int sockindex,
- struct connectdata *conn,
- bool protocol4a)
+ struct connectdata *conn)
{
+ const bool protocol4a =
+ (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
#define SOCKS4REQLEN 262
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
id */
int result;
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
if(Curl_timeleft(data, NULL, TRUE) < 0) {
/* time-out, bail out, go home */
@@ -127,7 +127,13 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
return CURLE_OPERATION_TIMEDOUT;
}
- curlx_nonblock(sock, FALSE);
+ if(conn->bits.httpproxy)
+ infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+ protocol4a ? "a" : "", hostname, remote_port);
+
+ (void)curlx_nonblock(sock, FALSE);
+
+ infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
/*
* Compose socks4 request
@@ -148,7 +154,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
struct Curl_dns_entry *dns;
- Curl_addrinfo *hp=NULL;
+ Curl_addrinfo *hp = NULL;
int rc;
rc = Curl_resolv(conn, hostname, remote_port, &dns);
@@ -165,25 +171,29 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
- hp=dns->addr;
+ hp = dns->addr;
if(hp) {
char buf[64];
- unsigned short ip[4];
Curl_printable_address(hp, buf, sizeof(buf));
- if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
- &ip[0], &ip[1], &ip[2], &ip[3])) {
- /* Set DSTIP */
- socksreq[4] = (unsigned char)ip[0];
- socksreq[5] = (unsigned char)ip[1];
- socksreq[6] = (unsigned char)ip[2];
- socksreq[7] = (unsigned char)ip[3];
+ if(hp->ai_family == AF_INET) {
+ struct sockaddr_in *saddr_in;
+
+ saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
+ socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
+ socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1];
+ socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
+ socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];
+
+ infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
}
- else
+ else {
hp = NULL; /* fail! */
- Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+ failf(data, "SOCKS4 connection to %s not supported\n", buf);
+ }
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
@@ -196,14 +206,14 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
* This is currently not supporting "Identification Protocol (RFC1413)".
*/
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
- if(proxy_name) {
- size_t plen = strlen(proxy_name);
+ if(proxy_user) {
+ size_t plen = strlen(proxy_user);
if(plen >= sizeof(socksreq) - 8) {
failf(data, "Too long SOCKS proxy name, can't use!\n");
return CURLE_COULDNT_CONNECT;
}
/* copy the proxy name WITH trailing zero */
- memcpy(socksreq + 8, proxy_name, plen+1);
+ memcpy(socksreq + 8, proxy_user, plen + 1);
}
/*
@@ -214,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
ssize_t written;
ssize_t hostnamelen = 0;
int packetsize = 9 +
- (int)strlen((char*)socksreq + 8); /* size including NUL */
+ (int)strlen((char *)socksreq + 8); /* size including NUL */
/* If SOCKS4a, set special invalid IP address 0.0.0.x */
if(protocol4a) {
@@ -225,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* If still enough room in buffer, also append hostname */
hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
if(packetsize + hostnamelen <= SOCKS4REQLEN)
- strcpy((char*)socksreq + packetsize, hostname);
+ strcpy((char *)socksreq + packetsize, hostname);
else
hostnamelen = 0; /* Flag: hostname did not fit in buffer */
}
@@ -234,7 +244,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
code = Curl_write_plain(conn, sock, (char *)socksreq,
packetsize + hostnamelen,
&written);
- if((code != CURLE_OK) || (written != packetsize + hostnamelen)) {
+ if(code || (written != packetsize + hostnamelen)) {
failf(data, "Failed to send SOCKS4 connect request.");
return CURLE_COULDNT_CONNECT;
}
@@ -243,7 +253,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
hostnamelen = (ssize_t)strlen(hostname) + 1;
code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen,
&written);
- if((code != CURLE_OK) || (written != hostnamelen)) {
+ if(code || (written != hostnamelen)) {
failf(data, "Failed to send SOCKS4 connect request.");
return CURLE_COULDNT_CONNECT;
}
@@ -254,7 +264,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
/* Receive response */
result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
&actualread);
- if((result != CURLE_OK) || (actualread != packetsize)) {
+ if(result || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS4 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
@@ -296,8 +306,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
", request rejected or failed.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+ (unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 92:
failf(data,
@@ -306,8 +316,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
"identd on the client.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+ (unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 93:
failf(data,
@@ -316,8 +326,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
"report different user-ids.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+ (unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
default:
failf(data,
@@ -325,13 +335,13 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
", Unknown.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
+ (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+ (unsigned char)socksreq[1]);
return CURLE_COULDNT_CONNECT;
}
}
- curlx_nonblock(sock, TRUE);
+ (void)curlx_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}
@@ -340,7 +350,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
-CURLcode Curl_SOCKS5(const char *proxy_name,
+CURLcode Curl_SOCKS5(const char *proxy_user,
const char *proxy_password,
const char *hostname,
int remote_port,
@@ -365,20 +375,28 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
*/
unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
+ int idx;
ssize_t actualread;
ssize_t written;
int result;
CURLcode code;
curl_socket_t sock = conn->sock[sockindex];
- struct SessionHandle *data = conn->data;
- long timeout;
- bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+ struct Curl_easy *data = conn->data;
+ timediff_t timeout;
+ bool socks5_resolve_local =
+ (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(hostname);
ssize_t len = 0;
+ const unsigned long auth = data->set.socks5auth;
+ bool allow_gssapi = FALSE;
+
+ if(conn->bits.httpproxy)
+ infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+ hostname, remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
- infof(conn->data,"SOCKS5: server resolving disabled for hostnames of "
+ infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
"length > 255 [actual len=%zu]\n", hostname_len);
socks5_resolve_local = TRUE;
}
@@ -392,16 +410,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_OPERATION_TIMEDOUT;
}
- curlx_nonblock(sock, TRUE);
+ (void)curlx_nonblock(sock, TRUE);
/* wait until socket gets connected */
- result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout);
+ result = SOCKET_WRITABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5: no connection here");
return CURLE_COULDNT_CONNECT;
}
- else if(0 == result) {
+ if(0 == result) {
failf(conn->data, "SOCKS5: connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -411,36 +429,49 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_COULDNT_CONNECT;
}
- socksreq[0] = 5; /* version */
+ if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
+ infof(conn->data,
+ "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
+ auth);
+ if(!(auth & CURLAUTH_BASIC))
+ /* disable username/password auth */
+ proxy_user = NULL;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */
- socksreq[2] = 0; /* no authentication */
- socksreq[3] = 1; /* gssapi */
- socksreq[4] = 2; /* username/password */
-#else
- socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
- socksreq[2] = 0; /* no authentication */
- socksreq[3] = 2; /* username/password */
+ if(auth & CURLAUTH_GSSAPI)
+ allow_gssapi = TRUE;
#endif
- curlx_nonblock(sock, FALSE);
+ idx = 0;
+ socksreq[idx++] = 5; /* version */
+ idx++; /* reserve for the number of authentication methods */
+ socksreq[idx++] = 0; /* no authentication */
+ if(allow_gssapi)
+ socksreq[idx++] = 1; /* GSS-API */
+ if(proxy_user)
+ socksreq[idx++] = 2; /* username/password */
+ /* write the number of authentication methods */
+ socksreq[1] = (unsigned char) (idx - 2);
+
+ (void)curlx_nonblock(sock, FALSE);
+
+ infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port);
code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
&written);
- if((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
+ if(code || (written != (2 + (int)socksreq[1]))) {
failf(data, "Unable to send initial SOCKS5 request.");
return CURLE_COULDNT_CONNECT;
}
- curlx_nonblock(sock, TRUE);
+ (void)curlx_nonblock(sock, TRUE);
- result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout);
+ result = SOCKET_READABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5 nothing to read");
return CURLE_COULDNT_CONNECT;
}
- else if(0 == result) {
+ if(0 == result) {
failf(conn->data, "SOCKS5 read timeout");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -450,10 +481,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_RECV_ERROR;
}
- curlx_nonblock(sock, FALSE);
+ (void)curlx_nonblock(sock, FALSE);
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
- if((result != CURLE_OK) || (actualread != 2)) {
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if(result || (actualread != 2)) {
failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
}
@@ -467,23 +498,23 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- else if(socksreq[1] == 1) {
+ else if(allow_gssapi && (socksreq[1] == 1)) {
code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
- if(code != CURLE_OK) {
- failf(data, "Unable to negotiate SOCKS5 gssapi context.");
+ if(code) {
+ failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
return CURLE_COULDNT_CONNECT;
}
}
#endif
else if(socksreq[1] == 2) {
/* Needs user name and password */
- size_t proxy_name_len, proxy_password_len;
- if(proxy_name && proxy_password) {
- proxy_name_len = strlen(proxy_name);
+ size_t proxy_user_len, proxy_password_len;
+ if(proxy_user && proxy_password) {
+ proxy_user_len = strlen(proxy_user);
proxy_password_len = strlen(proxy_password);
}
else {
- proxy_name_len = 0;
+ proxy_user_len = 0;
proxy_password_len = 0;
}
@@ -496,23 +527,23 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
*/
len = 0;
socksreq[len++] = 1; /* username/pw subnegotiation version */
- socksreq[len++] = (unsigned char) proxy_name_len;
- if(proxy_name && proxy_name_len)
- memcpy(socksreq + len, proxy_name, proxy_name_len);
- len += proxy_name_len;
+ socksreq[len++] = (unsigned char) proxy_user_len;
+ if(proxy_user && proxy_user_len)
+ memcpy(socksreq + len, proxy_user, proxy_user_len);
+ len += proxy_user_len;
socksreq[len++] = (unsigned char) proxy_password_len;
if(proxy_password && proxy_password_len)
memcpy(socksreq + len, proxy_password, proxy_password_len);
len += proxy_password_len;
code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
- if((code != CURLE_OK) || (len != written)) {
+ if(code || (len != written)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
return CURLE_COULDNT_CONNECT;
}
- result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
- if((result != CURLE_OK) || (actualread != 2)) {
+ result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+ if(result || (actualread != 2)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
return CURLE_COULDNT_CONNECT;
}
@@ -528,17 +559,13 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
}
else {
/* error */
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- if(socksreq[1] == 255) {
-#else
- if(socksreq[1] == 1) {
+ if(!allow_gssapi && (socksreq[1] == 1)) {
failf(data,
"SOCKS5 GSSAPI per-message authentication is not supported.");
return CURLE_COULDNT_CONNECT;
}
- else if(socksreq[1] == 255) {
-#endif
- if(!proxy_name || !*proxy_name) {
+ if(socksreq[1] == 255) {
+ if(!proxy_user || !*proxy_user) {
failf(data,
"No authentication method was acceptable. (It is quite likely"
" that the SOCKS5 server wanted a username/password, since none"
@@ -579,7 +606,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(rc == CURLRESOLV_PENDING) {
/* this requires that we're in "wait for resolve" state */
code = Curl_resolver_wait_resolv(conn, &dns);
- if(code != CURLE_OK)
+ if(code)
return code;
}
@@ -588,36 +615,43 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
- hp=dns->addr;
+ hp = dns->addr;
if(hp) {
- struct sockaddr_in *saddr_in;
-#ifdef ENABLE_IPV6
- struct sockaddr_in6 *saddr_in6;
-#endif
int i;
+ char buf[64];
+ Curl_printable_address(hp, buf, sizeof(buf));
if(hp->ai_family == AF_INET) {
+ struct sockaddr_in *saddr_in;
socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
- saddr_in = (struct sockaddr_in*)hp->ai_addr;
+ saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
for(i = 0; i < 4; i++) {
- socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
- infof(data, "%d\n", socksreq[len-1]);
+ socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
+
+ infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
+ struct sockaddr_in6 *saddr_in6;
socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
- saddr_in6 = (struct sockaddr_in6*)hp->ai_addr;
+ saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
for(i = 0; i < 16; i++) {
- socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+ socksreq[len++] =
+ ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
}
+
+ infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
}
#endif
- else
+ else {
hp = NULL; /* fail! */
+ failf(data, "SOCKS5 connection to %s not supported\n", buf);
+ }
+
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
@@ -632,13 +666,13 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
- failf(data, "SOCKS5 gssapi protection not yet implemented.");
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
}
else
#endif
code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
- if((code != CURLE_OK) || (len != written)) {
+ if(code || (len != written)) {
failf(data, "Failed to send SOCKS5 connect request.");
return CURLE_COULDNT_CONNECT;
}
@@ -647,14 +681,14 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
- failf(data, "SOCKS5 gssapi protection not yet implemented.");
+ failf(data, "SOCKS5 GSS-API protection not yet implemented.");
}
else
#endif
result = Curl_blockread_all(conn, sock, (char *)socksreq,
len, &actualread);
- if((result != CURLE_OK) || (len != actualread)) {
+ if(result || (len != actualread)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
@@ -664,39 +698,6 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLE_COULDNT_CONNECT;
}
- if(socksreq[1] != 0) { /* Anything besides 0 is an error */
- if(socksreq[3] == 1) {
- failf(data,
- "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
- }
- else if(socksreq[3] == 3) {
- failf(data,
- "Can't complete SOCKS5 connection to %s:%d. (%d)",
- hostname,
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
- }
- else if(socksreq[3] == 4) {
- failf(data,
- "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
- "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
- (unsigned char)socksreq[8], (unsigned char)socksreq[9],
- (unsigned char)socksreq[10], (unsigned char)socksreq[11],
- (unsigned char)socksreq[12], (unsigned char)socksreq[13],
- (unsigned char)socksreq[14], (unsigned char)socksreq[15],
- (unsigned char)socksreq[16], (unsigned char)socksreq[17],
- (unsigned char)socksreq[18], (unsigned char)socksreq[19],
- ((socksreq[8] << 8) | socksreq[9]),
- socksreq[1]);
- }
- return CURLE_COULDNT_CONNECT;
- }
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
1928, so the reply packet should be read until the end to avoid errors at
@@ -731,10 +732,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
/* decrypt_gssapi_blockread already read the whole packet */
#endif
if(len > 10) {
- len -= 10;
result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
- len, &actualread);
- if((result != CURLE_OK) || (len != actualread)) {
+ len - 10, &actualread);
+ if(result || ((len - 10) != actualread)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
@@ -743,7 +743,48 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
}
#endif
- curlx_nonblock(sock, TRUE);
+ if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ if(socksreq[3] == 1) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (((unsigned char)socksreq[8] << 8) |
+ (unsigned char)socksreq[9]),
+ (unsigned char)socksreq[1]);
+ }
+ else if(socksreq[3] == 3) {
+ unsigned char port_upper = (unsigned char)socksreq[len - 2];
+ socksreq[len - 2] = 0;
+ failf(data,
+ "Can't complete SOCKS5 connection to %s:%d. (%d)",
+ (char *)&socksreq[5],
+ ((port_upper << 8) |
+ (unsigned char)socksreq[len - 1]),
+ (unsigned char)socksreq[1]);
+ socksreq[len - 2] = port_upper;
+ }
+ else if(socksreq[3] == 4) {
+ failf(data,
+ "Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
+ (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+ (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ (unsigned char)socksreq[8], (unsigned char)socksreq[9],
+ (unsigned char)socksreq[10], (unsigned char)socksreq[11],
+ (unsigned char)socksreq[12], (unsigned char)socksreq[13],
+ (unsigned char)socksreq[14], (unsigned char)socksreq[15],
+ (unsigned char)socksreq[16], (unsigned char)socksreq[17],
+ (unsigned char)socksreq[18], (unsigned char)socksreq[19],
+ (((unsigned char)socksreq[20] << 8) |
+ (unsigned char)socksreq[21]),
+ (unsigned char)socksreq[1]);
+ }
+ return CURLE_COULDNT_CONNECT;
+ }
+ infof(data, "SOCKS5 request granted.\n");
+
+ (void)curlx_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}