url: split off proxy init and parsing from create_conn

Move the proxy parse/init into helper create_conn_helper_init_proxy to
mitigate the chances some non-proxy code will be mistakenly added to it.

Ref: https://github.com/curl/curl/issues/1274#issuecomment-281556510
Ref: https://github.com/curl/curl/pull/1293

Closes https://github.com/curl/curl/pull/1298
This commit is contained in:
Jay Satiro 2017-02-27 15:36:16 -05:00
Родитель cbff751e95
Коммит 9f20333443
1 изменённых файлов: 168 добавлений и 151 удалений

319
lib/url.c
Просмотреть файл

@ -5187,6 +5187,168 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
NULL, FALSE);
return result;
}
/* create_conn helper to parse and init proxy values. to be called after unix
socket init but before any proxy vars are evaluated. */
static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
{
char *proxy = NULL;
char *socksproxy = NULL;
char *no_proxy = NULL;
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
/*************************************************************
* Extract the user and password from the authentication string
*************************************************************/
if(conn->bits.proxy_user_passwd) {
result = parse_proxy_auth(data, conn);
if(result)
goto out;
}
/*************************************************************
* Detect what (if any) proxy to use
*************************************************************/
if(data->set.str[STRING_PROXY]) {
proxy = strdup(data->set.str[STRING_PROXY]);
/* if global proxy is set, this is it */
if(NULL == proxy) {
failf(data, "memory shortage");
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
if(data->set.str[STRING_PRE_PROXY]) {
socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
/* if global socks proxy is set, this is it */
if(NULL == socksproxy) {
failf(data, "memory shortage");
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
no_proxy = curl_getenv("no_proxy");
if(!no_proxy)
no_proxy = curl_getenv("NO_PROXY");
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
(!data->set.str[STRING_NOPROXY] &&
check_noproxy(conn->host.name, no_proxy))) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
else if(!proxy && !socksproxy)
#ifndef CURL_DISABLE_HTTP
/* if the host is not in the noproxy list, detect proxy. */
proxy = detect_proxy(conn);
#else /* !CURL_DISABLE_HTTP */
proxy = NULL;
#endif /* CURL_DISABLE_HTTP */
Curl_safefree(no_proxy);
#ifdef USE_UNIX_SOCKETS
/* For the time being do not mix proxy and unix domain sockets. See #1274 */
if(proxy && conn->unix_domain_socket) {
free(proxy);
proxy = NULL;
}
#endif
if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
free(proxy); /* Don't bother with an empty proxy string or if the
protocol doesn't work with network */
proxy = NULL;
}
if(socksproxy && (!*socksproxy ||
(conn->handler->flags & PROTOPT_NONETWORK))) {
free(socksproxy); /* Don't bother with an empty socks proxy string or if
the protocol doesn't work with network */
socksproxy = NULL;
}
/***********************************************************************
* If this is supposed to use a proxy, we need to figure out the proxy host
* name, proxy type and port number, so that we can re-use an existing
* connection that may exist registered to the same proxy host.
***********************************************************************/
if(proxy || socksproxy) {
if(proxy) {
result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
if(result)
goto out;
}
if(socksproxy) {
result = parse_proxy(data, conn, socksproxy,
conn->socks_proxy.proxytype);
/* parse_proxy copies the socks proxy string */
Curl_safefree(socksproxy);
if(result)
goto out;
}
if(conn->http_proxy.host.rawalloc) {
#ifdef CURL_DISABLE_HTTP
/* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
result = CURLE_UNSUPPORTED_PROTOCOL;
goto out;
#else
/* force this connection's protocol to become HTTP if not already
compatible - if it isn't tunneling through */
if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
!conn->bits.tunnel_proxy)
conn->handler = &Curl_handler_http;
conn->bits.httpproxy = TRUE;
#endif
}
else {
conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
}
if(conn->socks_proxy.host.rawalloc) {
if(!conn->http_proxy.host.rawalloc) {
/* once a socks proxy */
if(!conn->socks_proxy.user) {
conn->socks_proxy.user = conn->http_proxy.user;
conn->http_proxy.user = NULL;
Curl_safefree(conn->socks_proxy.passwd);
conn->socks_proxy.passwd = conn->http_proxy.passwd;
conn->http_proxy.passwd = NULL;
}
}
conn->bits.socksproxy = TRUE;
}
else
conn->bits.socksproxy = FALSE; /* not a socks proxy */
}
else {
conn->bits.socksproxy = FALSE;
conn->bits.httpproxy = FALSE;
}
conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
if(!conn->bits.proxy) {
/* we aren't using the proxy after all... */
conn->bits.proxy = FALSE;
conn->bits.httpproxy = FALSE;
conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
}
out:
free(socksproxy);
free(proxy);
return result;
}
#endif /* CURL_DISABLE_PROXY */
/*
@ -6110,9 +6272,6 @@ static CURLcode create_conn(struct Curl_easy *data,
char *passwd = NULL;
char *options = NULL;
bool reuse;
char *proxy = NULL;
char *socksproxy = NULL;
char *no_proxy = NULL;
bool prot_missing = FALSE;
bool connections_available = TRUE;
bool force_reuse = FALSE;
@ -6267,154 +6426,14 @@ static CURLcode create_conn(struct Curl_easy *data,
}
#endif
/* After the unix socket init but before the proxy vars are used, parse and
initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
/*************************************************************
* Extract the user and password from the authentication string
*************************************************************/
if(conn->bits.proxy_user_passwd) {
result = parse_proxy_auth(data, conn);
if(result)
goto out;
}
/*************************************************************
* Detect what (if any) proxy to use
*************************************************************/
if(data->set.str[STRING_PROXY]) {
proxy = strdup(data->set.str[STRING_PROXY]);
/* if global proxy is set, this is it */
if(NULL == proxy) {
failf(data, "memory shortage");
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
if(data->set.str[STRING_PRE_PROXY]) {
socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
/* if global socks proxy is set, this is it */
if(NULL == socksproxy) {
failf(data, "memory shortage");
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
no_proxy = curl_getenv("no_proxy");
if(!no_proxy)
no_proxy = curl_getenv("NO_PROXY");
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
(!data->set.str[STRING_NOPROXY] &&
check_noproxy(conn->host.name, no_proxy))) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
else if(!proxy && !socksproxy)
#ifndef CURL_DISABLE_HTTP
/* if the host is not in the noproxy list, detect proxy. */
proxy = detect_proxy(conn);
#else /* !CURL_DISABLE_HTTP */
proxy = NULL;
#endif /* CURL_DISABLE_HTTP */
Curl_safefree(no_proxy);
#ifdef USE_UNIX_SOCKETS
/* For the time being do not mix proxy and unix domain sockets. See #1274 */
if(proxy && conn->unix_domain_socket) {
free(proxy);
proxy = NULL;
}
result = create_conn_helper_init_proxy(conn);
if(result)
goto out;
#endif
if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
free(proxy); /* Don't bother with an empty proxy string or if the
protocol doesn't work with network */
proxy = NULL;
}
if(socksproxy && (!*socksproxy ||
(conn->handler->flags & PROTOPT_NONETWORK))) {
free(socksproxy); /* Don't bother with an empty socks proxy string or if
the protocol doesn't work with network */
socksproxy = NULL;
}
/***********************************************************************
* If this is supposed to use a proxy, we need to figure out the proxy host
* name, proxy type and port number, so that we can re-use an existing
* connection that may exist registered to the same proxy host.
***********************************************************************/
if(proxy || socksproxy) {
if(proxy) {
result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
if(result)
goto out;
}
if(socksproxy) {
result = parse_proxy(data, conn, socksproxy,
conn->socks_proxy.proxytype);
/* parse_proxy copies the socks proxy string */
Curl_safefree(socksproxy);
if(result)
goto out;
}
if(conn->http_proxy.host.rawalloc) {
#ifdef CURL_DISABLE_HTTP
/* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
result = CURLE_UNSUPPORTED_PROTOCOL;
goto out;
#else
/* force this connection's protocol to become HTTP if not already
compatible - if it isn't tunneling through */
if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
!conn->bits.tunnel_proxy)
conn->handler = &Curl_handler_http;
conn->bits.httpproxy = TRUE;
#endif
}
else {
conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
}
if(conn->socks_proxy.host.rawalloc) {
if(!conn->http_proxy.host.rawalloc) {
/* once a socks proxy */
if(!conn->socks_proxy.user) {
conn->socks_proxy.user = conn->http_proxy.user;
conn->http_proxy.user = NULL;
Curl_safefree(conn->socks_proxy.passwd);
conn->socks_proxy.passwd = conn->http_proxy.passwd;
conn->http_proxy.passwd = NULL;
}
}
conn->bits.socksproxy = TRUE;
}
else
conn->bits.socksproxy = FALSE; /* not a socks proxy */
}
else {
conn->bits.socksproxy = FALSE;
conn->bits.httpproxy = FALSE;
}
conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
if(!conn->bits.proxy) {
/* we aren't using the proxy after all... */
conn->bits.proxy = FALSE;
conn->bits.httpproxy = FALSE;
conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
}
#endif /* CURL_DISABLE_PROXY */
/*************************************************************
* If the protocol is using SSL and HTTP proxy is used, we set
* the tunnel_proxy bit.
@ -6775,13 +6794,11 @@ static CURLcode create_conn(struct Curl_easy *data,
*************************************************************/
result = resolve_server(data, conn, async);
out:
out:
free(options);
free(passwd);
free(user);
free(socksproxy);
free(proxy);
return result;
}