mirror of
https://github.com/curl/curl.git
synced 2024-11-21 01:16:58 +08:00
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:
parent
09897b8146
commit
a15d107dde
7
CHANGES
7
CHANGES
@ -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.
|
||||
|
@ -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)
|
||||
|
16
docs/curl.1
16
docs/curl.1
@ -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
|
||||
|
@ -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
197
lib/url.c
@ -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;
|
||||
}
|
||||
|
29
src/main.c
29
src/main.c
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user