aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--RELEASE-NOTES8
-rw-r--r--docs/curl.115
-rw-r--r--docs/libcurl/curl_easy_setopt.310
-rw-r--r--include/curl/curl.h5
-rw-r--r--lib/socks.c110
-rw-r--r--lib/url.c8
-rw-r--r--lib/urldata.h6
-rw-r--r--src/main.c30
9 files changed, 158 insertions, 40 deletions
diff --git a/CHANGES b/CHANGES
index b3f8bdd54..ae47a1e62 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@
Changelog
+Daniel S (4 Jan 2008)
+- Based on Maxim Perenesenko's patch, we now do SOCKS5 operations and let the
+ proxy do the host name resolving and only if --socks5ip (or
+ CURLOPT_SOCKS5_RESOLVE_LOCAL) is used we resolve the host name locally and
+ pass on the IP address only to the proxy.
+
Yang Tse (3 Jan 2008)
- Modified test harness to allow SCP, SFTP and SOCKS4 tests to run with
OpenSSH 2.9.9, SunSSH 1.0 or later versions. SOCKS5 tests need OpenSSH
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index e17dcb94a..bfa1fe291 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,8 +1,8 @@
Curl and libcurl 7.17.2
Public curl releases: 103
- Command line options: 124
- curl_easy_setopt() options: 148
+ Command line options: 125
+ curl_easy_setopt() options: 149
Public functions in libcurl: 55
Public web site mirrors: 42
Known libcurl bindings: 36
@@ -14,6 +14,7 @@ This release includes the following changes:
o CURLOPT_PROXY_TRANSFER_MODE was added
o --no-keep-alive was added
o --socks4a added (proxy type CURLPROXY_SOCKS4A for libcurl)
+ o --socks5ip added (CURLOPT_SOCKS5_RESOLVE_LOCAL for libcurl)
This release includes the following bugfixes:
@@ -42,6 +43,7 @@ This release includes the following bugfixes:
o bad connection re-use check with environment variable-activated proxy use
o --libcurl now generates a return statement as well
o socklen_t is no longer used in the public includes
+ o SOCKS5 uses now let the proxy resolve the host names by default
This release includes the following known bugs:
@@ -63,6 +65,6 @@ advice from friends like these:
Robin Johnson, Michal Marek, Ates Goral, Andres Garcia, Rob Crittenden,
Emil Romanus, Alessandro Vesely, Ray Pekowski, Spacen Jasset, Andrew Moise,
Gilles Blanc, David Wright, Vikram Saxena, Mateusz Loskot, Gary Maxwell,
- Dmitry Kurochkin, Mohun Biswas, Richard Atterer
+ Dmitry Kurochkin, Mohun Biswas, Richard Atterer, Maxim Perenesenko
Thanks! (and sorry if I forgot to mention someone)
diff --git a/docs/curl.1 b/docs/curl.1
index b94a1dc54..731c945db 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -1084,8 +1084,19 @@ mutually exclusive.
If this option is used several times, the last one will be used.
.IP "--socks5 <host[:port]>"
-Use the specified SOCKS5 proxy. If the port number is not specified, it is
-assumed at port 1080. (Added in 7.11.1)
+Use the specified SOCKS5 proxy (and let the proxy resolve the host name). If
+the port number is not specified, it is assumed at port 1080. (Added in
+7.11.1)
+
+This option overrides any previous use of \fI-x/--proxy\fP, as they are
+mutually exclusive.
+
+If this option is used several times, the last one will be used. (This option
+was previously wrongly documented and used as --socks without the number
+appended.)
+.IP "--socks5ip <host[:port]>"
+Use the specified SOCKS5 proxy - but resolve the host name locally. If the
+port number is not specified, it is assumed at port 1080. (Added in 7.17.2)
This option overrides any previous use of \fI-x/--proxy\fP, as they are
mutually exclusive.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index cc2af682e..299ac3ebb 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
-.TH curl_easy_setopt 3 "30 Aug 2007" "libcurl 7.17.0" "libcurl Manual"
+.TH curl_easy_setopt 3 "4 Jan 2008" "libcurl 7.17.2" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@@ -433,11 +433,19 @@ Pass a long with this option to set type of the proxy. Available options for
this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2),
\fICURLPROXY_SOCKS5\fP and \fICURLPROXY_SOCKS4A\fP (added in 7.17.2). The HTTP
type is default. (Added in 7.10)
+
+See also \fIURLOPT_SOCKS5_RESOLVE_LOCAL\fP.
.IP CURLOPT_HTTPPROXYTUNNEL
Set the parameter to non-zero to get the library to tunnel all operations
through a given HTTP proxy. There is a big difference between using a proxy
and to tunnel through it. If you don't know what this means, you probably
don't want this tunneling option.
+.IP CURLOPT_SOCKS5_RESOLVE_LOCAL
+Set the parameter to 1 to get the library to resolve the host name locally
+instead of passing it to the proxy to resolve, when using a SOCKS5 proxy.
+
+Note that libcurl before 7.17.2 always resolved the host name locally even
+when SOCKS5 was used. (Added in 7.17.2)
.IP CURLOPT_INTERFACE
Pass a char * as parameter. This set the interface name to use as outgoing
network interface. The name can be an interface name, an IP address or a host
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 396a0e0f2..c1288a7e9 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1172,6 +1172,11 @@ typedef enum {
/* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+ /* Set using of SOCKS5 to resolve host names locally instead of sending them
+ to the proxy to let it resolve them. Valid only if CURLOPT_PROXYTYPE ==
+ CURLPROXY_SOCKS5, otherwise ignored. */
+ CINIT(SOCKS5_RESOLVE_LOCAL, LONG, 167),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
diff --git a/lib/socks.c b/lib/socks.c
index 5146b0dc4..90ec1f215 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -390,6 +390,17 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
curl_socket_t sock = conn->sock[sockindex];
struct SessionHandle *data = conn->data;
long timeout;
+ bool socks5_resolve_local = data->set.socks5_resolve_local;
+ const size_t hostname_len = strlen(hostname);
+ int packetsize = 0;
+
+ /* 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 "
+ "length > 255 [actual len=%d]\n", hostname_len);
+ socks5_resolve_local = TRUE;
+ }
/* get timeout */
if(data->set.timeout && data->set.connecttimeout) {
@@ -553,13 +564,26 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
socksreq[0] = 5; /* version (SOCKS5) */
socksreq[1] = 1; /* connect */
socksreq[2] = 0; /* must be zero */
- socksreq[3] = 1; /* IPv4 = 1 */
- {
+ if(!socks5_resolve_local) {
+ packetsize = 5 + hostname_len + 2;
+
+ socksreq[3] = 3; /* ATYP: domain name = 3 */
+ socksreq[4] = (char) hostname_len; /* address length */
+ memcpy(&socksreq[5], hostname, hostname_len); /* address bytes w/o NULL */
+
+ *((unsigned short*)&socksreq[hostname_len+5]) =
+ htons((unsigned short)remote_port);
+ }
+ else {
struct Curl_dns_entry *dns;
Curl_addrinfo *hp=NULL;
int rc = Curl_resolv(conn, hostname, remote_port, &dns);
+ packetsize = 10;
+
+ socksreq[3] = 1; /* IPv4 = 1 */
+
if(rc == CURLRESOLV_ERROR)
return CURLE_COULDNT_RESOLVE_HOST;
@@ -595,40 +619,76 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
hostname);
return CURLE_COULDNT_RESOLVE_HOST;
}
+
+ *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port);
}
- *((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port);
+ code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
+ if((code != CURLE_OK) || (written != packetsize)) {
+ failf(data, "Failed to send SOCKS5 connect request.");
+ return CURLE_COULDNT_CONNECT;
+ }
- {
- const int packetsize = 10;
+ packetsize = 10; /* minimum packet size is 10 */
+
+ result = blockread_all(conn, sock, (char *)socksreq, packetsize,
+ &actualread, timeout);
+ if((result != CURLE_OK) || (actualread != packetsize)) {
+ failf(data, "Failed to receive SOCKS5 connect request ack.");
+ return CURLE_COULDNT_CONNECT;
+ }
- code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
- if((code != CURLE_OK) || (written != packetsize)) {
- failf(data, "Failed to send SOCKS5 connect request.");
+ if(socksreq[0] != 5) { /* version */
+ failf(data,
+ "SOCKS5 reply has wrong version, version should be 5.");
+ return CURLE_COULDNT_CONNECT;
+ }
+ if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ 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 int)ntohs(*(unsigned short*)(&socksreq[8])),
+ socksreq[1]);
return CURLE_COULDNT_CONNECT;
- }
+ }
- result = blockread_all(conn, sock, (char *)socksreq, packetsize,
+ /* 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
+ subsequent protocol level.
+
+ +----+-----+-------+------+----------+----------+
+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+ +----+-----+-------+------+----------+----------+
+ | 1 | 1 | X'00' | 1 | Variable | 2 |
+ +----+-----+-------+------+----------+----------+
+
+ ATYP:
+ o IP v4 address: X'01', BND.ADDR = 4 byte
+ o domain name: X'03', BND.ADDR = [ 1 byte length, string ]
+ o IP v6 address: X'04', BND.ADDR = 16 byte
+ */
+
+ /* Calculate real packet size */
+ if(socksreq[3] == 3) {
+ /* domain name */
+ int addrlen = (int) socksreq[4];
+ packetsize = 5 + addrlen + 2;
+ }
+ else if(socksreq[3] == 4) {
+ /* IPv6 */
+ packetsize = 4 + 16 + 2;
+ }
+
+ /* At this point we already read first 10 bytes */
+ if(packetsize > 10) {
+ packetsize -= 10;
+ result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize,
&actualread, timeout);
if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
-
- if(socksreq[0] != 5) { /* version */
- failf(data,
- "SOCKS5 reply has wrong version, version should be 5.");
- return CURLE_COULDNT_CONNECT;
- }
- if(socksreq[1] != 0) { /* Anything besides 0 is an error */
- 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 int)ntohs(*(unsigned short*)(&socksreq[8])),
- socksreq[1]);
- return CURLE_COULDNT_CONNECT;
- }
}
Curl_nonblock(sock, TRUE);
diff --git a/lib/url.c b/lib/url.c
index 550cb2113..774e25ff2 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2054,6 +2054,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
}
break;
+ case CURLOPT_SOCKS5_RESOLVE_LOCAL:
+ /*
+ * Enable or disable using of SOCKS5 proxy server to resolve domain names
+ * instead of using platform API like gethostbyname_r etc
+ */
+ data->set.socks5_resolve_local = (bool)(0 != va_arg(param, long));
+ break;
+
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_FAILED_INIT; /* correct this */
diff --git a/lib/urldata.h b/lib/urldata.h
index 9febb8415..2f061e035 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, 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
@@ -1441,7 +1441,9 @@ struct UserDefined {
long new_directory_perms; /* Permissions to use when creating remote dirs */
bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP
via an HTTP proxy */
-
+ bool socks5_resolve_local; /* resolve host names locally even if a SOCKS5
+ proxy in use. Valid only if CURLOPT_PROXYTYPE
+ == CURLPROXY_SOCKS5, otherwise ignored. */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
};
diff --git a/src/main.c b/src/main.c
index 77298913f..78f37c79a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -480,6 +480,8 @@ struct Configurable {
bool raw;
bool post301;
bool nokeepalive;
+ bool socks5_resolve_local; /* don't use SOCKS5 proxy server to resolve
+ domain names */
struct OutStruct *outs;
};
@@ -713,7 +715,8 @@ static void help(void)
" -S/--show-error Show error. With -s, make curl show errors when they occur",
" --socks4 <host[:port]> Use SOCKS4 proxy on given host + port",
" --socks4a <host[:port]> Use SOCKS4a proxy on given host + port",
- " --socks5 <host[:port]> Use SOCKS5 proxy on given host + port",
+ " --socks5 <host[:port]> Use SOCKS5 proxy and let the proxy resolve names",
+ " --socks5ip <host[:port]> Use SOCKS5 proxy on given host + port",
" --stderr <file> Where to redirect stderr. - means stdout",
" -t/--telnet-option <OPT=val> Set telnet option",
" --trace <file> Write a debug trace to the given file",
@@ -1514,10 +1517,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"*z", "disable-eprt", FALSE},
{"$a", "ftp-ssl", FALSE},
{"$b", "ftp-pasv", FALSE},
- {"$c", "socks5", TRUE},
- {"$c", "socks", TRUE}, /* this is how the option was documented but
- we prefer the --socks5 version for explicit
- version */
+ {"$c", "socks5ip", TRUE},
+ {"$c", "socks", TRUE}, /* this is how the option once was documented
+ but we prefer the --socks5 version for
+ explicit version */
{"$d", "tcp-nodelay",FALSE},
{"$e", "proxy-digest", FALSE},
{"$f", "proxy-basic", FALSE},
@@ -1544,6 +1547,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$#", "raw", FALSE},
{"$0", "post301", FALSE},
{"$1", "no-keep-alive", FALSE},
+ {"$2", "socks5", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
@@ -1900,9 +1904,11 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
free(config->ftpport);
config->ftpport = NULL;
break;
- case 'c': /* --socks5 specifies a socks5 proxy to use */
+ case 'c': /* --socks5ip specifies a socks5 proxy to use, but resolves
+ the name locally and passes on the resolved address */
GetStr(&config->socksproxy, nextarg);
config->socksver = CURLPROXY_SOCKS5;
+ config->socks5_resolve_local = TRUE;
break;
case 't': /* --socks4 specifies a socks4 proxy to use */
GetStr(&config->socksproxy, nextarg);
@@ -1912,6 +1918,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
GetStr(&config->socksproxy, nextarg);
config->socksver = CURLPROXY_SOCKS4A;
break;
+ case '2': /* --socks5 specifies a socks5 proxy and enables name resolving
+ with the proxy */
+ GetStr(&config->socksproxy, nextarg);
+ config->socksver = CURLPROXY_SOCKS5;
+ config->socks5_resolve_local = FALSE;
+ break;
case 'd': /* --tcp-nodelay option */
config->tcp_nodelay ^= TRUE;
break;
@@ -4340,7 +4352,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
/* SSH host key md5 checking allows us to fail if we are
- * not talking to who we think we should
+ * not talking to who we think we should
*/
my_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, config->hostpubmd5);
@@ -4497,6 +4509,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
if(config->socksproxy) {
my_setopt(curl, CURLOPT_PROXY, config->socksproxy);
my_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
+ if(config->socksver==CURLPROXY_SOCKS5)
+ /* added in 7.17.2 */
+ my_setopt(curl, CURLOPT_SOCKS5_RESOLVE_LOCAL,
+ config->socks5_resolve_local);
}
/* curl 7.13.0 */