summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/url.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-02-07 16:38:00 (GMT)
committerBrad King <brad.king@kitware.com>2017-02-07 16:38:00 (GMT)
commit1df9d5f91944e0b5ba00815d55bb7dc545053b4c (patch)
tree7f3ac8bf78c485cd3254a16754657bd5d43bd561 /Utilities/cmcurl/lib/url.c
parentf4a3290ae7ae096f8b92f7adfba7088e6918bc0b (diff)
parent4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab (diff)
downloadCMake-1df9d5f91944e0b5ba00815d55bb7dc545053b4c.zip
CMake-1df9d5f91944e0b5ba00815d55bb7dc545053b4c.tar.gz
CMake-1df9d5f91944e0b5ba00815d55bb7dc545053b4c.tar.bz2
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2016-12-22 (44b9b4d4)
Diffstat (limited to 'Utilities/cmcurl/lib/url.c')
-rw-r--r--Utilities/cmcurl/lib/url.c925
1 files changed, 656 insertions, 269 deletions
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index b997f41..7944d7b 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "warnless.h"
#include "non-ascii.h"
#include "inet_pton.h"
+#include "getinfo.h"
/* And now for the protocols */
#include "ftp.h"
@@ -463,6 +464,7 @@ CURLcode Curl_close(struct Curl_easy *data)
/* this destroys the channel and we cannot use it anymore after this */
Curl_resolver_cleanup(data->state.resolver);
+ Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data);
/* No longer a dirty share, if it exists */
@@ -525,9 +527,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* Set the default size of the SSL session ID cache */
- set->ssl.max_ssl_sessions = 5;
+ set->general_ssl.max_ssl_sessions = 5;
- set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
+ set->proxyport = 0;
set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
@@ -539,14 +541,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
*/
- set->ssl.verifypeer = TRUE;
- set->ssl.verifyhost = TRUE;
+ set->ssl.primary.verifypeer = TRUE;
+ set->ssl.primary.verifyhost = TRUE;
#ifdef USE_TLS_SRP
set->ssl.authtype = CURL_TLSAUTH_NONE;
#endif
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
type */
- set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+ set->general_ssl.sessionid = TRUE; /* session ID caching enabled by
+ default */
+ set->proxy_ssl = set->ssl;
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
@@ -569,14 +573,17 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
/* This is our preferred CA cert bundle/path since install time */
#if defined(CURL_CA_BUNDLE)
- result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
+ result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
if(result)
return result;
#endif
#if defined(CURL_CA_PATH)
- result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
+ result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
if(result)
return result;
+
+ result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
+ (char *) CURL_CA_PATH);
#endif
set->wildcardmatch = FALSE;
@@ -646,6 +653,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
Curl_convert_init(data);
+ Curl_initinfo(data);
+
/* most recent connection is not yet defined */
data->state.lastconnect = NULL;
@@ -694,7 +703,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
- result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSL_CIPHER_LIST:
+ /* set a list of cipher we want to use in the SSL connection for proxy */
+ result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
va_arg(param, char *));
break;
@@ -900,7 +914,18 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* implementations are lame.
*/
#ifdef USE_SSL
- data->set.ssl.version = va_arg(param, long);
+ data->set.ssl.primary.version = va_arg(param, long);
+#else
+ result = CURLE_UNKNOWN_OPTION;
+#endif
+ break;
+ case CURLOPT_PROXY_SSLVERSION:
+ /*
+ * Set explicit SSL version to try to connect with for proxy, as some SSL
+ * implementations are lame.
+ */
+#ifdef USE_SSL
+ data->set.proxy_ssl.primary.version = va_arg(param, long);
#else
result = CURLE_UNKNOWN_OPTION;
#endif
@@ -1007,7 +1032,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
(data->set.postfieldsize > (curl_off_t)((size_t)-1))))
result = CURLE_OUT_OF_MEMORY;
else {
- char * p;
+ char *p;
(void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
@@ -1434,18 +1459,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_PROXY:
/*
- * Set proxy server:port to use as HTTP proxy.
+ * Set proxy server:port to use as proxy.
*
- * If the proxy is set to "" we explicitly say that we don't want to use a
- * proxy (even though there might be environment variables saying so).
+ * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+ * we explicitly say that we don't want to use a proxy
+ * (even though there might be environment variables saying so).
*
* Setting it to NULL, means no proxy but allows the environment variables
- * to decide for us.
+ * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
*/
result = setstropt(&data->set.str[STRING_PROXY],
va_arg(param, char *));
break;
+ case CURLOPT_PRE_PROXY:
+ /*
+ * Set proxy server:port to use as SOCKS proxy.
+ *
+ * If the proxy is set to "" or NULL we explicitly say that we don't want
+ * to use the socks proxy.
+ */
+ result = setstropt(&data->set.str[STRING_PRE_PROXY],
+ va_arg(param, char *));
+ break;
+
case CURLOPT_PROXYTYPE:
/*
* Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1457,7 +1494,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
*/
- switch (va_arg(param, long)) {
+ switch(va_arg(param, long)) {
case 0:
data->set.proxy_transfer_mode = FALSE;
break;
@@ -1910,35 +1947,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* String that holds file name of the SSL certificate to use
*/
- result = setstropt(&data->set.str[STRING_CERT],
+ result = setstropt(&data->set.str[STRING_CERT_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERT:
+ /*
+ * String that holds file name of the SSL certificate to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_CERT_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLCERTTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
- result = setstropt(&data->set.str[STRING_CERT_TYPE],
+ result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLCERTTYPE:
+ /*
+ * String that holds file type of the SSL certificate to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEY:
/*
* String that holds file name of the SSL key to use
*/
- result = setstropt(&data->set.str[STRING_KEY],
+ result = setstropt(&data->set.str[STRING_KEY_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEY:
+ /*
+ * String that holds file name of the SSL key to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLKEYTYPE:
/*
* String that holds file type of the SSL key to use
*/
- result = setstropt(&data->set.str[STRING_KEY_TYPE],
+ result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_SSLKEYTYPE:
+ /*
+ * String that holds file type of the SSL key to use for proxy
+ */
+ result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_KEYPASSWD:
/*
* String that holds the SSL or SSH private key password.
*/
- result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_KEYPASSWD:
+ /*
+ * String that holds the SSL private key password for proxy.
+ */
+ result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
va_arg(param, char *));
break;
case CURLOPT_SSLENGINE:
@@ -2001,7 +2073,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* Enable peer SSL verifying.
*/
- data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYPEER:
+ /*
+ * Enable peer SSL verifying for proxy.
+ */
+ data->set.proxy_ssl.primary.verifypeer =
+ (0 != va_arg(param, long))?TRUE:FALSE;
break;
case CURLOPT_SSL_VERIFYHOST:
/*
@@ -2019,7 +2099,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
+ data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+ break;
+ case CURLOPT_PROXY_SSL_VERIFYHOST:
+ /*
+ * Enable verification of the host name in the peer certificate for proxy
+ */
+ arg = va_arg(param, long);
+
+ /* Obviously people are not reading documentation and too many thought
+ this argument took a boolean when it wasn't and misused it. We thus ban
+ 1 as a sensible input and we warn about its use. Then we only have the
+ 2 action internally stored as TRUE. */
+
+ if(1 == arg) {
+ failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
break;
case CURLOPT_SSL_VERIFYSTATUS:
/*
@@ -2030,7 +2128,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
}
- data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
break;
case CURLOPT_SSL_CTX_FUNCTION:
#ifdef have_curlssl_ssl_ctx
@@ -2076,7 +2175,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set pinned public key for SSL connection.
* Specify file name of the public key in DER format.
*/
- result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+ va_arg(param, char *));
+#else
+ result = CURLE_NOT_BUILT_IN;
+#endif
+ break;
+ case CURLOPT_PROXY_PINNEDPUBLICKEY:
+#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
+ /*
+ * Set pinned public key for SSL connection.
+ * Specify file name of the public key in DER format.
+ */
+ result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
#else
result = CURLE_NOT_BUILT_IN;
@@ -2086,7 +2197,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
- result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CAINFO:
+ /*
+ * Set CA info SSL connection for proxy. Specify file name of the
+ * CA certificate
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_CAPATH:
@@ -2096,7 +2215,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* certificates which have been prepared using openssl c_rehash utility.
*/
/* This does not work on windows. */
- result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CAPATH:
+ /*
+ * Set CA path info for SSL connection proxy. Specify directory name of the
+ * CA certificates which have been prepared using openssl c_rehash utility.
+ */
+ /* This does not work on windows. */
+ result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
#else
result = CURLE_NOT_BUILT_IN;
@@ -2107,7 +2235,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set CRL file info for SSL connection. Specify file name of the CRL
* to check certificates revocation
*/
- result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_CRLFILE:
+ /*
+ * Set CRL file info for SSL connection for proxy. Specify file name of the
+ * CRL to check certificates revocation
+ */
+ result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
va_arg(param, char *));
break;
case CURLOPT_ISSUERCERT:
@@ -2115,7 +2251,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* Set Issuer certificate file
* to check certificates issuer
*/
- result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+ result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
va_arg(param, char *));
break;
case CURLOPT_TELNETOPTIONS:
@@ -2196,7 +2332,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
}
#endif /* CURL_DISABLE_HTTP */
if(data->share->sslsession) {
- data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+ data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
data->state.session = data->share->sslsession;
}
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2231,8 +2367,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSL_OPTIONS:
arg = va_arg(param, long);
- data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
- data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ break;
+
+ case CURLOPT_PROXY_SSL_OPTIONS:
+ arg = va_arg(param, long);
+ data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+ data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
break;
#endif
@@ -2328,7 +2470,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
break;
#ifdef USE_LIBSSH2
@@ -2595,23 +2738,43 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
break;
#ifdef USE_TLS_SRP
case CURLOPT_TLSAUTH_USERNAME:
- result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+ case CURLOPT_PROXY_TLSAUTH_USERNAME:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
case CURLOPT_TLSAUTH_PASSWORD:
- result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
va_arg(param, char *));
- if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+ if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
+ case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+ result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+ va_arg(param, char *));
+ if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+ !data->set.proxy_ssl.authtype)
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+ break;
case CURLOPT_TLSAUTH_TYPE:
if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
data->set.ssl.authtype = CURL_TLSAUTH_SRP;
else
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
break;
+ case CURLOPT_PROXY_TLSAUTH_TYPE:
+ if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+ else
+ data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+ break;
#endif
case CURLOPT_DNS_SERVERS:
result = Curl_set_dns_servers(data, va_arg(param, char *));
@@ -2678,9 +2841,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
return CURLE_NOT_BUILT_IN;
#else
struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
- if(dep && GOOD_EASY_HANDLE(dep)) {
- data->set.stream_depends_on = dep;
- data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
+ if(!dep || GOOD_EASY_HANDLE(dep)) {
+ if(data->set.stream_depends_on) {
+ Curl_http2_remove_child(data->set.stream_depends_on, data);
+ }
+ Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
}
break;
#endif
@@ -2718,10 +2883,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num)
#endif /* DEBUGBUILD */
}
else {
- DEBUGASSERT (psnd->allocated_size == 0);
- DEBUGASSERT (psnd->recv_size == 0);
- DEBUGASSERT (psnd->recv_processed == 0);
- DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
+ DEBUGASSERT(psnd->allocated_size == 0);
+ DEBUGASSERT(psnd->recv_size == 0);
+ DEBUGASSERT(psnd->recv_processed == 0);
+ DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
}
}
@@ -2768,8 +2933,10 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->passwd);
Curl_safefree(conn->oauth_bearer);
Curl_safefree(conn->options);
- Curl_safefree(conn->proxyuser);
- Curl_safefree(conn->proxypasswd);
+ Curl_safefree(conn->http_proxy.user);
+ Curl_safefree(conn->socks_proxy.user);
+ Curl_safefree(conn->http_proxy.passwd);
+ Curl_safefree(conn->socks_proxy.passwd);
Curl_safefree(conn->allocptr.proxyuserpwd);
Curl_safefree(conn->allocptr.uagent);
Curl_safefree(conn->allocptr.userpwd);
@@ -2783,7 +2950,9 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
- Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+ Curl_safefree(conn->secondaryhostname);
+ Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
+ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
Curl_safefree(conn->master_buffer);
conn_reset_all_postponed_data(conn);
@@ -2795,7 +2964,12 @@ static void conn_free(struct connectdata *conn)
conn->recv_pipe = NULL;
Curl_safefree(conn->localdev);
- Curl_free_ssl_config(&conn->ssl_config);
+ Curl_free_primary_ssl_config(&conn->ssl_config);
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+
+#ifdef USE_UNIX_SOCKETS
+ Curl_safefree(conn->unix_domain_socket);
+#endif
free(conn); /* free all the connection oriented data */
}
@@ -2856,6 +3030,8 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
free_fixed_hostname(&conn->host);
free_fixed_hostname(&conn->conn_to_host);
free_fixed_hostname(&conn->proxy);
+ free_fixed_hostname(&conn->http_proxy.host);
+ free_fixed_hostname(&conn->socks_proxy.host);
Curl_ssl_close(conn, FIRSTSOCKET);
@@ -3014,8 +3190,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
struct curl_hash_iterator iter;
struct curl_llist_element *curr;
struct curl_hash_element *he;
- long highscore=-1;
- long score;
+ time_t highscore=-1;
+ time_t score;
struct timeval now;
struct connectdata *conn_candidate = NULL;
struct connectbundle *bundle;
@@ -3052,6 +3228,21 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
return conn_candidate;
}
+static bool
+proxy_info_matches(const struct proxy_info* data,
+ const struct proxy_info* needle)
+{
+ if((data->proxytype == needle->proxytype) &&
+ (data->port == needle->port) &&
+ Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
+ Curl_safe_strcasecompare(data->user, needle->user) &&
+ Curl_safe_strcasecompare(data->passwd, needle->passwd))
+ return TRUE;
+
+ return FALSE;
+}
+
+
/*
* This function finds the connection in the connection
* bundle that has been unused for the longest time.
@@ -3064,8 +3255,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
struct curl_llist_element *curr;
- long highscore=-1;
- long score;
+ time_t highscore=-1;
+ time_t score;
struct timeval now;
struct connectdata *conn_candidate = NULL;
struct connectdata *conn;
@@ -3147,7 +3338,7 @@ static int call_disconnect_if_dead(struct connectdata *conn,
static void prune_dead_connections(struct Curl_easy *data)
{
struct timeval now = Curl_tvnow();
- long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+ time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
if(elapsed >= 1000L) {
Curl_conncache_foreach(data->state.conn_cache, data,
@@ -3326,6 +3517,17 @@ ConnectionExists(struct Curl_easy *data,
}
}
+#ifdef USE_UNIX_SOCKETS
+ if(needle->unix_domain_socket) {
+ if(!check->unix_domain_socket)
+ continue;
+ if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
+ continue;
+ }
+ else if(check->unix_domain_socket)
+ continue;
+#endif
+
if((needle->handler->flags&PROTOPT_SSL) !=
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
@@ -3334,23 +3536,12 @@ ConnectionExists(struct Curl_easy *data,
/* except protocols that have been upgraded via TLS */
continue;
- if(needle->handler->flags&PROTOPT_SSL) {
- if((data->set.ssl.verifypeer != check->verifypeer) ||
- (data->set.ssl.verifyhost != check->verifyhost))
- continue;
- }
-
- if(needle->bits.proxy != check->bits.proxy)
- /* don't do mixed proxy and non-proxy connections */
+ if(needle->bits.httpproxy != check->bits.httpproxy ||
+ needle->bits.socksproxy != check->bits.socksproxy)
continue;
- if(needle->bits.proxy &&
- (needle->proxytype != check->proxytype ||
- needle->bits.httpproxy != check->bits.httpproxy ||
- needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
- !strcasecompare(needle->proxy.name, check->proxy.name) ||
- needle->port != check->port))
- /* don't mix connections that use different proxies */
+ if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
+ &check->socks_proxy))
continue;
if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -3363,6 +3554,33 @@ ConnectionExists(struct Curl_easy *data,
* connections that don't use this feature */
continue;
+ if(needle->bits.httpproxy) {
+ if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+ continue;
+
+ if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
+ continue;
+
+ if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ /* use https proxy */
+ if(needle->handler->flags&PROTOPT_SSL) {
+ /* use double layer ssl */
+ if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
+ &check->proxy_ssl_config))
+ continue;
+ if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
+ continue;
+ }
+ else {
+ if(!Curl_ssl_config_matches(&needle->ssl_config,
+ &check->ssl_config))
+ continue;
+ if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
+ continue;
+ }
+ }
+ }
+
if(!canPipeline && check->inuse)
/* this request can't be pipelined but the checked connection is
already in use so we skip it */
@@ -3382,9 +3600,8 @@ ConnectionExists(struct Curl_easy *data,
*/
if((check->localport != needle->localport) ||
(check->localportrange != needle->localportrange) ||
- !check->localdev ||
- !needle->localdev ||
- strcmp(check->localdev, needle->localdev))
+ (needle->localdev &&
+ (!check->localdev || strcmp(check->localdev, needle->localdev))))
continue;
}
@@ -3399,10 +3616,11 @@ ConnectionExists(struct Curl_easy *data,
}
if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
- (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
+ needle->bits.tunnel_proxy) {
/* The requested connection does not use a HTTP proxy or it uses SSL or
- it is a non-SSL protocol tunneled over the same HTTP proxy name and
- port number */
+ it is a non-SSL protocol tunneled or it is a non-SSL protocol which
+ is allowed to be upgraded via TLS */
+
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
(get_protocol_family(check->handler->protocol) ==
needle->handler->protocol && check->tls_upgraded)) &&
@@ -3463,12 +3681,13 @@ ConnectionExists(struct Curl_easy *data,
/* Same for Proxy NTLM authentication */
if(wantProxyNTLMhttp) {
- /* Both check->proxyuser and check->proxypasswd can be NULL */
- if(!check->proxyuser || !check->proxypasswd)
+ /* Both check->http_proxy.user and check->http_proxy.passwd can be
+ * NULL */
+ if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(strcmp(needle->proxyuser, check->proxyuser) ||
- strcmp(needle->proxypasswd, check->proxypasswd))
+ if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
+ strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
continue;
}
else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3572,51 +3791,48 @@ ConnectionExists(struct Curl_easy *data,
Note: this function's sub-functions call failf()
*/
-CURLcode Curl_connected_proxy(struct connectdata *conn,
- int sockindex)
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
{
- if(!conn->bits.proxy || sockindex)
- /* this magic only works for the primary socket as the secondary is used
- for FTP only and it has FTP specific magic in ftp.c */
- return CURLE_OK;
+ CURLcode result = CURLE_OK;
- switch(conn->proxytype) {
+ if(conn->bits.socksproxy) {
#ifndef CURL_DISABLE_PROXY
- case CURLPROXY_SOCKS5:
- case CURLPROXY_SOCKS5_HOSTNAME:
- return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn);
-
- case CURLPROXY_SOCKS4:
- return Curl_SOCKS4(conn->proxyuser,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn, FALSE);
-
- case CURLPROXY_SOCKS4A:
- return Curl_SOCKS4(conn->proxyuser,
- conn->bits.conn_to_host ? conn->conn_to_host.name :
- conn->host.name,
- conn->bits.conn_to_port ? conn->conn_to_port :
- conn->remote_port,
- FIRSTSOCKET, conn, TRUE);
+ const char * const host = conn->bits.conn_to_host ?
+ conn->conn_to_host.name :
+ conn->bits.httpproxy ?
+ conn->http_proxy.host.name :
+ sockindex == SECONDARYSOCKET ?
+ conn->secondaryhostname : conn->host.name;
+ const int port = conn->bits.conn_to_port ? conn->conn_to_port :
+ conn->bits.httpproxy ?
+ (int)conn->http_proxy.port :
+ sockindex == SECONDARYSOCKET ?
+ conn->secondary_port : conn->remote_port;
+ conn->bits.socksproxy_connecting = TRUE;
+ switch(conn->socks_proxy.proxytype) {
+ case CURLPROXY_SOCKS5:
+ case CURLPROXY_SOCKS5_HOSTNAME:
+ result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+ host, port, sockindex, conn);
+ break;
+ case CURLPROXY_SOCKS4:
+ case CURLPROXY_SOCKS4A:
+ result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+ conn);
+ break;
+
+ default:
+ failf(conn->data, "unknown proxytype option given");
+ result = CURLE_COULDNT_CONNECT;
+ } /* switch proxytype */
+ conn->bits.socksproxy_connecting = FALSE;
+#else
+ (void)sockindex;
#endif /* CURL_DISABLE_PROXY */
- case CURLPROXY_HTTP:
- case CURLPROXY_HTTP_1_0:
- /* do nothing here. handled later. */
- break;
- default:
- break;
- } /* switch proxytype */
+ }
- return CURLE_OK;
+ return result;
}
/*
@@ -3627,7 +3843,9 @@ void Curl_verboseconnect(struct connectdata *conn)
{
if(conn->data->set.verbose)
infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
- conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+ conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+ conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+ conn->host.dispname,
conn->ip_addr_str, conn->port, conn->connection_id);
}
#endif
@@ -3717,10 +3935,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
if(!conn->bits.protoconnstart) {
- result = Curl_proxy_connect(conn);
+ result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
return result;
+ if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+ /* wait for HTTPS proxy SSL initialization to complete */
+ return CURLE_OK;
+
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
(conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
/* when using an HTTP tunnel proxy, await complete tunnel establishment
@@ -3750,7 +3972,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
*/
static bool is_ASCII_name(const char *hostname)
{
- const unsigned char *ch = (const unsigned char*)hostname;
+ const unsigned char *ch = (const unsigned char *)hostname;
while(*ch) {
if(*ch++ & 0x80)
@@ -3879,12 +4101,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
- conn->proxytype = data->set.proxytype; /* type */
+ conn->http_proxy.proxytype = data->set.proxytype;
+ conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
#ifdef CURL_DISABLE_PROXY
conn->bits.proxy = FALSE;
conn->bits.httpproxy = FALSE;
+ conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
@@ -3895,11 +4119,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.proxy = (data->set.str[STRING_PROXY] &&
*data->set.str[STRING_PROXY]) ? TRUE : FALSE;
conn->bits.httpproxy = (conn->bits.proxy &&
- (conn->proxytype == CURLPROXY_HTTP ||
- conn->proxytype == CURLPROXY_HTTP_1_0)) ?
- TRUE : FALSE;
- conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
- TRUE : FALSE;
+ (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
+ conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
+ conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
+ TRUE : FALSE;
+ conn->bits.socksproxy = (conn->bits.proxy &&
+ !conn->bits.httpproxy) ? TRUE : FALSE;
+
+ if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
+ conn->bits.proxy = TRUE;
+ conn->bits.socksproxy = TRUE;
+ }
+
+ conn->bits.proxy_user_passwd =
+ (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
#endif /* CURL_DISABLE_PROXY */
@@ -3908,8 +4141,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
- conn->verifypeer = data->set.ssl.verifypeer;
- conn->verifyhost = data->set.ssl.verifyhost;
+ conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
+ conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+ conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
+ conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
conn->ip_version = data->set.ipver;
@@ -3924,7 +4159,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
!conn->master_buffer) {
/* Allocate master_buffer to be used for HTTP/1 pipelining */
- conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+ conn->master_buffer = calloc(BUFSIZE, sizeof(char));
if(!conn->master_buffer)
goto error;
}
@@ -4065,33 +4300,38 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* the URL protocols specified in RFC 1738
*/
if(path[0] != '/') {
- /* the URL included a host name, we ignore host names in file:// URLs
- as the standards don't define what to do with them */
- char *ptr=strchr(path, '/');
- if(ptr) {
- /* there was a slash present
-
- RFC1738 (section 3.1, page 5) says:
-
- The rest of the locator consists of data specific to the scheme,
- and is known as the "url-path". It supplies the details of how the
- specified resource can be accessed. Note that the "/" between the
- host (or port) and the url-path is NOT part of the url-path.
-
- As most agents use file://localhost/foo to get '/foo' although the
- slash preceding foo is a separator and not a slash for the path,
- a URL as file://localhost//foo must be valid as well, to refer to
- the same file with an absolute path.
- */
+ /* the URL includes a host name, it must match "localhost" or
+ "127.0.0.1" to be valid */
+ char *ptr;
+ if(!checkprefix("localhost/", path) &&
+ !checkprefix("127.0.0.1/", path)) {
+ failf(data, "Valid host name with slash missing in URL");
+ return CURLE_URL_MALFORMAT;
+ }
+ ptr = &path[9]; /* now points to the slash after the host */
- if(ptr[1] && ('/' == ptr[1]))
- /* if there was two slashes, we skip the first one as that is then
- used truly as a separator */
- ptr++;
+ /* there was a host name and slash present
- /* This cannot be made with strcpy, as the memory chunks overlap! */
- memmove(path, ptr, strlen(ptr)+1);
- }
+ RFC1738 (section 3.1, page 5) says:
+
+ The rest of the locator consists of data specific to the scheme,
+ and is known as the "url-path". It supplies the details of how the
+ specified resource can be accessed. Note that the "/" between the
+ host (or port) and the url-path is NOT part of the url-path.
+
+ As most agents use file://localhost/foo to get '/foo' although the
+ slash preceding foo is a separator and not a slash for the path,
+ a URL as file://localhost//foo must be valid as well, to refer to
+ the same file with an absolute path.
+ */
+
+ if('/' == ptr[1])
+ /* if there was two slashes, we skip the first one as that is then
+ used truly as a separator */
+ ptr++;
+
+ /* This cannot be made with strcpy, as the memory chunks overlap! */
+ memmove(path, ptr, strlen(ptr)+1);
}
protop = "file"; /* protocol string */
@@ -4473,7 +4713,7 @@ void Curl_free_request_state(struct Curl_easy *data)
* Checks if the host is in the noproxy list. returns true if it matches
* and therefore the proxy should NOT be used.
****************************************************************/
-static bool check_noproxy(const char* name, const char* no_proxy)
+static bool check_noproxy(const char *name, const char *no_proxy)
{
/* no_proxy=domain1.dom,host.domain2.dom
* (a comma-separated list of hosts which should
@@ -4482,7 +4722,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
*/
size_t tok_start;
size_t tok_end;
- const char* separator = ", ";
+ const char *separator = ", ";
size_t no_proxy_len;
size_t namelen;
char *endptr;
@@ -4636,7 +4876,8 @@ static char *detect_proxy(struct connectdata *conn)
* that may exist registered to the same proxy host.
*/
static CURLcode parse_proxy(struct Curl_easy *data,
- struct connectdata *conn, char *proxy)
+ struct connectdata *conn, char *proxy,
+ curl_proxytype proxytype)
{
char *prox_portno;
char *endofprot;
@@ -4645,6 +4886,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
char *proxyptr;
char *portptr;
char *atsign;
+ long port = -1;
+ char *proxyuser = NULL;
+ char *proxypasswd = NULL;
+ bool sockstype;
/* We do the proxy host string parsing here. We want the host name and the
* port name. Accept a protocol:// prefix
@@ -4654,14 +4899,16 @@ static CURLcode parse_proxy(struct Curl_easy *data,
endofprot = strstr(proxy, "://");
if(endofprot) {
proxyptr = endofprot+3;
- if(checkprefix("socks5h", proxy))
- conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+ if(checkprefix("https", proxy))
+ proxytype = CURLPROXY_HTTPS;
+ else if(checkprefix("socks5h", proxy))
+ proxytype = CURLPROXY_SOCKS5_HOSTNAME;
else if(checkprefix("socks5", proxy))
- conn->proxytype = CURLPROXY_SOCKS5;
+ proxytype = CURLPROXY_SOCKS5;
else if(checkprefix("socks4a", proxy))
- conn->proxytype = CURLPROXY_SOCKS4A;
+ proxytype = CURLPROXY_SOCKS4A;
else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
- conn->proxytype = CURLPROXY_SOCKS4;
+ proxytype = CURLPROXY_SOCKS4;
else if(checkprefix("http:", proxy))
; /* leave it as HTTP or HTTP/1.0 */
else {
@@ -4673,54 +4920,28 @@ static CURLcode parse_proxy(struct Curl_easy *data,
else
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
+#ifndef HTTPS_PROXY_SUPPORT
+ if(proxytype == CURLPROXY_HTTPS) {
+ failf(data, "Unsupported proxy \'%s\'"
+ ", libcurl is built without the HTTPS-proxy support.", proxy);
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
+
+ sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+ proxytype == CURLPROXY_SOCKS5 ||
+ proxytype == CURLPROXY_SOCKS4A ||
+ proxytype == CURLPROXY_SOCKS4;
+
/* Is there a username and password given in this proxy url? */
atsign = strchr(proxyptr, '@');
if(atsign) {
- char *proxyuser = NULL;
- char *proxypasswd = NULL;
CURLcode result =
parse_login_details(proxyptr, atsign - proxyptr,
- &proxyuser, &proxypasswd, NULL);
- if(!result) {
- /* found user and password, rip them out. note that we are
- unescaping them, as there is otherwise no way to have a
- username or password with reserved characters like ':' in
- them. */
- Curl_safefree(conn->proxyuser);
- if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
- result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
- FALSE);
- else {
- conn->proxyuser = strdup("");
- if(!conn->proxyuser)
- result = CURLE_OUT_OF_MEMORY;
- }
-
- if(!result) {
- Curl_safefree(conn->proxypasswd);
- if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
- result = Curl_urldecode(data, proxypasswd, 0,
- &conn->proxypasswd, NULL, FALSE);
- else {
- conn->proxypasswd = strdup("");
- if(!conn->proxypasswd)
- result = CURLE_OUT_OF_MEMORY;
- }
- }
-
- if(!result) {
- conn->bits.proxy_user_passwd = TRUE; /* enable it */
- atsign++; /* the right side of the @-letter */
-
- proxyptr = atsign; /* now use this instead */
- }
- }
-
- free(proxyuser);
- free(proxypasswd);
-
+ &proxyuser, &proxypasswd, NULL);
if(result)
return result;
+ proxyptr = atsign + 1;
}
/* start scanning for port number at this point */
@@ -4757,7 +4978,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
prox_portno = strchr(portptr, ':');
if(prox_portno) {
char *endp = NULL;
- long port = 0;
+
*prox_portno = 0x0; /* cut off number from host name */
prox_portno ++;
/* now set the local port number */
@@ -4791,15 +5012,59 @@ static CURLcode parse_proxy(struct Curl_easy *data,
if(data->set.proxyport)
/* None given in the proxy string, then get the default one if it is
given */
- conn->port = data->set.proxyport;
+ port = data->set.proxyport;
+ else {
+ if(proxytype == CURLPROXY_HTTPS)
+ port = CURL_DEFAULT_HTTPS_PROXY_PORT;
+ else
+ port = CURL_DEFAULT_PROXY_PORT;
+ }
}
- /* now, clone the cleaned proxy host name */
- conn->proxy.rawalloc = strdup(proxyptr);
- conn->proxy.name = conn->proxy.rawalloc;
+ if(*proxyptr) {
+ struct proxy_info *proxyinfo =
+ sockstype ? &conn->socks_proxy : &conn->http_proxy;
+ proxyinfo->proxytype = proxytype;
- if(!conn->proxy.rawalloc)
- return CURLE_OUT_OF_MEMORY;
+ if(proxyuser) {
+ /* found user and password, rip them out. note that we are unescaping
+ them, as there is otherwise no way to have a username or password
+ with reserved characters like ':' in them. */
+ Curl_safefree(proxyinfo->user);
+ proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
+
+ if(!proxyinfo->user)
+ return CURLE_OUT_OF_MEMORY;
+
+ Curl_safefree(proxyinfo->passwd);
+ if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+ proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+ else
+ proxyinfo->passwd = strdup("");
+
+ if(!proxyinfo->passwd)
+ return CURLE_OUT_OF_MEMORY;
+
+ conn->bits.proxy_user_passwd = TRUE; /* enable it */
+ }
+
+ if(port >= 0) {
+ proxyinfo->port = port;
+ if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
+ conn->port = port;
+ }
+
+ /* now, clone the cleaned proxy host name */
+ Curl_safefree(proxyinfo->host.rawalloc);
+ proxyinfo->host.rawalloc = strdup(proxyptr);
+ proxyinfo->host.name = proxyinfo->host.rawalloc;
+
+ if(!proxyinfo->host.rawalloc)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(proxyuser);
+ Curl_safefree(proxypasswd);
return CURLE_OK;
}
@@ -4825,10 +5090,11 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
}
- result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
+ result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+ FALSE);
if(!result)
- result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
- FALSE);
+ result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
+ NULL, FALSE);
return result;
}
#endif /* CURL_DISABLE_PROXY */
@@ -5180,11 +5446,16 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
*portptr = '\0'; /* cut off the name there */
conn->remote_port = curlx_ultous(port);
}
- else
+ else {
+ if(rest[0]) {
+ failf(data, "Illegal port number");
+ return CURLE_URL_MALFORMAT;
+ }
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
use the default port. Firefox and Chrome both do that. */
*portptr = '\0';
+ }
}
/* only if remote_port was not already parsed off the URL we use the
@@ -5404,6 +5675,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
int host_match = FALSE;
int port_match = FALSE;
+ *host_result = NULL;
+ *port_result = -1;
+
if(*ptr == ':') {
/* an empty hostname always matches */
host_match = TRUE;
@@ -5466,9 +5740,9 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
char *host = NULL;
- int port = 0;
+ int port = -1;
- while(conn_to_host && !host) {
+ while(conn_to_host && !host && port == -1) {
result = parse_connect_to_string(data, conn, conn_to_host->data,
&host, &port);
if(result)
@@ -5487,7 +5761,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
else {
/* no "connect to host" */
conn->bits.conn_to_host = FALSE;
- free(host);
+ Curl_safefree(host);
}
if(port >= 0) {
@@ -5498,6 +5772,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
else {
/* no "connect to port" */
conn->bits.conn_to_port = FALSE;
+ port = -1;
}
conn_to_host = conn_to_host->next;
@@ -5514,7 +5789,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
bool *async)
{
CURLcode result=CURLE_OK;
- long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
/*************************************************************
* Resolve the name of the server or proxy
@@ -5531,32 +5806,36 @@ static CURLcode resolve_server(struct Curl_easy *data,
struct Curl_dns_entry *hostaddr;
#ifdef USE_UNIX_SOCKETS
- if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ if(conn->unix_domain_socket) {
/* Unix domain sockets are local. The host gets ignored, just use the
* specified domain socket address. Do not cache "DNS entries". There is
* no DNS involved and we already have the filesystem path available */
- const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+ const char *path = conn->unix_domain_socket;
hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
if(!hostaddr)
result = CURLE_OUT_OF_MEMORY;
- else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
- hostaddr->inuse++;
else {
- /* Long paths are not supported for now */
- if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
- failf(data, "Unix socket path too long: '%s'", path);
- result = CURLE_COULDNT_RESOLVE_HOST;
+ int longpath=0;
+ hostaddr->addr = Curl_unix2addr(path, &longpath);
+ if(hostaddr->addr)
+ hostaddr->inuse++;
+ else {
+ /* Long paths are not supported for now */
+ if(longpath) {
+ failf(data, "Unix socket path too long: '%s'", path);
+ result = CURLE_COULDNT_RESOLVE_HOST;
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(hostaddr);
+ hostaddr = NULL;
}
- else
- result = CURLE_OUT_OF_MEMORY;
- free(hostaddr);
- hostaddr = NULL;
}
}
else
#endif
- if(!conn->proxy.name || !*conn->proxy.name) {
+ if(!conn->bits.proxy) {
struct hostname *connhost;
if(conn->bits.conn_to_host)
connhost = &conn->conn_to_host;
@@ -5588,8 +5867,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
else {
/* This is a proxy that hasn't been resolved yet. */
+ struct hostname * const host = conn->bits.socksproxy ?
+ &conn->socks_proxy.host : &conn->http_proxy.host;
+
/* resolve proxy */
- rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+ rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
@@ -5599,7 +5881,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
result = CURLE_OPERATION_TIMEDOUT;
else if(!hostaddr) {
- failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+ failf(data, "Couldn't resolve proxy '%s'", host->dispname);
result = CURLE_COULDNT_RESOLVE_PROXY;
/* don't return yet, we need to clean up the timeout first */
}
@@ -5619,12 +5901,18 @@ static CURLcode resolve_server(struct Curl_easy *data,
static void reuse_conn(struct connectdata *old_conn,
struct connectdata *conn)
{
+ free_fixed_hostname(&old_conn->http_proxy.host);
+ free_fixed_hostname(&old_conn->socks_proxy.host);
free_fixed_hostname(&old_conn->proxy);
+
+ free(old_conn->http_proxy.host.rawalloc);
+ free(old_conn->socks_proxy.host.rawalloc);
free(old_conn->proxy.rawalloc);
/* free the SSL config struct from this connection struct as this was
allocated in vain and is targeted for destruction */
- Curl_free_ssl_config(&old_conn->ssl_config);
+ Curl_free_primary_ssl_config(&old_conn->ssl_config);
+ Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
conn->data = old_conn->data;
@@ -5644,12 +5932,18 @@ static void reuse_conn(struct connectdata *old_conn,
conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
if(conn->bits.proxy_user_passwd) {
/* use the new proxy user name and proxy password though */
- Curl_safefree(conn->proxyuser);
- Curl_safefree(conn->proxypasswd);
- conn->proxyuser = old_conn->proxyuser;
- conn->proxypasswd = old_conn->proxypasswd;
- old_conn->proxyuser = NULL;
- old_conn->proxypasswd = NULL;
+ Curl_safefree(conn->http_proxy.user);
+ Curl_safefree(conn->socks_proxy.user);
+ Curl_safefree(conn->http_proxy.passwd);
+ Curl_safefree(conn->socks_proxy.passwd);
+ conn->http_proxy.user = old_conn->http_proxy.user;
+ conn->socks_proxy.user = old_conn->socks_proxy.user;
+ conn->http_proxy.passwd = old_conn->http_proxy.passwd;
+ conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
+ old_conn->http_proxy.user = NULL;
+ old_conn->socks_proxy.user = NULL;
+ old_conn->http_proxy.passwd = NULL;
+ old_conn->socks_proxy.passwd = NULL;
}
/* host can change, when doing keepalive with a proxy or if the case is
@@ -5675,8 +5969,10 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->user);
Curl_safefree(old_conn->passwd);
- Curl_safefree(old_conn->proxyuser);
- Curl_safefree(old_conn->proxypasswd);
+ Curl_safefree(old_conn->http_proxy.user);
+ Curl_safefree(old_conn->socks_proxy.user);
+ Curl_safefree(old_conn->http_proxy.passwd);
+ Curl_safefree(old_conn->socks_proxy.passwd);
Curl_safefree(old_conn->localdev);
Curl_llist_destroy(old_conn->send_pipe, NULL);
@@ -5686,6 +5982,10 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->recv_pipe = NULL;
Curl_safefree(old_conn->master_buffer);
+
+#ifdef USE_UNIX_SOCKETS
+ Curl_safefree(old_conn->unix_domain_socket);
+#endif
}
/**
@@ -5717,6 +6017,7 @@ static CURLcode create_conn(struct Curl_easy *data,
char *options = NULL;
bool reuse;
char *proxy = NULL;
+ char *socksproxy = NULL;
bool prot_missing = FALSE;
bool connections_available = TRUE;
bool force_reuse = FALSE;
@@ -5883,18 +6184,35 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
+ 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;
+ }
+ }
+
if(data->set.str[STRING_NOPROXY] &&
check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
- free(proxy); /* proxy is in exception list */
- proxy = NULL;
+ Curl_safefree(proxy);
+ Curl_safefree(socksproxy);
}
- else if(!proxy)
+ else if(!proxy && !socksproxy)
proxy = detect_proxy(conn);
#ifdef USE_UNIX_SOCKETS
- if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
- free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
- proxy = NULL;
+ if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+ if(proxy) {
+ free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
+ proxy = NULL;
+ }
+ conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
+ if(conn->unix_domain_socket == NULL) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
}
#endif
@@ -5903,23 +6221,36 @@ static CURLcode create_conn(struct Curl_easy *data,
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) {
- result = parse_proxy(data, conn, proxy);
-
- free(proxy); /* parse_proxy copies the proxy string */
- proxy = NULL;
+ 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(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->proxytype == CURLPROXY_HTTP) ||
- (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+ 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;
@@ -5938,12 +6269,34 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
}
- conn->bits.proxy = TRUE;
+
+ 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;
}
@@ -6079,20 +6432,51 @@ static CURLcode create_conn(struct Curl_easy *data,
that will be freed as part of the Curl_easy struct, but all cloned
copies will be separately allocated.
*/
- data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
- data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
- data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
- data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
- data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
- data->set.ssl.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+ data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+ data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.proxy_ssl.primary.random_file =
+ data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
+ data->set.proxy_ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+ data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
+ data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
+ data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
+ data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+ data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
+ data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
+ data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
+ data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+ data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
#ifdef USE_TLS_SRP
- data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
- data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+ data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
+ data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+ data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
- if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+ if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
+ &conn->ssl_config)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
+ &conn->proxy_ssl_config)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -6149,7 +6533,9 @@ static CURLcode create_conn(struct Curl_easy *data,
infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
conn->connection_id,
conn->bits.proxy?"proxy":"host",
- conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+ conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
+ conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
+ conn->host.dispname);
}
else {
/* We have decided that we want a new connection. However, we may not
@@ -6280,6 +6666,7 @@ static CURLcode create_conn(struct Curl_easy *data,
free(options);
free(passwd);
free(user);
+ free(socksproxy);
free(proxy);
return result;
}