mirror of
https://github.com/curl/curl.git
synced 2026-05-05 01:59:54 +03:00
socks filter: pass operation parameters
Pass all operations parameters to a SOCKS filter at creation time, not relying on "global" connectdata values. Eliminate modifications to `conn->ip_version` when local resolving for SOCKS4. Do not retrieve the socket for GSSAPI blocking calls from connectdata, but from the filters "below" the SOCKS one. Closes #21436
This commit is contained in:
parent
7d295145eb
commit
4840fe3f8a
3 changed files with 143 additions and 104 deletions
|
|
@ -374,7 +374,27 @@ connect_sub_chain:
|
|||
/* sub-chain connected, do we need to add more? */
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(ctx->state < CF_SETUP_CNNCT_SOCKS && cf->conn->bits.socksproxy) {
|
||||
result = Curl_cf_socks_proxy_insert_after(cf, data);
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
const char *hostname =
|
||||
cf->conn->bits.httpproxy ?
|
||||
cf->conn->http_proxy.host.name :
|
||||
cf->conn->bits.conn_to_host ?
|
||||
cf->conn->conn_to_host.name :
|
||||
cf->sockindex == SECONDARYSOCKET ?
|
||||
cf->conn->secondaryhostname : cf->conn->host.name;
|
||||
uint16_t port =
|
||||
cf->conn->bits.httpproxy ? cf->conn->http_proxy.port :
|
||||
cf->sockindex == SECONDARYSOCKET ? cf->conn->secondary_port :
|
||||
cf->conn->bits.conn_to_port ? cf->conn->conn_to_port :
|
||||
cf->conn->remote_port;
|
||||
const char *user = cf->conn->socks_proxy.user;
|
||||
const char *passwd = cf->conn->socks_proxy.passwd;
|
||||
|
||||
result = Curl_cf_socks_proxy_insert_after(
|
||||
cf, data, hostname, port, cf->conn->ip_version,
|
||||
cf->conn->socks_proxy.proxytype, user, passwd);
|
||||
if(result)
|
||||
return result;
|
||||
ctx->state = CF_SETUP_CNNCT_SOCKS;
|
||||
|
|
|
|||
212
lib/socks.c
212
lib/socks.c
|
|
@ -95,19 +95,21 @@ static const char * const cf_socks_statename[] = {
|
|||
#define SOCKS_CHUNKS 1
|
||||
|
||||
|
||||
struct socks_state {
|
||||
struct socks_ctx {
|
||||
enum socks_state_t state;
|
||||
struct bufq iobuf;
|
||||
const char *hostname;
|
||||
uint16_t remote_port;
|
||||
const char *proxy_user;
|
||||
const char *proxy_password;
|
||||
const char *user;
|
||||
const char *passwd;
|
||||
CURLproxycode presult;
|
||||
uint32_t resolv_id;
|
||||
uint8_t ip_version;
|
||||
uint8_t proxy_type;
|
||||
unsigned char version;
|
||||
BIT(resolve_local);
|
||||
BIT(start_resolving);
|
||||
BIT(socks4a);
|
||||
char hostname[1];
|
||||
};
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
|
|
@ -129,13 +131,15 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf,
|
|||
*pnread = 0;
|
||||
for(;;) {
|
||||
timediff_t timeout_ms = Curl_timeleft_ms(data);
|
||||
curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* we already got the timeout */
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
if(!timeout_ms)
|
||||
timeout_ms = TIMEDIFF_T_MAX;
|
||||
if(SOCKET_READABLE(cf->conn->sock[cf->sockindex], timeout_ms) <= 0)
|
||||
if(SOCKET_READABLE(sock, timeout_ms) <= 0)
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
|
||||
if(result == CURLE_AGAIN)
|
||||
|
|
@ -164,7 +168,7 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf,
|
|||
#endif
|
||||
|
||||
/* always use this function to change state, to make debugging easier */
|
||||
static void socksstate(struct socks_state *sx,
|
||||
static void socksstate(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
enum socks_state_t state
|
||||
|
|
@ -191,7 +195,7 @@ static void socksstate(struct socks_state *sx,
|
|||
#endif
|
||||
}
|
||||
|
||||
static CURLproxycode socks_failed(struct socks_state *sx,
|
||||
static CURLproxycode socks_failed(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
CURLproxycode presult)
|
||||
|
|
@ -201,7 +205,7 @@ static CURLproxycode socks_failed(struct socks_state *sx,
|
|||
return presult;
|
||||
}
|
||||
|
||||
static CURLproxycode socks_flush(struct socks_state *sx,
|
||||
static CURLproxycode socks_flush(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
|
|
@ -225,7 +229,7 @@ static CURLproxycode socks_flush(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks_recv(struct socks_state *sx,
|
||||
static CURLproxycode socks_recv(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
size_t min_bytes,
|
||||
|
|
@ -259,7 +263,7 @@ static CURLproxycode socks_recv(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks4_req_add_hd(struct socks_state *sx,
|
||||
static CURLproxycode socks4_req_add_hd(struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
|
|
@ -278,14 +282,14 @@ static CURLproxycode socks4_req_add_hd(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks4_req_add_user(struct socks_state *sx,
|
||||
static CURLproxycode socks4_req_add_user(struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result;
|
||||
size_t nwritten;
|
||||
|
||||
if(sx->proxy_user) {
|
||||
size_t plen = strlen(sx->proxy_user);
|
||||
if(sx->user) {
|
||||
size_t plen = strlen(sx->user);
|
||||
if(plen > 255) {
|
||||
/* there is no real size limit to this field in the protocol, but
|
||||
SOCKS5 limits the proxy user field to 255 bytes and it seems likely
|
||||
|
|
@ -294,7 +298,7 @@ static CURLproxycode socks4_req_add_user(struct socks_state *sx,
|
|||
return CURLPX_LONG_USER;
|
||||
}
|
||||
/* add proxy name WITH trailing zero */
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_user, plen + 1,
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->user, plen + 1,
|
||||
&nwritten);
|
||||
if(result || (nwritten != (plen + 1)))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
|
|
@ -309,7 +313,7 @@ static CURLproxycode socks4_req_add_user(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks4_resolving(struct socks_state *sx,
|
||||
static CURLproxycode socks4_resolving(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
|
|
@ -323,9 +327,8 @@ static CURLproxycode socks4_resolving(struct socks_state *sx,
|
|||
if(sx->start_resolving) {
|
||||
/* need to resolve hostname to add destination address */
|
||||
sx->start_resolving = FALSE;
|
||||
DEBUGASSERT(sx->hostname && *sx->hostname);
|
||||
result = Curl_cf_dns_insert_after(
|
||||
cf, data, Curl_resolv_dns_queries(data, cf->conn->ip_version),
|
||||
cf, data, Curl_resolv_dns_queries(data, sx->ip_version),
|
||||
sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE);
|
||||
if(result) {
|
||||
failf(data, "unable to create DNS filter for socks");
|
||||
|
|
@ -370,7 +373,7 @@ static CURLproxycode socks4_resolving(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks4_check_resp(struct socks_state *sx,
|
||||
static CURLproxycode socks4_check_resp(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
|
|
@ -459,7 +462,7 @@ static CURLproxycode socks4_check_resp(struct socks_state *sx,
|
|||
* Nonsupport "Identification Protocol (RFC1413)"
|
||||
*/
|
||||
static CURLproxycode socks4_connect(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
size_t nwritten;
|
||||
|
|
@ -477,16 +480,14 @@ process_state:
|
|||
case SOCKS4_ST_START:
|
||||
Curl_bufq_reset(&sx->iobuf);
|
||||
sx->start_resolving = FALSE;
|
||||
sx->socks4a = (cf->conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A);
|
||||
sx->socks4a = (sx->proxy_type == CURLPROXY_SOCKS4A);
|
||||
sx->resolve_local = !sx->socks4a;
|
||||
sx->presult = CURLPX_OK;
|
||||
|
||||
/* SOCKS4 can only do IPv4, insist! */
|
||||
cf->conn->ip_version = CURL_IPRESOLVE_V4;
|
||||
CURL_TRC_CF(data, cf, "SOCKS4%s communication to%s %s:%u",
|
||||
sx->socks4a ? "a" : "",
|
||||
cf->conn->bits.httpproxy ? " HTTP proxy" : "",
|
||||
sx->hostname, sx->remote_port);
|
||||
sx->ip_version = CURL_IPRESOLVE_V4;
|
||||
CURL_TRC_CF(data, cf, "SOCKS4%s connecting to %s:%u",
|
||||
sx->socks4a ? "a" : "", sx->hostname, sx->remote_port);
|
||||
|
||||
/*
|
||||
* Compose socks4 request
|
||||
|
|
@ -579,7 +580,7 @@ process_state:
|
|||
}
|
||||
|
||||
static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
const unsigned char auth = data->set.socks5auth;
|
||||
|
|
@ -601,7 +602,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf,
|
|||
"CURLOPT_SOCKS5_AUTH: %u", auth);
|
||||
if(!(auth & CURLAUTH_BASIC))
|
||||
/* disable username/password auth */
|
||||
sx->proxy_user = NULL;
|
||||
sx->user = NULL;
|
||||
|
||||
req[0] = 5; /* version */
|
||||
nauths = 1;
|
||||
|
|
@ -612,7 +613,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf,
|
|||
req[1 + nauths] = 1; /* GSS-API */
|
||||
}
|
||||
#endif
|
||||
if(sx->proxy_user) {
|
||||
if(sx->user) {
|
||||
++nauths;
|
||||
req[1 + nauths] = 2; /* username/password */
|
||||
}
|
||||
|
|
@ -625,7 +626,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks5_check_resp0(struct socks_state *sx,
|
||||
static CURLproxycode socks5_check_resp0(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
|
|
@ -677,7 +678,7 @@ static CURLproxycode socks5_check_resp0(struct socks_state *sx,
|
|||
}
|
||||
|
||||
static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
/* Needs username and password */
|
||||
|
|
@ -685,9 +686,9 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
|
|||
unsigned char buf[2];
|
||||
CURLcode result;
|
||||
|
||||
if(sx->proxy_user && sx->proxy_password) {
|
||||
ulen = strlen(sx->proxy_user);
|
||||
plen = strlen(sx->proxy_password);
|
||||
if(sx->user && sx->passwd) {
|
||||
ulen = strlen(sx->user);
|
||||
plen = strlen(sx->passwd);
|
||||
/* the lengths must fit in a single byte */
|
||||
if(ulen > 255) {
|
||||
failf(data, "Excessive username length for proxy auth");
|
||||
|
|
@ -712,7 +713,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
|
|||
if(result || (nwritten != 2))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
if(ulen) {
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_user, ulen, &nwritten);
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->user, ulen, &nwritten);
|
||||
if(result || (nwritten != ulen))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
}
|
||||
|
|
@ -721,7 +722,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
|
|||
if(result || (nwritten != 1))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
if(plen) {
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_password, plen, &nwritten);
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->passwd, plen, &nwritten);
|
||||
if(result || (nwritten != plen))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
}
|
||||
|
|
@ -729,7 +730,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks5_check_auth_resp(struct socks_state *sx,
|
||||
static CURLproxycode socks5_check_auth_resp(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
|
|
@ -754,7 +755,7 @@ static CURLproxycode socks5_check_auth_resp(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks5_req1_init(struct socks_state *sx,
|
||||
static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
|
|
@ -823,7 +824,7 @@ static CURLproxycode socks5_req1_init(struct socks_state *sx,
|
|||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
static CURLproxycode socks5_resolving(struct socks_state *sx,
|
||||
static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
|
|
@ -842,9 +843,8 @@ static CURLproxycode socks5_resolving(struct socks_state *sx,
|
|||
if(sx->start_resolving) {
|
||||
/* need to resolve hostname to add destination address */
|
||||
sx->start_resolving = FALSE;
|
||||
DEBUGASSERT(sx->hostname && *sx->hostname);
|
||||
result = Curl_cf_dns_insert_after(
|
||||
cf, data, Curl_resolv_dns_queries(data, cf->conn->ip_version),
|
||||
cf, data, Curl_resolv_dns_queries(data, sx->ip_version),
|
||||
sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE);
|
||||
if(result) {
|
||||
failf(data, "unable to create DNS filter for socks");
|
||||
|
|
@ -928,7 +928,7 @@ out:
|
|||
return presult;
|
||||
}
|
||||
|
||||
static CURLproxycode socks5_recv_resp1(struct socks_state *sx,
|
||||
static CURLproxycode socks5_recv_resp1(struct socks_ctx *sx,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
|
|
@ -1027,7 +1027,7 @@ static CURLproxycode socks5_recv_resp1(struct socks_state *sx,
|
|||
* destination server.
|
||||
*/
|
||||
static CURLproxycode socks5_connect(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct socks_ctx *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLproxycode presult;
|
||||
|
|
@ -1037,14 +1037,13 @@ process_state:
|
|||
switch(sx->state) {
|
||||
case SOCKS_ST_INIT:
|
||||
sx->version = 5;
|
||||
sx->resolve_local = (cf->conn->socks_proxy.proxytype == CURLPROXY_SOCKS5);
|
||||
sx->resolve_local = (sx->proxy_type == CURLPROXY_SOCKS5);
|
||||
sxstate(sx, cf, data, SOCKS5_ST_START);
|
||||
FALLTHROUGH();
|
||||
|
||||
case SOCKS5_ST_START:
|
||||
if(cf->conn->bits.httpproxy)
|
||||
CURL_TRC_CF(data, cf, "SOCKS5: connecting to HTTP proxy %s port %u",
|
||||
sx->hostname, sx->remote_port);
|
||||
CURL_TRC_CF(data, cf, "SOCKS5: connecting to %s:%u",
|
||||
sx->hostname, sx->remote_port);
|
||||
presult = socks5_req0_init(cf, sx, data);
|
||||
if(presult)
|
||||
return socks_failed(sx, cf, data, presult);
|
||||
|
|
@ -1179,13 +1178,11 @@ process_state:
|
|||
}
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_free(struct Curl_cfilter *cf)
|
||||
static void socks_proxy_ctx_free(struct socks_ctx *ctx)
|
||||
{
|
||||
struct socks_state *sxstate = cf->ctx;
|
||||
if(sxstate) {
|
||||
Curl_bufq_free(&sxstate->iobuf);
|
||||
curlx_free(sxstate);
|
||||
cf->ctx = NULL;
|
||||
if(ctx) {
|
||||
Curl_bufq_free(&ctx->iobuf);
|
||||
curlx_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1200,11 +1197,9 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn = cf->conn;
|
||||
int sockindex = cf->sockindex;
|
||||
struct socks_state *sx = cf->ctx;
|
||||
struct socks_ctx *ctx = cf->ctx;
|
||||
CURLproxycode pxresult = CURLPX_OK;
|
||||
CURLcode result;
|
||||
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
|
|
@ -1215,47 +1210,19 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||
if(result || !*done)
|
||||
return result;
|
||||
|
||||
if(!sx) {
|
||||
cf->ctx = sx = curlx_calloc(1, sizeof(*sx));
|
||||
if(!sx) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
sx->hostname =
|
||||
conn->bits.httpproxy ?
|
||||
conn->http_proxy.host.name :
|
||||
conn->bits.conn_to_host ?
|
||||
conn->conn_to_host.name :
|
||||
sockindex == SECONDARYSOCKET ?
|
||||
conn->secondaryhostname : conn->host.name;
|
||||
sx->remote_port =
|
||||
conn->bits.httpproxy ? conn->http_proxy.port :
|
||||
sockindex == SECONDARYSOCKET ? conn->secondary_port :
|
||||
conn->bits.conn_to_port ? conn->conn_to_port :
|
||||
(uint16_t)conn->remote_port;
|
||||
sx->proxy_user = conn->socks_proxy.user;
|
||||
sx->proxy_password = conn->socks_proxy.passwd;
|
||||
Curl_bufq_init2(&sx->iobuf, SOCKS_CHUNK_SIZE, SOCKS_CHUNKS,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
}
|
||||
|
||||
switch(conn->socks_proxy.proxytype) {
|
||||
switch(ctx->proxy_type) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
pxresult = socks5_connect(cf, sx, data);
|
||||
pxresult = socks5_connect(cf, ctx, data);
|
||||
break;
|
||||
|
||||
case CURLPROXY_SOCKS4:
|
||||
case CURLPROXY_SOCKS4A:
|
||||
pxresult = socks4_connect(cf, sx, data);
|
||||
pxresult = socks4_connect(cf, ctx, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
failf(data, "unknown proxytype option given");
|
||||
DEBUGASSERT(0); /* should not come here, checked it at creation time */
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1265,7 +1232,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||
data->info.pxcode = pxresult;
|
||||
goto out;
|
||||
}
|
||||
else if(sx->state != SOCKS_ST_SUCCESS)
|
||||
else if(ctx->state != SOCKS_ST_SUCCESS)
|
||||
goto out;
|
||||
|
||||
#ifdef CURLVERBOSE
|
||||
|
|
@ -1275,20 +1242,23 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||
if(!Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad))
|
||||
infof(data, "Opened %sSOCKS connection from %s port %d to %s port %d "
|
||||
"(via %s port %u)",
|
||||
(sockindex == SECONDARYSOCKET) ? "2nd " : "",
|
||||
(cf->sockindex == SECONDARYSOCKET) ? "2nd " : "",
|
||||
ipquad.local_ip, ipquad.local_port,
|
||||
sx->hostname, sx->remote_port,
|
||||
ctx->hostname, ctx->remote_port,
|
||||
ipquad.remote_ip, ipquad.remote_port);
|
||||
else
|
||||
infof(data, "Opened %sSOCKS connection",
|
||||
(sockindex == SECONDARYSOCKET) ? "2nd " : "");
|
||||
(cf->sockindex == SECONDARYSOCKET) ? "2nd " : "");
|
||||
}
|
||||
#endif
|
||||
socks_proxy_cf_free(cf);
|
||||
cf->connected = TRUE;
|
||||
|
||||
out:
|
||||
*done = (bool)cf->connected;
|
||||
if(*done || result) {
|
||||
ctx->user = NULL;
|
||||
ctx->passwd = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1296,7 +1266,7 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
|
|||
struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
{
|
||||
struct socks_state *sx = cf->ctx;
|
||||
struct socks_ctx *sx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(!cf->connected && sx) {
|
||||
|
|
@ -1323,24 +1293,24 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf,
|
|||
static void socks_proxy_cf_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
cf->connected = FALSE;
|
||||
socks_proxy_cf_free(cf);
|
||||
cf->next->cft->do_close(cf->next, data);
|
||||
if(cf->next)
|
||||
cf->next->cft->do_close(cf->next, data);
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
socks_proxy_cf_free(cf);
|
||||
socks_proxy_ctx_free(cf->ctx);
|
||||
cf->ctx = NULL;
|
||||
}
|
||||
|
||||
static CURLcode socks_cf_query(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int query, int *pres1, void *pres2)
|
||||
{
|
||||
struct socks_state *sx = cf->ctx;
|
||||
struct socks_ctx *sx = cf->ctx;
|
||||
|
||||
switch(query) {
|
||||
case CF_QUERY_HOST_PORT:
|
||||
|
|
@ -1383,15 +1353,53 @@ struct Curl_cftype Curl_cft_socks_proxy = {
|
|||
};
|
||||
|
||||
CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
||||
struct Curl_easy *data)
|
||||
struct Curl_easy *data,
|
||||
const char *hostname,
|
||||
uint16_t port,
|
||||
uint8_t ip_version,
|
||||
uint8_t proxy_type,
|
||||
const char *user,
|
||||
const char *passwd)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
struct socks_ctx *ctx;
|
||||
size_t hostlen = hostname ? strlen(hostname) : 0;
|
||||
CURLcode result;
|
||||
|
||||
(void)data;
|
||||
result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, NULL);
|
||||
if(!hostlen)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
switch(proxy_type) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
case CURLPROXY_SOCKS4:
|
||||
case CURLPROXY_SOCKS4A:
|
||||
break; /* all supported */
|
||||
default:
|
||||
failf(data, "unknown proxytype %d option given", proxy_type);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* NUL byte already part of struct size */
|
||||
ctx = curlx_calloc(1, sizeof(*ctx) + hostlen);
|
||||
if(!ctx) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(ctx->hostname, hostname, hostlen);
|
||||
ctx->remote_port = port;
|
||||
ctx->ip_version = ip_version;
|
||||
ctx->proxy_type = proxy_type;
|
||||
ctx->user = user;
|
||||
ctx->passwd = passwd;
|
||||
Curl_bufq_init2(&ctx->iobuf, SOCKS_CHUNK_SIZE, SOCKS_CHUNKS,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
|
||||
result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, ctx);
|
||||
if(!result)
|
||||
Curl_conn_cf_insert_after(cf_at, cf);
|
||||
else
|
||||
socks_proxy_ctx_free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
13
lib/socks.h
13
lib/socks.h
|
|
@ -46,8 +46,19 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
|
|||
struct Curl_easy *data);
|
||||
#endif
|
||||
|
||||
/* Insert a SOCKS filter after `cf_at` for connecting to `hostname`
|
||||
* and `port` with optional credentials.
|
||||
* Credentials are NOT duplicated and are
|
||||
* expected to exist during connect phase.
|
||||
*/
|
||||
CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
||||
struct Curl_easy *data);
|
||||
struct Curl_easy *data,
|
||||
const char *hostname,
|
||||
uint16_t port,
|
||||
uint8_t ip_version,
|
||||
uint8_t proxy_type,
|
||||
const char *user,
|
||||
const char *passwd);
|
||||
|
||||
extern struct Curl_cftype Curl_cft_socks_proxy;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue