Peter Su added support for SOCKS4 proxies. Enable this by setting the proxy

type to the already provided type CURLPROXY_SOCKS4.
I added a --socks4 option that works like the current --socks5 option but
instead use the socks4 protocol.
This commit is contained in:
Daniel Stenberg 2006-02-21 07:46:41 +00:00
parent 09897b8146
commit a15d107dde
6 changed files with 239 additions and 21 deletions

View File

@ -6,6 +6,13 @@
Changelog
Daniel (21 February 2006)
- Peter Su added support for SOCKS4 proxies. Enable this by setting the proxy
type to the already provided type CURLPROXY_SOCKS4.
I added a --socks4 option that works like the current --socks5 option but
instead use the socks4 protocol.
Daniel (20 February 2006)
- Shmulik Regev fixed an issue with multi-pass authentication and compressed
content when libcurl didn't honor the internal ignorebody flag.

View File

@ -2,7 +2,7 @@ Curl and libcurl 7.15.2
Public curl release number: 92
Releases counted from the very beginning: 119
Available command line options: 111
Available command line options: 112
Available curl_easy_setopt() options: 129
Number of public functions in libcurl: 46
Amount of public web site mirrors: 31
@ -11,6 +11,7 @@ Curl and libcurl 7.15.2
This release includes the following changes:
o Support for SOCKS4 proxies (added --socks4)
o CURLOPT_CONNECT_ONLY and CURLINFO_LASTSOCKET added
o CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE (--local-port) added
o Dropped support for the LPRT ftp command
@ -65,6 +66,6 @@ advice from friends like these:
Dov Murik, Jean Jacques Drouin, Andres Garcia, Yang Tse, Gisle Vanem, Dan
Fandrich, Alexander Lazic, Michael Jahn, Andrew Benham, Bryan Henderson,
David Shaw, Jon Turner, Duane Cathey, Michal Marek, Philippe Vaucher, Kent
Boortz, Karl Moerder, Shmulik Regev, Ulf Härnhammar, Shmulik Regev
Boortz, Karl Moerder, Shmulik Regev, Ulf Härnhammar, Peter Su
Thanks! (and sorry if I forgot to mention someone)

View File

@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
.TH curl 1 "24 Nov 2005" "Curl 7.15.1" "Curl Manual"
.TH curl 1 "21 Feb 2006" "Curl 7.15.2" "Curl Manual"
.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
@ -859,14 +859,24 @@ If this option is used twice, the second will again disable silent mode.
When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error.
.IP "--socks <host[:port]>"
.IP "--socks4 <host[:port]>"
Use the specified SOCKS4 proxy. If the port number is not specified, it is
assumed at port 1080. (Added in 7.15.2)
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.
.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)
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.
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 "--stderr <file>"
Redirect all writes to stderr to the specified file instead. If the file name
is a plain '-', it is instead written to stdout. This option has no point when

View File

@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
.TH curl_easy_setopt 3 "28 Jan 2006" "libcurl 7.15.2" "libcurl Manual"
.TH curl_easy_setopt 3 "21 Feb 2006" "libcurl 7.15.2" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@ -324,8 +324,8 @@ Pass a long with this option to set the proxy port to connect to unless it is
specified in the proxy string \fICURLOPT_PROXY\fP.
.IP CURLOPT_PROXYTYPE
Pass a long with this option to set type of the proxy. Available options for
this are \fICURLPROXY_HTTP\fP and \fICURLPROXY_SOCKS5\fP, with the HTTP one
being default. (Added in 7.10)
this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2)
\fICURLPROXY_SOCKS5\fP. The HTTP type is default. (Added in 7.10)
.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

197
lib/url.c
View File

@ -1809,6 +1809,191 @@ ConnectionStore(struct SessionHandle *data,
return i;
}
/*
* This function logs in to a SOCKS4 proxy and sends the specifies the final
* desitination server.
*
* Reference :
* http://socks.permeo.com/protocol/socks4.protocol
*
* Note :
* Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
static int handleSock4Proxy(struct connectdata *conn)
{
unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
int result;
CURLcode code;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct SessionHandle *data = conn->data;
Curl_nonblock(sock, FALSE);
/*
* Compose socks4 request
*
* Request format
*
* +----+----+----+----+----+----+----+----+----+----+....+----+
* | VN | CD | DSTPORT | DSTIP | USERID |NULL|
* +----+----+----+----+----+----+----+----+----+----+....+----+
* # of bytes: 1 1 2 4 variable 1
*/
socksreq[0] = 4; /* version (SOCKS4) */
socksreq[1] = 1; /* connect */
*((unsigned short*)&socksreq[2]) = htons(conn->remote_port);
/* DNS resolve */
{
struct Curl_dns_entry *dns;
Curl_addrinfo *hp=NULL;
int rc;
rc = Curl_resolv(conn, conn->host.name, (int)conn->remote_port, &dns);
if(rc == CURLRESOLV_ERROR)
return 1;
if(rc == CURLRESOLV_PENDING)
/* this requires that we're in "wait for resolve" state */
rc = Curl_wait_for_resolv(conn, &dns);
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
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];
}
else
hp = NULL; /* fail! */
Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
}
if(!hp) {
failf(conn->data, "Failed to resolve \"%s\" for SOCKS4 connect.\n",
conn->host.name);
return 1;
}
}
/*
* Make connection
*/
{
ssize_t actualread;
ssize_t written;
int packetsize = 9; /* request data size (include NULL) */
/* Send request */
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
if ((code != CURLE_OK) || (written != packetsize)) {
failf(conn->data, "Failed to send SOCKS4 connect request.\n");
return 1;
}
packetsize = 8; /* receive data size */
/* Receive response */
result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread);
if ((result != CURLE_OK) || (actualread != packetsize)) {
failf(conn->data, "Failed to receive SOCKS4 connect request ack.\n");
return 1;
}
/*
* Response format
*
* +----+----+----+----+----+----+----+----+
* | VN | CD | DSTPORT | DSTIP |
* +----+----+----+----+----+----+----+----+
* # of bytes: 1 1 2 4
*
* VN is the version of the reply code and should be 0. CD is the result
* code with one of the following values:
*
* 90: request granted
* 91: request rejected or failed
* 92: request rejected becasue SOCKS server cannot connect to
* identd on the client
* 93: request rejected because the client program and identd
* report different user-ids
*/
/* wrong version ? */
if (socksreq[0] != 0) {
failf(conn->data,
"SOCKS4 reply has wrong version, version should be 4.\n");
return 1;
}
/* Result */
switch(socksreq[1])
{
case 90:
infof(data, "SOCKS4 request granted.\n");
break;
case 91:
failf(conn->data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected or failed.\n",
(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 1;
case 92:
failf(conn->data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected becasue SOCKS server cannot connect to "
"identd on the client.\n",
(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 1;
case 93:
failf(conn->data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because the client program and identd "
"report different user-ids.\n",
(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 1;
default :
failf(conn->data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", Unknown.\n",
(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 1;
}
}
Curl_nonblock(sock, TRUE);
return 0; /* Proxy was successful! */
}
/*
* This function logs in to a SOCKS5 proxy and sends the specifies the final
* desitination server.
@ -2052,16 +2237,18 @@ static CURLcode ConnectPlease(struct connectdata *conn,
Curl_store_ip_addr(conn);
if (conn->data->set.proxytype == CURLPROXY_SOCKS5) {
switch(conn->data->set.proxytype) {
case CURLPROXY_SOCKS5:
return handleSock5Proxy(conn->proxyuser,
conn->proxypasswd,
conn) ?
CURLE_COULDNT_CONNECT : CURLE_OK;
}
else if (conn->data->set.proxytype == CURLPROXY_HTTP) {
case CURLPROXY_HTTP:
/* do nothing here. handled later. */
}
else {
break;
case CURLPROXY_SOCKS4:
return handleSock4Proxy(conn) ? CURLE_COULDNT_CONNECT : CURLE_OK;
default:
failf(conn->data, "unknown proxytype option given");
return CURLE_COULDNT_CONNECT;
}

View File

@ -343,7 +343,10 @@ struct Configurable {
struct timeval lastrecvtime;
size_t lastrecvsize;
bool ftp_ssl;
char *socks5proxy;
char *socksproxy; /* set to server string */
int socksver; /* set to CURLPROXY_SOCKS* define */
bool tcp_nodelay;
long req_retry; /* number of retries */
long retry_delay; /* delay between retries (in seconds) */
@ -557,7 +560,8 @@ static void help(void)
" --retry-max-time <seconds> Retry only within this period",
" -s/--silent Silent mode. Don't output anything",
" -S/--show-error Show error. With -s, make curl show errors when they occur",
" --socks <host[:port]> Use SOCKS5 proxy on given host + port",
" --socks4 <host[:port]> Use SOCKS4 proxy on given host + port",
" --socks5 <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",
@ -1314,6 +1318,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$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 */
{"$d", "tcp-nodelay",FALSE},
{"$e", "proxy-digest", FALSE},
{"$f", "proxy-basic", FALSE},
@ -1330,6 +1337,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$q", "ftp-skip-pasv-ip", FALSE},
{"$r", "ftp-method", TRUE},
{"$s", "local-port", TRUE},
{"$t", "socks4", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
@ -1673,8 +1681,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
free(config->ftpport);
config->ftpport = NULL;
break;
case 'c': /* --socks specifies a socks5 proxy to use */
GetStr(&config->socks5proxy, nextarg);
case 'c': /* --socks5 specifies a socks5 proxy to use */
GetStr(&config->socksproxy, nextarg);
config->socksver = CURLPROXY_SOCKS5;
break;
case 't': /* --socks4 specifies a socks5 proxy to use */
GetStr(&config->socksproxy, nextarg);
config->socksver = CURLPROXY_SOCKS4;
break;
case 'd': /* --tcp-nodelay option */
config->tcp_nodelay ^= TRUE;
@ -3972,10 +3985,10 @@ operate(struct Configurable *config, int argc, char *argv[])
if(config->ftp_ssl)
curl_easy_setopt(curl, CURLOPT_FTP_SSL, CURLFTPSSL_TRY);
/* new in curl 7.11.1 */
if(config->socks5proxy) {
curl_easy_setopt(curl, CURLOPT_PROXY, config->socks5proxy);
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
/* new in curl 7.11.1, modified in 7.15.2 */
if(config->socksproxy) {
curl_easy_setopt(curl, CURLOPT_PROXY, config->socksproxy);
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
}
/* curl 7.13.0 */