proxy: Support HTTPS proxy and SOCKS+HTTP(s)
HTTPS proxies: An HTTPS proxy receives all transactions over an SSL/TLS connection. Once a secure connection with the proxy is established, the user agent uses the proxy as usual, including sending CONNECT requests to instruct the proxy to establish a [usually secure] TCP tunnel with an origin server. HTTPS proxies protect nearly all aspects of user-proxy communications as opposed to HTTP proxies that receive all requests (including CONNECT requests) in vulnerable clear text. With HTTPS proxies, it is possible to have two concurrent _nested_ SSL/TLS sessions: the "outer" one between the user agent and the proxy and the "inner" one between the user agent and the origin server (through the proxy). This change adds supports for such nested sessions as well. The secure connection with the proxy requires its own set of the usual SSL/TLS-related options (their descriptions need polishing): --proxy-cacert FILE CA certificate to verify peer against --proxy-capath DIR CA directory to verify peer against --proxy-cert CERT[:PASSWD] Client certificate file and password --proxy-cert-type TYPE Certificate file type (DER/PEM/ENG) --proxy-ciphers LIST SSL ciphers to use --proxy-crlfile FILE Get a CRL list in PEM format from the given file --proxy-insecure Allow connections to SSL sites without certs --proxy-key KEY Private key file name --proxy-key-type TYPE Private key file type (DER/PEM/ENG) --proxy-pass PASS Pass phrase for the private key --proxy-ssl-allow-beast Allow security flaw to improve interop --proxy-sslv2 Use SSLv2 --proxy-sslv3 Use SSLv3 --proxy-tlsv1 Use TLSv1 --proxy-tlsuser USER TLS username --proxy-tlspassword STRING TLS password --proxy-tlsauthtype STRING TLS authentication type (default SRP) All --proxy-foo options are independent from their --foo counterparts, except --proxy-crlfile defaults to --crlfile and --proxy-capath defaults to --capath. Curl now also supports %{proxy_ssl_verify_result} --write-out variable, similar to the existing %{ssl_verify_result} variable. SOCKS proxy + HTTP/HTTPS proxy combination: If both --socks* and --proxy options are given, Curl first connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or HTTPS proxy.
This commit is contained in:
parent
69c77f69a5
commit
3d90ec5448
@ -235,6 +235,7 @@ CURLINFO_PRIMARY_IP 7.19.0
|
||||
CURLINFO_PRIMARY_PORT 7.21.0
|
||||
CURLINFO_PRIVATE 7.10.3
|
||||
CURLINFO_PROXYAUTH_AVAIL 7.10.8
|
||||
CURLINFO_PROXY_SSL_VERIFYRESULT 7.44.0
|
||||
CURLINFO_REDIRECT_COUNT 7.9.7
|
||||
CURLINFO_REDIRECT_TIME 7.9.7
|
||||
CURLINFO_REDIRECT_URL 7.18.2
|
||||
@ -455,7 +456,23 @@ CURLOPT_PROXYPORT 7.1
|
||||
CURLOPT_PROXYTYPE 7.10
|
||||
CURLOPT_PROXYUSERNAME 7.19.1
|
||||
CURLOPT_PROXYUSERPWD 7.1
|
||||
CURLOPT_PROXY_CAINFO 7.44.0
|
||||
CURLOPT_PROXY_CAPATH 7.44.0
|
||||
CURLOPT_PROXY_CRLFILE 7.44.0
|
||||
CURLOPT_PROXY_KEYPASSWD 7.44.0
|
||||
CURLOPT_PROXY_SERVICE_NAME 7.43.0
|
||||
CURLOPT_PROXY_SSLCERT 7.44.0
|
||||
CURLOPT_PROXY_SSLCERTTYPE 7.44.0
|
||||
CURLOPT_PROXY_SSLKEY 7.44.0
|
||||
CURLOPT_PROXY_SSLKEYTYPE 7.44.0
|
||||
CURLOPT_PROXY_SSLVERSION 7.44.0
|
||||
CURLOPT_PROXY_SSL_CIPHER_LIST 7.44.0
|
||||
CURLOPT_PROXY_SSL_OPTIONS 7.44.0
|
||||
CURLOPT_PROXY_SSL_VERIFYHOST 7.44.0
|
||||
CURLOPT_PROXY_SSL_VERIFYPEER 7.44.0
|
||||
CURLOPT_PROXY_TLSAUTH_PASSWORD 7.44.0
|
||||
CURLOPT_PROXY_TLSAUTH_TYPE 7.44.0
|
||||
CURLOPT_PROXY_TLSAUTH_USERNAME 7.44.0
|
||||
CURLOPT_PROXY_TRANSFER_MODE 7.18.0
|
||||
CURLOPT_PUT 7.1
|
||||
CURLOPT_QUOTE 7.1
|
||||
@ -485,6 +502,8 @@ CURLOPT_SOCKOPTDATA 7.16.0
|
||||
CURLOPT_SOCKOPTFUNCTION 7.16.0
|
||||
CURLOPT_SOCKS5_GSSAPI_NEC 7.19.4
|
||||
CURLOPT_SOCKS5_GSSAPI_SERVICE 7.19.4
|
||||
CURLOPT_SOCKS_PROXY 7.44.0
|
||||
CURLOPT_SOCKS_PROXYTYPE 7.44.0
|
||||
CURLOPT_SOURCE_HOST 7.12.1 - 7.15.5
|
||||
CURLOPT_SOURCE_PATH 7.12.1 - 7.15.5
|
||||
CURLOPT_SOURCE_PORT 7.12.1 - 7.15.5
|
||||
@ -593,6 +612,7 @@ CURLPROTO_TELNET 7.19.4
|
||||
CURLPROTO_TFTP 7.19.4
|
||||
CURLPROXY_HTTP 7.10
|
||||
CURLPROXY_HTTP_1_0 7.19.4
|
||||
CURLPROXY_HTTPS 7.44.0
|
||||
CURLPROXY_SOCKS4 7.10
|
||||
CURLPROXY_SOCKS4A 7.18.0
|
||||
CURLPROXY_SOCKS5 7.10
|
||||
|
@ -612,6 +612,7 @@ typedef enum {
|
||||
CONNECT HTTP/1.1 */
|
||||
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
|
||||
HTTP/1.0 */
|
||||
CURLPROXY_HTTPS = 2, /* added in TBD */
|
||||
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
|
||||
in 7.10 */
|
||||
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
|
||||
@ -1169,7 +1170,8 @@ typedef enum {
|
||||
CINIT(SHARE, OBJECTPOINT, 100),
|
||||
|
||||
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
|
||||
CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
|
||||
CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
|
||||
CURLPROXY_SOCKS5. */
|
||||
CINIT(PROXYTYPE, LONG, 101),
|
||||
|
||||
/* Set the Accept-Encoding string. Use this to tell a server you would like
|
||||
@ -1641,6 +1643,70 @@ typedef enum {
|
||||
/* Wait/don't wait for pipe/mutex to clarify */
|
||||
CINIT(PIPEWAIT, LONG, 237),
|
||||
|
||||
/* The CApath or CAfile used to validate the proxy certificate
|
||||
this option is used only if PROXY_SSL_VERIFYPEER is true */
|
||||
CINIT(PROXY_CAINFO, OBJECTPOINT, 238),
|
||||
|
||||
/* The CApath directory used to validate the proxy certificate
|
||||
this option is used only if PROXY_SSL_VERIFYPEER is true */
|
||||
CINIT(PROXY_CAPATH, OBJECTPOINT, 239),
|
||||
|
||||
/* Set if we should verify the proxy in ssl handshake,
|
||||
set 1 to verify. */
|
||||
CINIT(PROXY_SSL_VERIFYPEER, LONG, 240),
|
||||
|
||||
/* Set if we should verify the Common name from the proxy certificate in ssl
|
||||
* handshake, set 1 to check existence, 2 to ensure that it matches
|
||||
* the provided hostname. */
|
||||
CINIT(PROXY_SSL_VERIFYHOST, LONG, 241),
|
||||
|
||||
/* What version to specifically try to use for proxy.
|
||||
See CURL_SSLVERSION defines below. */
|
||||
CINIT(PROXY_SSLVERSION, LONG, 242),
|
||||
|
||||
/* Set a username for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_USERNAME, OBJECTPOINT, 243),
|
||||
|
||||
/* Set a password for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_PASSWORD, OBJECTPOINT, 244),
|
||||
|
||||
/* Set authentication type for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_TYPE, OBJECTPOINT, 245),
|
||||
|
||||
/* name of the file keeping your private SSL-certificate for proxy */
|
||||
CINIT(PROXY_SSLCERT, OBJECTPOINT, 246),
|
||||
|
||||
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG")
|
||||
for proxy */
|
||||
CINIT(PROXY_SSLCERTTYPE, OBJECTPOINT, 247),
|
||||
|
||||
/* name of the file keeping your private SSL-key for proxy */
|
||||
CINIT(PROXY_SSLKEY, OBJECTPOINT, 248),
|
||||
|
||||
/* type of the file keeping your private SSL-key ("DER", "PEM", "ENG")
|
||||
for proxy */
|
||||
CINIT(PROXY_SSLKEYTYPE, OBJECTPOINT, 249),
|
||||
|
||||
/* password for the SSL private key for proxy */
|
||||
CINIT(PROXY_KEYPASSWD, OBJECTPOINT, 250),
|
||||
|
||||
/* Specify which SSL ciphers to use for proxy */
|
||||
CINIT(PROXY_SSL_CIPHER_LIST, OBJECTPOINT, 251),
|
||||
|
||||
/* CRL file for proxy */
|
||||
CINIT(PROXY_CRLFILE, OBJECTPOINT, 252),
|
||||
|
||||
/* Enable/disable specific SSL features with a bitmask for proxy,
|
||||
see CURLSSLOPT_* */
|
||||
CINIT(PROXY_SSL_OPTIONS, LONG, 253),
|
||||
|
||||
/* Name of socks proxy to use. */
|
||||
CINIT(SOCKS_PROXY, OBJECTPOINT, 254),
|
||||
|
||||
/* indicates type of proxy. accepted values are CURLPROXY_SOCKS4,
|
||||
CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
|
||||
CINIT(SOCKS_PROXYTYPE, LONG, 255),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@ -2132,9 +2198,10 @@ typedef enum {
|
||||
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
|
||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 44,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 43
|
||||
CURLINFO_LASTONE = 44
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
|
@ -133,7 +133,9 @@ void Curl_conncache_destroy(struct conncache *connc)
|
||||
static char *hashkey(struct connectdata *conn)
|
||||
{
|
||||
return aprintf("%s:%d",
|
||||
conn->bits.proxy?conn->proxy.name:conn->host.name,
|
||||
conn->bits.socksproxy ? conn->socks_proxy.host.name :
|
||||
conn->bits.httpproxy ? conn->http_proxy.host.name :
|
||||
conn->host.name,
|
||||
conn->localport);
|
||||
}
|
||||
|
||||
|
@ -850,7 +850,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
}
|
||||
|
||||
failf(data, "Failed to connect to %s port %ld: %s",
|
||||
conn->bits.proxy?conn->proxy.name:conn->host.name,
|
||||
conn->bits.socksproxy ? conn->socks_proxy.host.name :
|
||||
conn->bits.httpproxy ? conn->http_proxy.host.name : conn->host.name,
|
||||
conn->port, Curl_strerror(conn, error));
|
||||
}
|
||||
|
||||
|
@ -133,8 +133,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
||||
|
||||
if(proxy) {
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->proxyuser;
|
||||
passwdp = conn->proxypasswd;
|
||||
userp = conn->http_proxy.user;
|
||||
passwdp = conn->http_proxy.passwd;
|
||||
ntlm = &conn->proxyntlm;
|
||||
authp = &conn->data->state.authproxy;
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
|
||||
if(proxy) {
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->proxyuser;
|
||||
userp = conn->http_proxy.user;
|
||||
ntlm = &conn->proxyntlm;
|
||||
authp = &conn->data->state.authproxy;
|
||||
}
|
||||
|
136
lib/ftp.c
136
lib/ftp.c
@ -488,7 +488,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
|
||||
struct FTP *ftp = data->req.protop;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn->ssl[SECONDARYSOCKET].use) {
|
||||
if(conn->bits.ftp_use_data_ssl) {
|
||||
/* since we only have a plaintext TCP connection here, we must now
|
||||
* do the TLS stuff */
|
||||
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
||||
@ -729,7 +729,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
* wait for more data anyway.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
else if(!Curl_ssl_data_pending(conn, FIRSTSOCKET)) {
|
||||
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
|
||||
case -1: /* select() error, stop reading */
|
||||
failf(data, "FTP response aborted due to select/poll error: %d",
|
||||
@ -1827,84 +1827,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the necessary magic that needs to be done once the TCP connection
|
||||
* to the proxy has completed.
|
||||
*/
|
||||
static CURLcode proxy_magic(struct connectdata *conn,
|
||||
char *newhost, unsigned short newport,
|
||||
bool *magicdone)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
#if defined(CURL_DISABLE_PROXY)
|
||||
(void) newhost;
|
||||
(void) newport;
|
||||
#endif
|
||||
|
||||
*magicdone = FALSE;
|
||||
|
||||
switch(conn->proxytype) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
|
||||
newport, SECONDARYSOCKET, conn);
|
||||
*magicdone = TRUE;
|
||||
break;
|
||||
case CURLPROXY_SOCKS4:
|
||||
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
|
||||
SECONDARYSOCKET, conn, FALSE);
|
||||
*magicdone = TRUE;
|
||||
break;
|
||||
case CURLPROXY_SOCKS4A:
|
||||
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
|
||||
SECONDARYSOCKET, conn, TRUE);
|
||||
*magicdone = TRUE;
|
||||
break;
|
||||
case CURLPROXY_HTTP:
|
||||
case CURLPROXY_HTTP_1_0:
|
||||
/* do nothing here. handled later. */
|
||||
break;
|
||||
default:
|
||||
failf(data, "unknown proxytype option given");
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
break;
|
||||
}
|
||||
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||
/* BLOCKING */
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
|
||||
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
|
||||
* member conn->proto.http; we want FTP through HTTP and we have to
|
||||
* change the member temporarily for connecting to the HTTP proxy. After
|
||||
* Curl_proxyCONNECT we have to set back the member to the original
|
||||
* struct FTP pointer
|
||||
*/
|
||||
struct HTTP http_proxy;
|
||||
struct FTP *ftp_save = data->req.protop;
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
data->req.protop = &http_proxy;
|
||||
|
||||
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
|
||||
|
||||
data->req.protop = ftp_save;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
|
||||
/* the CONNECT procedure is not complete, the tunnel is not yet up */
|
||||
state(conn, FTP_STOP); /* this phase is completed */
|
||||
return result;
|
||||
}
|
||||
else
|
||||
*magicdone = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *control_address(struct connectdata *conn)
|
||||
{
|
||||
@ -1912,11 +1834,7 @@ static char *control_address(struct connectdata *conn)
|
||||
If a proxy tunnel is used, returns the original host name instead, because
|
||||
the effective control connection address is the proxy address,
|
||||
not the ftp host. */
|
||||
if(conn->bits.tunnel_proxy ||
|
||||
conn->proxytype == CURLPROXY_SOCKS5 ||
|
||||
conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
|
||||
conn->proxytype == CURLPROXY_SOCKS4 ||
|
||||
conn->proxytype == CURLPROXY_SOCKS4A)
|
||||
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
|
||||
return conn->host.name;
|
||||
|
||||
return conn->ip_addr_str;
|
||||
@ -2040,7 +1958,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
* here. We don't want to rely on a former host lookup that might've
|
||||
* expired now, instead we remake the lookup here and now!
|
||||
*/
|
||||
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
|
||||
const char * const host_name = conn->bits.socksproxy ?
|
||||
conn->socks_proxy.host.name : conn->http_proxy.host.name;
|
||||
rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
|
||||
if(rc == CURLRESOLV_PENDING)
|
||||
/* BLOCKING, ignores the return code but 'addr' will be NULL in
|
||||
case of failure */
|
||||
@ -2050,8 +1970,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
(unsigned short)conn->port; /* we connect to the proxy's port */
|
||||
|
||||
if(!addr) {
|
||||
failf(data, "Can't resolve proxy host %s:%hu",
|
||||
conn->proxy.name, connectport);
|
||||
failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
|
||||
return CURLE_FTP_CANT_GET_HOST;
|
||||
}
|
||||
}
|
||||
@ -2092,6 +2011,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
|
||||
|
||||
Curl_safefree(conn->secondaryhostname);
|
||||
conn->secondaryhostname = strdup(ftpc->newhost);
|
||||
conn->secondary_port = ftpc->newport;
|
||||
|
||||
Curl_resolv_unlock(data, addr); /* we're done using this address */
|
||||
conn->bits.do_more = TRUE;
|
||||
state(conn, FTP_STOP); /* this phase is completed */
|
||||
@ -2740,7 +2663,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
if(data->set.use_ssl &&
|
||||
(!conn->ssl[FIRSTSOCKET].use ||
|
||||
(conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
|
||||
!conn->proxy_ssl[FIRSTSOCKET].use))) {
|
||||
/* We don't have a SSL/TLS connection yet, but FTPS is
|
||||
requested. Try a FTPS connection now */
|
||||
|
||||
@ -2785,7 +2711,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
/* Curl_ssl_connect is BLOCKING */
|
||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
||||
if(!result) {
|
||||
conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
|
||||
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
|
||||
result = ftp_state_user(conn);
|
||||
}
|
||||
}
|
||||
@ -2827,7 +2753,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
case FTP_PROT:
|
||||
if(ftpcode/100 == 2)
|
||||
/* We have enabled SSL for the data connection! */
|
||||
conn->ssl[SECONDARYSOCKET].use =
|
||||
conn->bits.ftp_use_data_ssl =
|
||||
(data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
|
||||
/* FTP servers typically responds with 500 if they decide to reject
|
||||
our 'P' request */
|
||||
@ -3642,23 +3568,11 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
|
||||
/* if the second connection isn't done yet, wait for it */
|
||||
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
||||
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
|
||||
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
|
||||
aren't used so we blank their arguments. TODO: make this nicer */
|
||||
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
|
||||
|
||||
/* Ready to do more? */
|
||||
if(connected) {
|
||||
DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
|
||||
if(conn->bits.proxy) {
|
||||
infof(data, "Connection to proxy confirmed\n");
|
||||
result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(result && (ftpc->count1 == 0)) {
|
||||
@ -3670,6 +3584,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
}
|
||||
}
|
||||
|
||||
result = Curl_proxy_connect(conn, SECONDARYSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
|
||||
return result;
|
||||
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
|
||||
conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
|
||||
return result;
|
||||
|
||||
|
||||
if(ftpc->state) {
|
||||
/* already in a state so skip the intial commands.
|
||||
They are only done to kickstart the do_more state */
|
||||
@ -4231,8 +4157,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
const char *cur_pos;
|
||||
const char *filename = NULL;
|
||||
|
||||
cur_pos = path_to_use; /* current position in path. point at the begin
|
||||
of next path component */
|
||||
cur_pos = path_to_use; /* current position in path. point at the begin of
|
||||
next path component */
|
||||
|
||||
ftpc->ctl_valid = FALSE;
|
||||
ftpc->cwdfail = FALSE;
|
||||
|
@ -148,6 +148,9 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
|
||||
case CURLINFO_SSL_VERIFYRESULT:
|
||||
*param_longp = data->set.ssl.certverifyresult;
|
||||
break;
|
||||
case CURLINFO_PROXY_SSL_VERIFYRESULT:
|
||||
*param_longp = data->set.proxy_ssl.certverifyresult;
|
||||
break;
|
||||
case CURLINFO_REDIRECT_COUNT:
|
||||
*param_longp = data->set.followlocation;
|
||||
break;
|
||||
|
51
lib/http.c
51
lib/http.c
@ -305,8 +305,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
|
||||
|
||||
if(proxy) {
|
||||
userp = &conn->allocptr.proxyuserpwd;
|
||||
user = conn->proxyuser;
|
||||
pwd = conn->proxypasswd;
|
||||
user = conn->http_proxy.user;
|
||||
pwd = conn->http_proxy.passwd;
|
||||
}
|
||||
else {
|
||||
userp = &conn->allocptr.userpwd;
|
||||
@ -660,7 +660,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
if(auth) {
|
||||
infof(data, "%s auth using %s with user '%s'\n",
|
||||
proxy?"Proxy":"Server", auth,
|
||||
proxy?(conn->proxyuser?conn->proxyuser:""):
|
||||
proxy?(conn->http_proxy.user?conn->http_proxy.user:""):
|
||||
(conn->user?conn->user:""));
|
||||
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
|
||||
}
|
||||
@ -1110,8 +1110,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if(conn->handler->flags & PROTOPT_SSL) {
|
||||
if(conn->handler->flags & PROTOPT_SSL ||
|
||||
conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
|
||||
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
needs to fit into the normal read-callback buffer later on and that
|
||||
@ -1363,10 +1363,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
connkeep(conn, "HTTP default");
|
||||
|
||||
/* the CONNECT procedure might not have been completed */
|
||||
result = Curl_proxy_connect(conn);
|
||||
result = Curl_proxy_connect(conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||
return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
|
||||
|
||||
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
|
||||
/* nothing else to do except wait right now - we're not done here. */
|
||||
return CURLE_OK;
|
||||
@ -1409,48 +1412,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
|
||||
/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
|
||||
It should be made to query the generic SSL layer instead. */
|
||||
static int https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
if(conn->handler->flags & PROTOPT_SSL) {
|
||||
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if(connssl->connecting_state == ssl_connect_2_writing) {
|
||||
/* write mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
else if(connssl->connecting_state == ssl_connect_2_reading) {
|
||||
/* read mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
#else
|
||||
#ifdef USE_SSL
|
||||
static int https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
(void)conn;
|
||||
(void)socks;
|
||||
(void)numsocks;
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
return Curl_ssl_getsock(conn, socks, numsocks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
|
||||
|
||||
/*
|
||||
* Curl_http_done() gets called from Curl_done() after a single HTTP request
|
||||
|
@ -96,8 +96,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
if(proxy) {
|
||||
digest = &data->state.proxydigest;
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->proxyuser;
|
||||
passwdp = conn->proxypasswd;
|
||||
userp = conn->http_proxy.user;
|
||||
passwdp = conn->http_proxy.passwd;
|
||||
authp = &data->state.authproxy;
|
||||
}
|
||||
else {
|
||||
|
@ -65,7 +65,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
char *spn = Curl_sasl_build_gssapi_spn(
|
||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||
data->set.str[STRING_SERVICE_NAME],
|
||||
proxy ? conn->proxy.name : conn->host.name);
|
||||
proxy ? conn->http_proxy.host.name : conn->host.name);
|
||||
if(!spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -90,14 +90,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
|
||||
if(!neg_ctx->server_name) {
|
||||
/* Check proxy auth requested but no given proxy name */
|
||||
if(proxy && !conn->proxy.name)
|
||||
if(proxy && !conn->http_proxy.host.name)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
/* Generate our SPN */
|
||||
neg_ctx->server_name = Curl_sasl_build_spn(
|
||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||
data->set.str[STRING_SERVICE_NAME],
|
||||
proxy ? conn->proxy.name : conn->host.name);
|
||||
proxy ? conn->http_proxy.host.name : conn->host.name);
|
||||
if(!neg_ctx->server_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -37,19 +37,57 @@
|
||||
#include "connect.h"
|
||||
#include "curl_printf.h"
|
||||
#include "curlx.h"
|
||||
#include "vtls/vtls.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
/*
|
||||
* Perform SSL initialization for HTTPS proxy. Sets
|
||||
* proxy_ssl_connected connection bit when complete. Can be
|
||||
* called multiple times.
|
||||
*/
|
||||
static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
#ifdef USE_SSL
|
||||
CURLcode result = CURLE_OK;
|
||||
DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
|
||||
if(!conn->bits.proxy_ssl_connected[sockindex]) {
|
||||
/* perform SSL initialization for this socket */
|
||||
result =
|
||||
Curl_ssl_connect_nonblocking(conn, sockindex,
|
||||
&conn->bits.proxy_ssl_connected[sockindex]);
|
||||
if(result)
|
||||
conn->bits.close = TRUE; /* a failed connection is marked for closure to
|
||||
prevent (bad) re-use or similar */
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
|
||||
const CURLcode result = https_proxy_connect(conn, sockindex);
|
||||
if(result)
|
||||
return result;
|
||||
if(!conn->bits.proxy_ssl_connected[sockindex])
|
||||
return result; /* wait for HTTPS proxy SSL initialization to complete */
|
||||
}
|
||||
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* for [protocol] tunneled through HTTP proxy */
|
||||
struct HTTP http_proxy;
|
||||
void *prot_save;
|
||||
CURLcode result;
|
||||
const char * const host = sockindex == SECONDARYSOCKET ?
|
||||
conn->secondaryhostname : conn->host.name;
|
||||
const int port = sockindex == SECONDARYSOCKET ? conn->secondary_port :
|
||||
conn->remote_port;
|
||||
|
||||
/* BLOCKING */
|
||||
/* We want "seamless" operations through HTTP proxy tunnel */
|
||||
@ -67,8 +105,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||
conn->data->req.protop = &http_proxy;
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
|
||||
conn->host.name, conn->remote_port, FALSE);
|
||||
result = Curl_proxyCONNECT(conn, sockindex, host, port, FALSE);
|
||||
conn->data->req.protop = prot_save;
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
@ -152,7 +189,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
char *host=(char *)"";
|
||||
const char *proxyconn="";
|
||||
const char *useragent="";
|
||||
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
|
||||
const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
|
||||
"1.0" : "1.1";
|
||||
char *hostheader= /* host:port with IPv6 support */
|
||||
aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
|
||||
|
@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
/* Default proxy timeout in milliseconds */
|
||||
#define PROXY_TIMEOUT (3600*1000)
|
||||
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn);
|
||||
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
|
||||
|
||||
#else
|
||||
#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
|
||||
#define Curl_proxy_connect(x) CURLE_OK
|
||||
#define Curl_proxy_connect(x,y) CURLE_OK
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
||||
|
14
lib/ldap.c
14
lib/ldap.c
@ -273,7 +273,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
|
||||
#else
|
||||
int ldap_option;
|
||||
char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
|
||||
char* ldap_ca = conn->ssl_config.CAfile;
|
||||
#if defined(CURL_HAS_NOVELL_LDAPSDK)
|
||||
rc = ldapssl_client_init(NULL, NULL);
|
||||
if(rc != LDAP_SUCCESS) {
|
||||
@ -281,11 +281,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
result = CURLE_SSL_CERTPROBLEM;
|
||||
goto quit;
|
||||
}
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
/* Novell SDK supports DER or BASE64 files. */
|
||||
int cert_type = LDAPSSL_CERT_FILETYPE_B64;
|
||||
if((data->set.str[STRING_CERT_TYPE]) &&
|
||||
(Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
|
||||
if((data->set.ssl.cert_type) &&
|
||||
(Curl_raw_equal(data->set.ssl.cert_type, "DER")))
|
||||
cert_type = LDAPSSL_CERT_FILETYPE_DER;
|
||||
if(!ldap_ca) {
|
||||
failf(data, "LDAP local: ERROR %s CA cert not set!",
|
||||
@ -323,10 +323,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
||||
goto quit;
|
||||
}
|
||||
#elif defined(LDAP_OPT_X_TLS)
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
/* OpenLDAP SDK supports BASE64 files. */
|
||||
if((data->set.str[STRING_CERT_TYPE]) &&
|
||||
(!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
|
||||
if((data->set.ssl.cert_type) &&
|
||||
(!Curl_raw_equal(data->set.ssl.cert_type, "PEM"))) {
|
||||
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
|
||||
result = CURLE_SSL_CERTPROBLEM;
|
||||
goto quit;
|
||||
|
18
lib/multi.c
18
lib/multi.c
@ -42,7 +42,8 @@
|
||||
#include "multihandle.h"
|
||||
#include "pipeline.h"
|
||||
#include "sigpipe.h"
|
||||
#include "curl_printf.h"
|
||||
#include "vtls/vtls.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@ -629,6 +630,9 @@ static int waitconnect_getsock(struct connectdata *conn,
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||
return Curl_ssl_getsock(conn, sock, numsocks);
|
||||
|
||||
for(i=0; i<2; i++) {
|
||||
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
|
||||
sock[s] = conn->tempsock[i];
|
||||
@ -1223,7 +1227,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
multistate(data, CURLM_STATE_CONNECT);
|
||||
}
|
||||
else if(!result) {
|
||||
if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE)
|
||||
if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
|
||||
data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
|
||||
(data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT))
|
||||
/* initiate protocol connect phase */
|
||||
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
|
||||
}
|
||||
@ -1234,6 +1240,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/* awaiting a completion of an asynch TCP connect */
|
||||
result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
|
||||
if(connected && !result) {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
|
||||
!data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
|
||||
(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
|
||||
multistate(data, CURLM_STATE_WAITPROXYCONNECT);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
multistate(data, data->easy_conn->bits.tunnel_proxy?
|
||||
CURLM_STATE_WAITPROXYCONNECT:
|
||||
|
@ -38,7 +38,9 @@ typedef enum {
|
||||
CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
|
||||
CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
|
||||
CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */
|
||||
CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
|
||||
CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
|
||||
to complete and/or proxy CONNECT to
|
||||
finalize */
|
||||
CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
|
||||
CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
|
||||
phase */
|
||||
|
@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
|
||||
else
|
||||
interval_ms = 0; /* immediate */
|
||||
|
||||
if(Curl_pp_moredata(pp))
|
||||
if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
||||
rc = 1;
|
||||
else if(Curl_pp_moredata(pp))
|
||||
/* We are receiving and there is data in the cache so just read it */
|
||||
rc = 1;
|
||||
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
||||
|
10
lib/rawstr.c
10
lib/rawstr.c
@ -110,6 +110,16 @@ int Curl_raw_equal(const char *first, const char *second)
|
||||
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
|
||||
}
|
||||
|
||||
bool Curl_safe_strequal(const char *str1, const char *str2)
|
||||
{
|
||||
if(str1 && str2)
|
||||
/* both pointers point to something then compare them */
|
||||
return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
|
||||
else
|
||||
/* if both pointers are NULL then treat them as equal */
|
||||
return (!str1 && !str2) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
int Curl_raw_nequal(const char *first, const char *second, size_t max)
|
||||
{
|
||||
while(*first && *second && max) {
|
||||
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
int Curl_raw_equal(const char *first, const char *second);
|
||||
int Curl_raw_nequal(const char *first, const char *second, size_t max);
|
||||
bool Curl_safe_strequal(const char *str1, const char *str2);
|
||||
|
||||
char Curl_raw_toupper(char in);
|
||||
|
||||
|
16
lib/socks.c
16
lib/socks.c
@ -110,9 +110,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct connectdata *conn,
|
||||
bool protocol4a)
|
||||
struct connectdata *conn)
|
||||
{
|
||||
const bool protocol4a =
|
||||
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
|
||||
#define SOCKS4REQLEN 262
|
||||
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
|
||||
id */
|
||||
@ -127,6 +128,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
if(conn->bits.httpproxy)
|
||||
infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
|
||||
protocol4a ? "a" : "", hostname, remote_port);
|
||||
|
||||
(void)curlx_nonblock(sock, FALSE);
|
||||
|
||||
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
|
||||
@ -376,10 +381,15 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
curl_socket_t sock = conn->sock[sockindex];
|
||||
struct SessionHandle *data = conn->data;
|
||||
long timeout;
|
||||
bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
|
||||
bool socks5_resolve_local =
|
||||
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
|
||||
const size_t hostname_len = strlen(hostname);
|
||||
ssize_t len = 0;
|
||||
|
||||
if(conn->bits.httpproxy)
|
||||
infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
|
||||
hostname, remote_port);
|
||||
|
||||
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
|
||||
if(!socks5_resolve_local && hostname_len > 255) {
|
||||
infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef CURL_DISABLE_PROXY
|
||||
#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
|
||||
#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN
|
||||
#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
|
||||
#else
|
||||
/*
|
||||
@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct connectdata *conn,
|
||||
bool protocol4a);
|
||||
struct connectdata *conn);
|
||||
|
||||
/*
|
||||
* This function logs in to a SOCKS5 proxy and sends the specifics to the
|
||||
|
@ -121,6 +121,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
char *user=NULL;
|
||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
const size_t serviceptr_length = strlen(serviceptr);
|
||||
|
||||
/* GSS-API request looks like
|
||||
* +----+------+-----+----------------+
|
||||
@ -132,22 +133,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
|
||||
/* prepare service name */
|
||||
if(strchr(serviceptr, '/')) {
|
||||
service.value = malloc(strlen(serviceptr));
|
||||
service.length = serviceptr_length;
|
||||
service.value = malloc(service.length);
|
||||
if(!service.value)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
service.length = strlen(serviceptr);
|
||||
memcpy(service.value, serviceptr, service.length);
|
||||
|
||||
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
||||
(gss_OID) GSS_C_NULL_OID, &server);
|
||||
}
|
||||
else {
|
||||
service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
|
||||
service.value = malloc(serviceptr_length +
|
||||
strlen(conn->socks_proxy.host.name)+2);
|
||||
if(!service.value)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
|
||||
service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
|
||||
snprintf(service.value, service.length+1, "%s@%s",
|
||||
serviceptr, conn->proxy.name);
|
||||
serviceptr, conn->socks_proxy.host.name);
|
||||
|
||||
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
||||
GSS_C_NT_HOSTBASED_SERVICE, &server);
|
||||
|
@ -84,6 +84,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
unsigned long qop;
|
||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
const size_t service_length = strlen(service);
|
||||
|
||||
/* GSS-API request looks like
|
||||
* +----+------+-----+----------------+
|
||||
@ -95,17 +96,19 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
|
||||
/* prepare service name */
|
||||
if(strchr(service, '/')) {
|
||||
service_name = malloc(strlen(service));
|
||||
service_name = malloc(service_length);
|
||||
if(!service_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
memcpy(service_name, service, strlen(service));
|
||||
memcpy(service_name, service, service_length);
|
||||
}
|
||||
else {
|
||||
service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
|
||||
service_name = malloc(service_length +
|
||||
strlen(conn->socks_proxy.host.name) + 2);
|
||||
if(!service_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
|
||||
"%s/%s", service, conn->proxy.name);
|
||||
snprintf(service_name, service_length +
|
||||
strlen(conn->socks_proxy.host.name)+2, "%s/%s",
|
||||
service, conn->socks_proxy.host.name);
|
||||
}
|
||||
|
||||
input_desc.cBuffers = 1;
|
||||
|
@ -863,7 +863,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
break;
|
||||
}
|
||||
|
||||
sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
|
||||
sshc->passphrase = data->set.ssl.key_passwd;
|
||||
if(!sshc->passphrase)
|
||||
sshc->passphrase = "";
|
||||
|
||||
|
@ -1300,7 +1300,7 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||
/* Init the SSL session ID cache here. We do it here since we want to do it
|
||||
after the *_setopt() calls (that could specify the size of the cache) but
|
||||
before any transfer takes place. */
|
||||
result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
|
||||
result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
11
lib/url.h
11
lib/url.h
@ -82,5 +82,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
|
||||
void Curl_verboseconnect(struct connectdata *conn);
|
||||
#endif
|
||||
|
||||
#define CONNECT_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[sockindex])
|
||||
|
||||
#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[FIRSTSOCKET])
|
||||
|
||||
#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
|
||||
|
||||
#endif /* HEADER_CURL_URL_H */
|
||||
|
@ -337,27 +337,36 @@ struct ssl_connect_data {
|
||||
#endif /* USE_DARWINSSL */
|
||||
};
|
||||
|
||||
struct ssl_config_data {
|
||||
struct ssl_primary_config {
|
||||
long version; /* what version the client wants to use */
|
||||
long certverifyresult; /* result from the certificate verification */
|
||||
|
||||
bool verifypeer; /* set TRUE if this is desired */
|
||||
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
|
||||
bool verifystatus; /* set TRUE if certificate status must be checked */
|
||||
char *CApath; /* certificate dir (doesn't work on windows) */
|
||||
char *CAfile; /* certificate to verify peer against */
|
||||
const char *CRLfile; /* CRL to check certificate revocation */
|
||||
const char *issuercert;/* optional issuer certificate filename */
|
||||
char *random_file; /* path to file containing "random" data */
|
||||
char *egdsocket; /* path to file containing the EGD daemon socket */
|
||||
char *cipher_list; /* list of ciphers to use */
|
||||
size_t max_ssl_sessions; /* SSL session id cache size */
|
||||
};
|
||||
|
||||
struct ssl_config_data {
|
||||
struct ssl_primary_config primary;
|
||||
bool enable_beast; /* especially allow this flaw for interoperability's
|
||||
sake*/
|
||||
long certverifyresult; /* result from the certificate verification */
|
||||
char *CRLfile; /* CRL to check certificate revocation */
|
||||
char *issuercert;/* optional issuer certificate filename */
|
||||
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
|
||||
void *fsslctxp; /* parameter for call back */
|
||||
bool sessionid; /* cache session IDs or not */
|
||||
bool certinfo; /* gather lots of certificate info */
|
||||
bool falsestart;
|
||||
|
||||
char *cert; /* client certificate file name */
|
||||
char *cert_type; /* format for certificate (default: PEM)*/
|
||||
char *key; /* private key file name */
|
||||
char *key_type; /* format for private key (default: PEM) */
|
||||
char *key_passwd; /* plain text private key password */
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
char *username; /* TLS username (for, e.g., SRP) */
|
||||
char *password; /* TLS password (for, e.g., SRP) */
|
||||
@ -365,6 +374,11 @@ struct ssl_config_data {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ssl_general_config {
|
||||
bool sessionid; /* cache session IDs or not */
|
||||
size_t max_ssl_sessions; /* SSL session id cache size */
|
||||
};
|
||||
|
||||
/* information stored about one single SSL session */
|
||||
struct curl_ssl_session {
|
||||
char *name; /* host name for which this ID was used */
|
||||
@ -372,7 +386,7 @@ struct curl_ssl_session {
|
||||
size_t idsize; /* if known, otherwise 0 */
|
||||
long age; /* just a number, the higher the more recent */
|
||||
int remote_port; /* remote port to connect to */
|
||||
struct ssl_config_data ssl_config; /* setup for this session */
|
||||
struct ssl_primary_config ssl_config; /* setup for this session */
|
||||
};
|
||||
|
||||
/* Struct used for Digest challenge-response authentication */
|
||||
@ -485,6 +499,7 @@ struct ConnectBits {
|
||||
bool reuse; /* if set, this is a re-used connection */
|
||||
bool proxy; /* if set, this transfer is done through a proxy - any type */
|
||||
bool httpproxy; /* if set, this transfer is done through a http proxy */
|
||||
bool socksproxy; /* if set, this transfer is done through a socks proxy */
|
||||
bool user_passwd; /* do we use user+password for this connection? */
|
||||
bool proxy_user_passwd; /* user+password for the proxy? */
|
||||
bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
|
||||
@ -519,6 +534,7 @@ struct ConnectBits {
|
||||
bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
|
||||
EPRT doesn't work we disable it for the forthcoming
|
||||
requests */
|
||||
bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
|
||||
bool netrc; /* name+password provided by netrc */
|
||||
bool userpwd_in_url; /* name+password found in url */
|
||||
bool stream_was_rewound; /* Indicates that the stream was rewound after a
|
||||
@ -531,6 +547,9 @@ struct ConnectBits {
|
||||
connection */
|
||||
bool type_set; /* type= was used in the URL */
|
||||
bool multiplex; /* connection is multiplexed */
|
||||
bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
|
||||
is complete */
|
||||
bool socksproxy_connecting; /* connecting through a socks proxy */
|
||||
};
|
||||
|
||||
struct hostname {
|
||||
@ -819,6 +838,14 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
|
||||
size_t len, /* max amount to read */
|
||||
CURLcode *err); /* error to return */
|
||||
|
||||
struct proxy_info {
|
||||
struct hostname host;
|
||||
long port;
|
||||
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
||||
char *user; /* proxy user name string, allocated */
|
||||
char *passwd; /* proxy password string, allocated */
|
||||
};
|
||||
|
||||
/*
|
||||
* The connectdata struct contains all fields and variables that should be
|
||||
* unique for an entire connection.
|
||||
@ -868,10 +895,15 @@ struct connectdata {
|
||||
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
|
||||
|
||||
struct hostname host;
|
||||
struct hostname proxy;
|
||||
char *secondaryhostname; /* secondary socket host name (ftp) */
|
||||
|
||||
struct proxy_info socks_proxy;
|
||||
struct proxy_info http_proxy;
|
||||
|
||||
long port; /* which port to use locally */
|
||||
int remote_port; /* what remote port to connect to, not the proxy port! */
|
||||
unsigned short secondary_port; /* secondary socket remote port to connect to
|
||||
(ftp) */
|
||||
|
||||
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
|
||||
ip address and port number whenever an outgoing connection is
|
||||
@ -896,10 +928,6 @@ struct connectdata {
|
||||
|
||||
char *xoauth2_bearer; /* bearer token for xoauth2, allocated */
|
||||
|
||||
char *proxyuser; /* proxy user name string, allocated */
|
||||
char *proxypasswd; /* proxy password string, allocated */
|
||||
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
||||
|
||||
int httpversion; /* the HTTP version*10 reported by the server */
|
||||
int rtspversion; /* the RTSP version*10 reported by the server */
|
||||
|
||||
@ -914,7 +942,9 @@ struct connectdata {
|
||||
Curl_send *send[2];
|
||||
|
||||
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
|
||||
struct ssl_config_data ssl_config;
|
||||
struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
|
||||
struct ssl_primary_config ssl_config;
|
||||
struct ssl_primary_config proxy_ssl_config;
|
||||
|
||||
struct ConnectBits bits; /* various state-flags for this connection */
|
||||
|
||||
@ -1040,9 +1070,6 @@ struct connectdata {
|
||||
int socks5_gssapi_enctype;
|
||||
#endif
|
||||
|
||||
bool verifypeer;
|
||||
bool verifyhost;
|
||||
|
||||
/* When this connection is created, store the conditions for the local end
|
||||
bind. This is stored before the actual bind and before any connection is
|
||||
made and will serve the purpose of being used for comparison reasons so
|
||||
@ -1346,8 +1373,6 @@ struct DynamicStatic {
|
||||
struct Curl_multi; /* declared and used only in multi.c */
|
||||
|
||||
enum dupstring {
|
||||
STRING_CERT, /* client certificate file name */
|
||||
STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
|
||||
STRING_COOKIE, /* HTTP cookie string to send */
|
||||
STRING_COOKIEJAR, /* dump all cookies to this file */
|
||||
STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
|
||||
@ -1356,25 +1381,16 @@ enum dupstring {
|
||||
STRING_FTP_ACCOUNT, /* ftp account data */
|
||||
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
|
||||
STRING_FTPPORT, /* port to send with the FTP PORT command */
|
||||
STRING_KEY, /* private key file name */
|
||||
STRING_KEY_PASSWD, /* plain text private key password */
|
||||
STRING_KEY_TYPE, /* format for private key (default: PEM) */
|
||||
STRING_KRB_LEVEL, /* krb security level */
|
||||
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
|
||||
$HOME/.netrc */
|
||||
STRING_PROXY, /* proxy to use */
|
||||
STRING_SOCKS_PROXY, /* socks proxy to use */
|
||||
STRING_SET_RANGE, /* range, if used */
|
||||
STRING_SET_REFERER, /* custom string for the HTTP referer field */
|
||||
STRING_SET_URL, /* what original URL to work on */
|
||||
STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
|
||||
STRING_SSL_CAFILE, /* certificate file to verify peer against */
|
||||
STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
|
||||
STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
|
||||
STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
|
||||
STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
|
||||
STRING_USERAGENT, /* User-Agent string */
|
||||
STRING_SSL_CRLFILE, /* crl file to check certificate */
|
||||
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
|
||||
STRING_USERNAME, /* <username>, if used */
|
||||
STRING_PASSWORD, /* <password>, if used */
|
||||
STRING_OPTIONS, /* <options>, if used */
|
||||
@ -1399,10 +1415,6 @@ enum dupstring {
|
||||
STRING_MAIL_FROM,
|
||||
STRING_MAIL_AUTH,
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
STRING_TLSAUTH_USERNAME, /* TLS auth <username> */
|
||||
STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
|
||||
#endif
|
||||
STRING_BEARER, /* <bearer>, if used */
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
|
||||
@ -1516,7 +1528,10 @@ struct UserDefined {
|
||||
long httpversion; /* when non-zero, a specific HTTP version requested to
|
||||
be used in the library's request(s) */
|
||||
struct ssl_config_data ssl; /* user defined SSL stuff */
|
||||
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
|
||||
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
|
||||
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
||||
curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */
|
||||
long dns_cache_timeout; /* DNS cache timeout */
|
||||
long buffer_size; /* size of receive buffer to use */
|
||||
void *private_data; /* application-private data */
|
||||
@ -1580,8 +1595,6 @@ struct UserDefined {
|
||||
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
|
||||
us */
|
||||
bool connect_only; /* make connection, let application use the socket */
|
||||
bool ssl_enable_beast; /* especially allow this flaw for interoperability's
|
||||
sake*/
|
||||
long ssh_auth_types; /* allowed SSH auth types */
|
||||
bool http_te_skip; /* pass the raw body data to the user, even when
|
||||
transfer-encoded (chunked, compressed) */
|
||||
|
@ -160,7 +160,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* axTLS only supports TLSv1 */
|
||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||
switch(data->set.ssl.version) {
|
||||
switch(conn->ssl_config.version) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
break;
|
||||
@ -185,17 +185,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
conn->ssl[sockindex].ssl = NULL;
|
||||
|
||||
/* Load the trusted CA cert bundle file */
|
||||
if(data->set.ssl.CAfile) {
|
||||
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
|
||||
!= SSL_OK) {
|
||||
if(conn->ssl_config.CAfile) {
|
||||
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
|
||||
conn->ssl_config.CAfile, NULL) != SSL_OK) {
|
||||
infof(data, "error reading ca cert file %s \n",
|
||||
data->set.ssl.CAfile);
|
||||
if(data->set.ssl.verifypeer) {
|
||||
conn->ssl_config.CAfile);
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
|
||||
infof(data, "found certificates in %s\n", conn->ssl_config.CAfile);
|
||||
}
|
||||
|
||||
/* gtls.c tasks we're skipping for now:
|
||||
@ -207,15 +207,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
*/
|
||||
|
||||
/* Load client certificate */
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
if(data->set.ssl.cert) {
|
||||
i=0;
|
||||
/* Instead of trying to analyze cert type here, let axTLS try them all. */
|
||||
while(cert_types[i] != 0) {
|
||||
ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
|
||||
data->set.str[STRING_CERT], NULL);
|
||||
data->set.ssl.cert, NULL);
|
||||
if(ssl_fcn_return == SSL_OK) {
|
||||
infof(data, "successfully read cert file %s \n",
|
||||
data->set.str[STRING_CERT]);
|
||||
data->set.ssl.cert);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
@ -223,7 +223,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
/* Tried all cert types, none worked. */
|
||||
if(cert_types[i] == 0) {
|
||||
failf(data, "%s is not x509 or pkcs12 format",
|
||||
data->set.str[STRING_CERT]);
|
||||
data->set.ssl.cert);
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
@ -231,15 +231,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
/* Load client key.
|
||||
If a pkcs12 file successfully loaded a cert, then there's nothing to do
|
||||
because the key has already been loaded. */
|
||||
if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
|
||||
if(data->set.ssl.key && cert_types[i] != SSL_OBJ_PKCS12) {
|
||||
i=0;
|
||||
/* Instead of trying to analyze key type here, let axTLS try them all. */
|
||||
while(key_types[i] != 0) {
|
||||
ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
|
||||
data->set.str[STRING_KEY], NULL);
|
||||
data->set.ssl.key, NULL);
|
||||
if(ssl_fcn_return == SSL_OK) {
|
||||
infof(data, "successfully read key file %s \n",
|
||||
data->set.str[STRING_KEY]);
|
||||
data->set.ssl.key);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
@ -247,7 +247,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
/* Tried all key types, none worked. */
|
||||
if(key_types[i] == 0) {
|
||||
failf(data, "Failure: %s is not a supported key file",
|
||||
data->set.str[STRING_KEY]);
|
||||
data->set.ssl.key);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
@ -259,7 +259,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
*/
|
||||
|
||||
/* In axTLS, handshaking happens inside ssl_client_new. */
|
||||
if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
|
||||
if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
|
||||
sockindex)) {
|
||||
/* we got a session id, use it! */
|
||||
infof (data, "SSL re-using session ID\n");
|
||||
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
|
||||
@ -293,7 +294,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
*/
|
||||
|
||||
/* Verify server's certificate */
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
if(ssl_verify_cert(ssl) != SSL_OK) {
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "server cert verify failed");
|
||||
@ -359,7 +360,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
else {
|
||||
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
/* Break connection ! */
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
||||
@ -381,7 +382,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
/* Put our freshly minted SSL session in cache */
|
||||
ssl_idsize = ssl_get_session_id_size(ssl);
|
||||
ssl_sessionid = ssl_get_session_id(ssl);
|
||||
if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
|
||||
if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize, sockindex)
|
||||
!= CURLE_OK)
|
||||
infof (data, "failed to add session to cache\n");
|
||||
|
||||
|
@ -116,7 +116,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
|
||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||
switch(data->set.ssl.version) {
|
||||
switch(conn->ssl_config.version) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
|
||||
@ -190,18 +190,18 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
/* load trusted cacert */
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
if(conn->ssl_config.CAfile) {
|
||||
if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
|
||||
data->set.str[STRING_SSL_CAFILE],
|
||||
data->set.str[STRING_SSL_CAPATH])) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
conn->ssl_config.CAfile,
|
||||
conn->ssl_config.CApath)) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
/* Fail if we insist on successfully verifying the server. */
|
||||
failf(data, "error setting certificate verify locations:\n"
|
||||
" CAfile: %s\n CApath: %s",
|
||||
data->set.str[STRING_SSL_CAFILE]?
|
||||
data->set.str[STRING_SSL_CAFILE]: "none",
|
||||
data->set.str[STRING_SSL_CAPATH]?
|
||||
data->set.str[STRING_SSL_CAPATH] : "none");
|
||||
conn->ssl_config.CAfile?
|
||||
conn->ssl_config.CAfile: "none",
|
||||
conn->ssl_config.CApath?
|
||||
conn->ssl_config.CApath : "none");
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else {
|
||||
@ -218,25 +218,25 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
infof(data,
|
||||
" CAfile: %s\n"
|
||||
" CApath: %s\n",
|
||||
data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
|
||||
conn->ssl_config.CAfile ? conn->ssl_config.CAfile:
|
||||
"none",
|
||||
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
|
||||
conn->ssl_config.CApath ? conn->ssl_config.CApath:
|
||||
"none");
|
||||
}
|
||||
|
||||
/* Load the client certificate, and private key */
|
||||
if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
|
||||
int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
|
||||
if(data->set.ssl.cert && data->set.ssl.key) {
|
||||
int file_type = do_file_type(data->set.ssl.cert_type);
|
||||
|
||||
if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
|
||||
if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.ssl.cert,
|
||||
file_type) != 1) {
|
||||
failf(data, "unable to use client certificate (no key or wrong pass"
|
||||
" phrase?)");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
|
||||
if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
|
||||
file_type = do_file_type(data->set.ssl.key_type);
|
||||
if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.ssl.key,
|
||||
file_type) != 1) {
|
||||
failf(data, "unable to set private key");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -249,7 +249,8 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
* anyway. In the latter case the result of the verification is checked with
|
||||
* SSL_get_verify_result() below. */
|
||||
SSL_CTX_set_verify(conssl->ctx,
|
||||
data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
|
||||
conn->ssl_config.verifypeer?SSL_VERIFY_PEER:
|
||||
SSL_VERIFY_NONE,
|
||||
NULL);
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
@ -302,7 +303,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* Check if there's a cached ID we can/should use here! */
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
|
||||
/* we got a session id, use it! */
|
||||
if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
|
||||
failf(data, "SSL: SSL_set_session failed: %s",
|
||||
@ -336,7 +337,7 @@ cyassl_connect_step2(struct connectdata *conn,
|
||||
conn->send[sockindex] = cyassl_send;
|
||||
|
||||
/* Enable RFC2818 checks */
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
|
||||
if(ret == SSL_FAILURE)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@ -369,7 +370,7 @@ cyassl_connect_step2(struct connectdata *conn,
|
||||
* CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
|
||||
* way to do this is currently to switch the CyaSSL_check_domain_name()
|
||||
* in and out based on the 'data->set.ssl.verifyhost' value. */
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
failf(data,
|
||||
"\tsubject alt name(s) or common name do not match \"%s\"\n",
|
||||
conn->host.dispname);
|
||||
@ -464,7 +465,8 @@ cyassl_connect_step3(struct connectdata *conn,
|
||||
|
||||
our_ssl_sessionid = SSL_get_session(connssl->handle);
|
||||
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
|
||||
sockindex));
|
||||
if(incache) {
|
||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||
infof(data, "old SSL session ID is stale, removing\n");
|
||||
@ -475,7 +477,7 @@ cyassl_connect_step3(struct connectdata *conn,
|
||||
|
||||
if(!incache) {
|
||||
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
||||
0 /* unknown size */);
|
||||
0 /* unknown size */, sockindex);
|
||||
if(result) {
|
||||
failf(data, "failed to store ssl session");
|
||||
return result;
|
||||
|
@ -1055,7 +1055,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||
if(SSLSetProtocolVersionMax != NULL) {
|
||||
switch(data->set.ssl.version) {
|
||||
switch(conn->ssl_config.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1096,7 +1096,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocolAll,
|
||||
false);
|
||||
switch (data->set.ssl.version) {
|
||||
switch (conn->ssl_config.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1148,7 +1148,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#else
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
|
||||
switch(data->set.ssl.version) {
|
||||
switch(conn->ssl_config.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1293,7 +1293,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
#else
|
||||
if(SSLSetSessionOption != NULL) {
|
||||
#endif /* CURL_BUILD_MAC */
|
||||
bool break_on_auth = !data->set.ssl.verifypeer ||
|
||||
bool break_on_auth = !conn->ssl_config.verifypeer ||
|
||||
data->set.str[STRING_SSL_CAFILE];
|
||||
err = SSLSetSessionOption(connssl->ssl_ctx,
|
||||
kSSLSessionOptionBreakOnServerAuth,
|
||||
@ -1306,7 +1306,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
else {
|
||||
#if CURL_SUPPORT_MAC_10_8
|
||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||
data->set.ssl.verifypeer?true:false);
|
||||
conn->ssl_config.verifypeer?true:false);
|
||||
if(err != noErr) {
|
||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1315,7 +1315,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#else
|
||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||
data->set.ssl.verifypeer?true:false);
|
||||
conn->ssl_config.verifypeer?true:false);
|
||||
if(err != noErr) {
|
||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1340,7 +1340,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
/* Configure hostname check. SNI is used if available.
|
||||
* Both hostname check and SNI require SSLSetPeerDomainName().
|
||||
* Also: the verifyhost setting influences SNI usage */
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
|
||||
strlen(conn->host.name));
|
||||
|
||||
|
@ -411,11 +411,11 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
Curl_gtls_init();
|
||||
|
||||
/* GnuTLS only supports SSLv3 and TLSv1 */
|
||||
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
|
||||
if(conn->ssl_config.version == CURL_SSLVERSION_SSLv2) {
|
||||
failf(data, "GnuTLS does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
|
||||
else if(conn->ssl_config.version == CURL_SSLVERSION_SSLv3)
|
||||
sni = FALSE; /* SSLv3 has no SNI */
|
||||
|
||||
/* allocate a cred struct */
|
||||
@ -449,23 +449,23 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.ssl.CAfile) {
|
||||
if(conn->ssl_config.CAfile) {
|
||||
/* set the trusted CA cert bundle file */
|
||||
gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
|
||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
||||
|
||||
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
|
||||
data->set.ssl.CAfile,
|
||||
conn->ssl_config.CAfile,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
if(rc < 0) {
|
||||
infof(data, "error reading ca cert file %s (%s)\n",
|
||||
data->set.ssl.CAfile, gnutls_strerror(rc));
|
||||
if(data->set.ssl.verifypeer)
|
||||
conn->ssl_config.CAfile, gnutls_strerror(rc));
|
||||
if(conn->ssl_config.verifypeer)
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else
|
||||
infof(data, "found %d certificates in %s\n",
|
||||
rc, data->set.ssl.CAfile);
|
||||
rc, conn->ssl_config.CAfile);
|
||||
}
|
||||
|
||||
#ifdef HAS_CAPATH
|
||||
@ -544,7 +544,7 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
switch (data->set.ssl.version) {
|
||||
switch (conn->ssl_config.version) {
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
protocol_priority[0] = GNUTLS_SSL3;
|
||||
break;
|
||||
@ -579,7 +579,7 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
/* Ensure +SRP comes at the *end* of all relevant strings so that it can be
|
||||
* removed if a run-time error indicates that SRP is not supported by this
|
||||
* GnuTLS version */
|
||||
switch (data->set.ssl.version) {
|
||||
switch (conn->ssl_config.version) {
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
|
||||
sni = false;
|
||||
@ -654,13 +654,13 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
if(data->set.ssl.cert) {
|
||||
if(gnutls_certificate_set_x509_key_file(
|
||||
conn->ssl[sockindex].cred,
|
||||
data->set.str[STRING_CERT],
|
||||
data->set.str[STRING_KEY] ?
|
||||
data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
|
||||
do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
|
||||
data->set.ssl.cert,
|
||||
data->set.ssl.key ?
|
||||
data->set.ssl.key : data->set.ssl.cert,
|
||||
do_file_type(data->set.ssl.cert_type) ) !=
|
||||
GNUTLS_E_SUCCESS) {
|
||||
failf(data, "error reading X.509 key or certificate file");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -712,7 +712,7 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
/* This might be a reconnect, so we check for a session ID in the cache
|
||||
to speed up things */
|
||||
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
|
||||
/* we got a session id, use it! */
|
||||
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
|
||||
|
||||
@ -825,13 +825,13 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
|
||||
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
|
||||
if(!chainp) {
|
||||
if(data->set.ssl.verifypeer ||
|
||||
data->set.ssl.verifyhost ||
|
||||
if(conn->ssl_config.verifypeer ||
|
||||
conn->ssl_config.verifyhost ||
|
||||
data->set.ssl.issuercert) {
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
|
||||
&& data->set.ssl.username != NULL
|
||||
&& !data->set.ssl.verifypeer
|
||||
&& !conn->ssl_config.verifypeer
|
||||
&& gnutls_cipher_get(session)) {
|
||||
/* no peer cert, but auth is ok if we have SRP user and cipher and no
|
||||
peer verify */
|
||||
@ -864,7 +864,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
/* This function will try to verify the peer's certificate and return its
|
||||
status (trusted, invalid etc.). The value of status should be one or
|
||||
more of the gnutls_certificate_status_t enumerated elements bitwise
|
||||
@ -880,9 +880,10 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
|
||||
/* verify_status is a bitmask of gnutls_certificate_status bits */
|
||||
if(verify_status & GNUTLS_CERT_INVALID) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
failf(data, "server certificate verification failed. CAfile: %s "
|
||||
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
|
||||
"CRLfile: %s", conn->ssl_config.CAfile ? conn->ssl_config.CAfile:
|
||||
"none",
|
||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
||||
return CURLE_SSL_CACERT;
|
||||
}
|
||||
@ -1085,7 +1086,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
if(!rc) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
failf(data, "SSL: certificate subject name (%s) does not match "
|
||||
"target host name '%s'", certbuf, conn->host.dispname);
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
@ -1102,7 +1103,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
failf(data, "server cert expiration date verify failed");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1127,7 +1128,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
|
||||
|
||||
if(certclock == (time_t)-1) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
failf(data, "server cert activation date verify failed");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1245,7 +1246,8 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
/* extract session ID to the allocated buffer */
|
||||
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
|
||||
|
||||
incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
|
||||
sockindex));
|
||||
if(incache) {
|
||||
/* there was one before in the cache, so instead of risking that the
|
||||
previous one was rejected, we just kill that and store the new */
|
||||
@ -1253,7 +1255,8 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* store this session id */
|
||||
result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
|
||||
result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
|
||||
sockindex);
|
||||
if(result) {
|
||||
free(connect_sessionid);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
@ -1508,8 +1511,8 @@ static int Curl_gtls_seed(struct SessionHandle *data)
|
||||
/* Quickly add a bit of entropy */
|
||||
gcry_fast_random_poll();
|
||||
|
||||
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
|
||||
data->set.str[STRING_SSL_EGDSOCKET]) {
|
||||
if(!ssl_seeded || data->set.ssl.primary.random_file ||
|
||||
data->set.ssl.primary.egdsocket) {
|
||||
|
||||
/* TODO: to a good job seeding the RNG
|
||||
This may involve the gcry_control function and these options:
|
||||
|
@ -313,9 +313,8 @@ static int is_file(const char *filename)
|
||||
* should be later deallocated using free(). If the OOM failure occurs, we
|
||||
* return NULL, too.
|
||||
*/
|
||||
static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
|
||||
static char* dup_nickname(struct SessionHandle *data, const char *str)
|
||||
{
|
||||
const char *str = data->set.str[cert_kind];
|
||||
const char *n;
|
||||
|
||||
if(!is_file(str))
|
||||
@ -566,7 +565,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
||||
PK11_IsPresent(slot);
|
||||
|
||||
status = PK11_Authenticate(slot, PR_TRUE,
|
||||
conn->data->set.str[STRING_KEY_PASSWD]);
|
||||
conn->data->set.ssl.key_passwd);
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
|
||||
@ -645,7 +644,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
|
||||
struct connectdata *conn = (struct connectdata *)arg;
|
||||
|
||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
||||
if(conn->data->set.ssl.verifystatus) {
|
||||
if(conn->ssl_config.verifystatus) {
|
||||
SECStatus cacheResult;
|
||||
|
||||
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
|
||||
@ -671,7 +670,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!conn->data->set.ssl.verifypeer) {
|
||||
if(!conn->ssl_config.verifypeer) {
|
||||
infof(conn->data, "skipping SSL peer certificate verification\n");
|
||||
return SECSuccess;
|
||||
}
|
||||
@ -893,7 +892,7 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
|
||||
/* remember the cert verification result */
|
||||
data->set.ssl.certverifyresult = err;
|
||||
|
||||
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
|
||||
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !conn->ssl_config.verifyhost)
|
||||
/* we are asked not to verify the host name */
|
||||
return SECSuccess;
|
||||
|
||||
@ -1399,8 +1398,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
const char *cafile = data->set.ssl.CAfile;
|
||||
const char *capath = data->set.ssl.CApath;
|
||||
const char *cafile = conn->ssl_config.CAfile;
|
||||
const char *capath = conn->ssl_config.CApath;
|
||||
|
||||
if(cafile) {
|
||||
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
|
||||
@ -1450,7 +1449,7 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
static CURLcode nss_init_sslver(SSLVersionRange *sslver,
|
||||
struct SessionHandle *data)
|
||||
{
|
||||
switch(data->set.ssl.version) {
|
||||
switch (conn->ssl_config.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1609,7 +1608,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
goto error;
|
||||
|
||||
/* do not use SSL cache if disabled or we are not going to verify peer */
|
||||
ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
|
||||
ssl_no_cache = (conn->ssl_config.sessionid && conn->ssl_config.verifypeer) ?
|
||||
PR_FALSE : PR_TRUE;
|
||||
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
|
||||
goto error;
|
||||
@ -1620,7 +1619,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
ssl_cbc_random_iv = !data->set.ssl_enable_beast;
|
||||
ssl_cbc_random_iv = !data->set.ssl.enable_beast;
|
||||
#ifdef SSL_CBC_RANDOM_IV
|
||||
/* unless the user explicitly asks to allow the protocol vulnerability, we
|
||||
use the work-around */
|
||||
@ -1632,14 +1631,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
|
||||
#endif
|
||||
|
||||
if(data->set.ssl.cipher_list) {
|
||||
if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
|
||||
if(conn->ssl_config.cipher_list) {
|
||||
if(set_ciphers(data, model, conn->ssl_config.cipher_list) != SECSuccess) {
|
||||
result = CURLE_SSL_CIPHER;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
|
||||
if(!conn->ssl_config.verifypeer && conn->ssl_config.verifyhost)
|
||||
infof(data, "warning: ignoring value of ssl.verifyhost\n");
|
||||
|
||||
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
|
||||
@ -1654,7 +1653,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
|
||||
if(rv) {
|
||||
result = rv;
|
||||
@ -1671,15 +1670,15 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile);
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
char *nickname = dup_nickname(data, STRING_CERT);
|
||||
if(data->set.ssl.cert) {
|
||||
char *nickname = dup_nickname(data, data->set.ssl.cert);
|
||||
if(nickname) {
|
||||
/* we are not going to use libnsspem.so to read the client cert */
|
||||
connssl->obj_clicert = NULL;
|
||||
}
|
||||
else {
|
||||
CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
|
||||
data->set.str[STRING_KEY]);
|
||||
CURLcode rv = cert_stuff(conn, sockindex, data->set.ssl.cert,
|
||||
data->set.ssl.key);
|
||||
if(rv) {
|
||||
/* failf() is already done in cert_stuff() */
|
||||
result = rv;
|
||||
@ -1732,8 +1731,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
model = NULL;
|
||||
|
||||
/* This is the password associated with the cert that we're using */
|
||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
||||
SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
|
||||
if(data->set.ssl.key_passwd) {
|
||||
SSL_SetPKCS11PinArg(connssl->handle, data->set.ssl.key_passwd);
|
||||
}
|
||||
|
||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
||||
@ -1837,11 +1836,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
||||
if(result)
|
||||
goto error;
|
||||
|
||||
if(data->set.str[STRING_SSL_ISSUERCERT]) {
|
||||
if(data->set.ssl.issuercert) {
|
||||
SECStatus ret = SECFailure;
|
||||
char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
|
||||
char *nickname = dup_nickname(data, data->set.ssl.issuercert);
|
||||
if(nickname) {
|
||||
/* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
|
||||
/* we support only nicknames in case of issuercert for now */
|
||||
ret = check_issuer_cert(connssl->handle, nickname);
|
||||
free(nickname);
|
||||
}
|
||||
|
@ -149,6 +149,15 @@
|
||||
*/
|
||||
#define RAND_LOAD_LENGTH 1024
|
||||
|
||||
#define IS_PROXY_SSL() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
|
||||
ssl_connection_complete != conn->proxy_ssl[sockindex].state)
|
||||
|
||||
#define SSL_OPTION(var) (IS_PROXY_SSL() ? data->set.proxy_ssl.var : \
|
||||
data->set.ssl.var)
|
||||
|
||||
#define SSL_OPTION_PRIM(var) (IS_PROXY_SSL() ? \
|
||||
conn->proxy_ssl_config.var : conn->ssl_config.var)
|
||||
|
||||
static int passwd_callback(char *buf, int num, int encrypting,
|
||||
void *global_passwd)
|
||||
{
|
||||
@ -198,13 +207,13 @@ static int ossl_seed(struct SessionHandle *data)
|
||||
#ifndef RANDOM_FILE
|
||||
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
|
||||
us to! */
|
||||
if(data->set.ssl.random_file)
|
||||
if(data->set.ssl.primary.random_file)
|
||||
#define RANDOM_FILE "" /* doesn't matter won't be used */
|
||||
#endif
|
||||
{
|
||||
/* let the option override the define */
|
||||
nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
|
||||
data->set.str[STRING_SSL_RANDOM_FILE]:
|
||||
nread += RAND_load_file((data->set.ssl.primary.random_file?
|
||||
data->set.ssl.primary.random_file:
|
||||
RANDOM_FILE),
|
||||
RAND_LOAD_LENGTH);
|
||||
if(seed_enough(nread))
|
||||
@ -217,14 +226,14 @@ static int ossl_seed(struct SessionHandle *data)
|
||||
#ifndef EGD_SOCKET
|
||||
/* If we don't have the define set, we only do this if the egd-option
|
||||
is set */
|
||||
if(data->set.str[STRING_SSL_EGDSOCKET])
|
||||
if(data->set.ssl.primary.egdsocket)
|
||||
#define EGD_SOCKET "" /* doesn't matter won't be used */
|
||||
#endif
|
||||
{
|
||||
/* If there's an option and a define, the option overrides the
|
||||
define */
|
||||
int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
|
||||
data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
|
||||
int ret = RAND_egd(data->set.ssl.primary.egdsocket?
|
||||
data->set.ssl.primary.egdsocket:EGD_SOCKET);
|
||||
if(-1 != ret) {
|
||||
nread += ret;
|
||||
if(seed_enough(nread))
|
||||
@ -262,8 +271,8 @@ static void Curl_ossl_seed(struct SessionHandle *data)
|
||||
time-consuming seedings in vain */
|
||||
static bool ssl_seeded = FALSE;
|
||||
|
||||
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
|
||||
data->set.str[STRING_SSL_EGDSOCKET]) {
|
||||
if(!ssl_seeded || data->set.ssl.primary.random_file ||
|
||||
data->set.ssl.primary.egdsocket) {
|
||||
ossl_seed(data);
|
||||
ssl_seeded = TRUE;
|
||||
}
|
||||
@ -343,7 +352,8 @@ int cert_stuff(struct connectdata *conn,
|
||||
char *cert_file,
|
||||
const char *cert_type,
|
||||
char *key_file,
|
||||
const char *key_type)
|
||||
const char *key_type,
|
||||
char *key_passwd)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
@ -354,10 +364,9 @@ int cert_stuff(struct connectdata *conn,
|
||||
X509 *x509;
|
||||
int cert_done = 0;
|
||||
|
||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
||||
if(key_passwd) {
|
||||
/* set the password in the callback userdata */
|
||||
SSL_CTX_set_default_passwd_cb_userdata(ctx,
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
|
||||
/* Set passwd callback: */
|
||||
SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
|
||||
}
|
||||
@ -467,7 +476,7 @@ int cert_stuff(struct connectdata *conn,
|
||||
|
||||
PKCS12_PBE_add();
|
||||
|
||||
if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
|
||||
if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
|
||||
&ca)) {
|
||||
failf(data,
|
||||
"could not parse PKCS12 file, check password, OpenSSL error %s",
|
||||
@ -579,7 +588,7 @@ int cert_stuff(struct connectdata *conn,
|
||||
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||
ui_method,
|
||||
#endif
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
key_passwd);
|
||||
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||
UI_destroy_method(ui_method);
|
||||
#endif
|
||||
@ -871,13 +880,8 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is called when an SSL connection is closed.
|
||||
*/
|
||||
void Curl_ossl_close(struct connectdata *conn, int sockindex)
|
||||
static void ossl_close(struct ssl_connect_data *connssl)
|
||||
{
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
|
||||
if(connssl->handle) {
|
||||
(void)SSL_shutdown(connssl->handle);
|
||||
SSL_set_connect_state(connssl->handle);
|
||||
@ -891,6 +895,15 @@ void Curl_ossl_close(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when an SSL connection is closed.
|
||||
*/
|
||||
void Curl_ossl_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
ossl_close(&conn->ssl[sockindex]);
|
||||
ossl_close(&conn->proxy_ssl[sockindex]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called to shut down the SSL layer but keep the
|
||||
* socket open (CCC - Clear Command Channel)
|
||||
@ -1082,7 +1095,8 @@ static int asn1_output(const ASN1_UTCTIME *tm,
|
||||
in the certificate and must exactly match the IP in the URI.
|
||||
|
||||
*/
|
||||
static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
static CURLcode verifyhost(struct connectdata *conn,
|
||||
X509 *server_cert, const int sockindex)
|
||||
{
|
||||
int matched = -1; /* -1 is no alternative match yet, 1 means match and 0
|
||||
means mismatch */
|
||||
@ -1096,16 +1110,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
const char * const hostname = IS_PROXY_SSL() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const char * const dispname = IS_PROXY_SSL() ?
|
||||
conn->http_proxy.host.dispname : conn->host.dispname;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
if(conn->bits.ipv6_ip &&
|
||||
Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
|
||||
Curl_inet_pton(AF_INET6, hostname, &addr)) {
|
||||
target = GEN_IPADD;
|
||||
addrlen = sizeof(struct in6_addr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
|
||||
if(Curl_inet_pton(AF_INET, hostname, &addr)) {
|
||||
target = GEN_IPADD;
|
||||
addrlen = sizeof(struct in_addr);
|
||||
}
|
||||
@ -1147,7 +1165,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
if((altlen == strlen(altptr)) &&
|
||||
/* if this isn't true, there was an embedded zero in the name
|
||||
string and we cannot match it. */
|
||||
Curl_cert_hostcheck(altptr, conn->host.name))
|
||||
Curl_cert_hostcheck(altptr, hostname))
|
||||
matched = 1;
|
||||
else
|
||||
matched = 0;
|
||||
@ -1169,13 +1187,13 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
|
||||
if(matched == 1)
|
||||
/* an alternative name matched the server hostname */
|
||||
infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
|
||||
infof(data, "\t subjectAltName: %s matched\n", dispname);
|
||||
else if(matched == 0) {
|
||||
/* an alternative name field existed, but didn't match and then
|
||||
we MUST fail */
|
||||
infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
|
||||
infof(data, "\t subjectAltName does not match %s\n", dispname);
|
||||
failf(data, "SSL: no alternative certificate subject name matches "
|
||||
"target host name '%s'", conn->host.dispname);
|
||||
"target host name '%s'", dispname);
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else {
|
||||
@ -1249,9 +1267,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
"SSL: unable to obtain common name from peer certificate");
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
||||
else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
|
||||
failf(data, "SSL: certificate subject name '%s' does not match "
|
||||
"target host name '%s'", peer_CN, conn->host.dispname);
|
||||
"target host name '%s'", peer_CN, dispname);
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else {
|
||||
@ -1688,17 +1706,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif
|
||||
long * const certverifyresult = IS_PROXY_SSL() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
const long int ssl_version = SSL_OPTION_PRIM(version);
|
||||
#ifdef USE_TLS_SRP
|
||||
const enum CURL_TLSAUTH ssl_authtype = SSL_OPTION(authtype);
|
||||
#endif
|
||||
char * const ssl_cert = SSL_OPTION(cert);
|
||||
const char * const ssl_cert_type = SSL_OPTION(cert_type);
|
||||
const char * const ssl_cafile = SSL_OPTION_PRIM(CAfile);
|
||||
const char * const ssl_capath = SSL_OPTION_PRIM(CApath);
|
||||
const bool verifypeer = SSL_OPTION_PRIM(verifypeer);
|
||||
const char * const ssl_crlfile = SSL_OPTION(CRLfile);
|
||||
const char * const hostname = IS_PROXY_SSL() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
|
||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||
|
||||
/* Make funny stuff to get random input */
|
||||
Curl_ossl_seed(data);
|
||||
|
||||
data->set.ssl.certverifyresult = !X509_V_OK;
|
||||
*certverifyresult = !X509_V_OK;
|
||||
|
||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||
|
||||
switch(data->set.ssl.version) {
|
||||
switch(ssl_version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1720,7 +1751,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#else
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
|
||||
if(ssl_authtype == CURL_TLSAUTH_SRP)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
#endif
|
||||
req_method = SSLv2_client_method();
|
||||
@ -1733,7 +1764,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#else
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
|
||||
if(ssl_authtype == CURL_TLSAUTH_SRP)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
#endif
|
||||
req_method = SSLv3_client_method();
|
||||
@ -1818,14 +1849,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
|
||||
/* unless the user explicitly ask to allow the protocol vulnerability we
|
||||
use the work-around */
|
||||
if(!conn->data->set.ssl_enable_beast)
|
||||
if(!SSL_OPTION(enable_beast))
|
||||
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
#endif
|
||||
|
||||
switch(data->set.ssl.version) {
|
||||
switch(ssl_version) {
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
|
||||
if(ssl_authtype == CURL_TLSAUTH_SRP) {
|
||||
infof(data, "Set version TLSv1.x for SRP authorisation\n");
|
||||
}
|
||||
#endif
|
||||
@ -1919,19 +1950,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
||||
if(!cert_stuff(conn,
|
||||
connssl->ctx,
|
||||
data->set.str[STRING_CERT],
|
||||
data->set.str[STRING_CERT_TYPE],
|
||||
data->set.str[STRING_KEY],
|
||||
data->set.str[STRING_KEY_TYPE])) {
|
||||
if(ssl_cert || ssl_cert_type) {
|
||||
if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
|
||||
SSL_OPTION(key), SSL_OPTION(key_type),
|
||||
SSL_OPTION(key_passwd))) {
|
||||
/* failf() is already done in cert_stuff() */
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
|
||||
ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
ciphers = SSL_OPTION_PRIM(cipher_list);
|
||||
if(!ciphers)
|
||||
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
|
||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
|
||||
@ -1941,18 +1969,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof(data, "Cipher selection: %s\n", ciphers);
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
|
||||
infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
|
||||
if(ssl_authtype == CURL_TLSAUTH_SRP) {
|
||||
char * const ssl_username = SSL_OPTION(username);
|
||||
|
||||
if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
|
||||
infof(data, "Using TLS-SRP username: %s\n", ssl_username);
|
||||
|
||||
if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
|
||||
failf(data, "Unable to set SRP user name");
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) {
|
||||
if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_OPTION(password))) {
|
||||
failf(data, "failed setting SRP password");
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
|
||||
if(!SSL_OPTION_PRIM(cipher_list)) {
|
||||
infof(data, "Setting cipher list SRP\n");
|
||||
|
||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
|
||||
@ -1962,20 +1992,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
|
||||
|
||||
if(ssl_cafile || ssl_capath) {
|
||||
/* tell SSL where to find CA certificates that are used to verify
|
||||
the servers certificate. */
|
||||
if(!SSL_CTX_load_verify_locations(connssl->ctx,
|
||||
data->set.str[STRING_SSL_CAFILE],
|
||||
data->set.str[STRING_SSL_CAPATH])) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
|
||||
if(verifypeer) {
|
||||
/* Fail if we insist on successfully verifying the server. */
|
||||
failf(data, "error setting certificate verify locations:\n"
|
||||
" CAfile: %s\n CApath: %s",
|
||||
data->set.str[STRING_SSL_CAFILE]?
|
||||
data->set.str[STRING_SSL_CAFILE]: "none",
|
||||
data->set.str[STRING_SSL_CAPATH]?
|
||||
data->set.str[STRING_SSL_CAPATH] : "none");
|
||||
ssl_cafile ? ssl_cafile : "none",
|
||||
ssl_capath ? ssl_capath : "none");
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else {
|
||||
@ -1992,22 +2019,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof(data,
|
||||
" CAfile: %s\n"
|
||||
" CApath: %s\n",
|
||||
data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
|
||||
"none",
|
||||
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
|
||||
"none");
|
||||
ssl_cafile ? ssl_cafile : "none",
|
||||
ssl_capath ? ssl_capath : "none");
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
if(ssl_crlfile) {
|
||||
/* tell SSL where to find CRL file that is used to check certificate
|
||||
* revocation */
|
||||
lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
|
||||
X509_LOOKUP_file());
|
||||
if(!lookup ||
|
||||
(!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
|
||||
X509_FILETYPE_PEM)) ) {
|
||||
failf(data, "error loading CRL file: %s",
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
(!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
|
||||
failf(data, "error loading CRL file: %s", ssl_crlfile);
|
||||
return CURLE_SSL_CRL_BADFILE;
|
||||
}
|
||||
else {
|
||||
@ -2016,9 +2039,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
|
||||
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
|
||||
}
|
||||
infof(data,
|
||||
" CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
|
||||
data->set.str[STRING_SSL_CRLFILE]: "none");
|
||||
infof(data, " CRLfile: %s\n", ssl_crlfile ? ssl_crlfile: "none");
|
||||
}
|
||||
|
||||
/* Try building a chain using issuers in the trusted store first to avoid
|
||||
@ -2040,8 +2061,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
* anyway. In the latter case the result of the verification is checked with
|
||||
* SSL_get_verify_result() below. */
|
||||
SSL_CTX_set_verify(connssl->ctx,
|
||||
data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
|
||||
NULL);
|
||||
verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
||||
|
||||
/* give application a chance to interfere with SSL set up. */
|
||||
if(data->set.ssl.fsslctx) {
|
||||
@ -2064,27 +2084,26 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||
!defined(OPENSSL_IS_BORINGSSL)
|
||||
if(data->set.ssl.verifystatus)
|
||||
if(SSL_OPTION_PRIM(verifystatus))
|
||||
SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
|
||||
#endif
|
||||
|
||||
SSL_set_connect_state(connssl->handle);
|
||||
|
||||
connssl->server_cert = 0x0;
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
|
||||
if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
|
||||
#ifdef ENABLE_IPV6
|
||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
|
||||
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
|
||||
#endif
|
||||
sni &&
|
||||
!SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
|
||||
!SSL_set_tlsext_host_name(connssl->handle, hostname))
|
||||
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||
"TLS extension\n");
|
||||
#endif
|
||||
|
||||
/* Check if there's a cached ID we can/should use here! */
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
|
||||
/* we got a session id, use it! */
|
||||
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
|
||||
failf(data, "SSL: SSL_set_session failed: %s",
|
||||
@ -2095,8 +2114,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof (data, "SSL re-using session ID\n");
|
||||
}
|
||||
|
||||
/* pass the raw socket into the SSL layers */
|
||||
if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
|
||||
if(conn->proxy_ssl[sockindex].use) {
|
||||
BIO *const bio = BIO_new(BIO_f_ssl());
|
||||
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
|
||||
DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
|
||||
DEBUGASSERT(bio != NULL);
|
||||
BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
|
||||
SSL_set_bio(connssl->handle, bio, bio);
|
||||
}
|
||||
else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
|
||||
/* pass the raw socket into the SSL layers */
|
||||
failf(data, "SSL: SSL_set_fd failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -2189,8 +2216,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
* the SO_ERROR is also lost.
|
||||
*/
|
||||
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
|
||||
const char * const hostname = IS_PROXY_SSL() ?
|
||||
conn->http_proxy.host.name : conn->host.name;
|
||||
const long int port = IS_PROXY_SSL() ? conn->port : conn->remote_port;
|
||||
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
|
||||
conn->host.name, conn->remote_port);
|
||||
hostname, port);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2626,7 +2656,8 @@ static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
|
||||
*/
|
||||
static CURLcode servercert(struct connectdata *conn,
|
||||
struct ssl_connect_data *connssl,
|
||||
bool strict)
|
||||
bool strict,
|
||||
const int sockindex)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
int rc;
|
||||
@ -2637,6 +2668,8 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
FILE *fp;
|
||||
char *buffer = data->state.buffer;
|
||||
const char *ptr;
|
||||
long * const certverifyresult = IS_PROXY_SSL() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
|
||||
if(data->set.ssl.certinfo)
|
||||
/* we've been asked to gather certificate info! */
|
||||
@ -2649,7 +2682,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
infof(data, "Server certificate:\n");
|
||||
infof(data, "%s certificate:\n", IS_PROXY_SSL() ? "Proxy" : "Server");
|
||||
|
||||
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
||||
buffer, BUFSIZE);
|
||||
@ -2663,8 +2696,8 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
asn1_output(certdate, buffer, BUFSIZE);
|
||||
infof(data, "\t expire date: %s\n", buffer);
|
||||
|
||||
if(data->set.ssl.verifyhost) {
|
||||
result = verifyhost(conn, connssl->server_cert);
|
||||
if(SSL_OPTION_PRIM(verifyhost)) {
|
||||
result = verifyhost(conn, connssl->server_cert, sockindex);
|
||||
if(result) {
|
||||
X509_free(connssl->server_cert);
|
||||
connssl->server_cert = NULL;
|
||||
@ -2686,12 +2719,12 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
deallocating the certificate. */
|
||||
|
||||
/* e.g. match issuer name with provided issuer certificate */
|
||||
if(data->set.str[STRING_SSL_ISSUERCERT]) {
|
||||
fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT);
|
||||
if(data->set.ssl.issuercert) {
|
||||
fp = fopen(data->set.ssl.issuercert, FOPEN_READTEXT);
|
||||
if(!fp) {
|
||||
if(strict)
|
||||
failf(data, "SSL: Unable to open issuer cert (%s)",
|
||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
||||
data->set.ssl.issuercert);
|
||||
X509_free(connssl->server_cert);
|
||||
connssl->server_cert = NULL;
|
||||
return CURLE_SSL_ISSUER_ERROR;
|
||||
@ -2701,7 +2734,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
if(!issuer) {
|
||||
if(strict)
|
||||
failf(data, "SSL: Unable to read issuer cert (%s)",
|
||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
||||
data->set.ssl.issuercert);
|
||||
X509_free(connssl->server_cert);
|
||||
X509_free(issuer);
|
||||
fclose(fp);
|
||||
@ -2713,7 +2746,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
|
||||
if(strict)
|
||||
failf(data, "SSL: Certificate issuer check failed (%s)",
|
||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
||||
data->set.ssl.issuercert);
|
||||
X509_free(connssl->server_cert);
|
||||
X509_free(issuer);
|
||||
connssl->server_cert = NULL;
|
||||
@ -2721,15 +2754,14 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
}
|
||||
|
||||
infof(data, "\t SSL certificate issuer check ok (%s)\n",
|
||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
||||
data->set.ssl.issuercert);
|
||||
X509_free(issuer);
|
||||
}
|
||||
|
||||
lerr = data->set.ssl.certverifyresult =
|
||||
SSL_get_verify_result(connssl->handle);
|
||||
lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
|
||||
|
||||
if(data->set.ssl.certverifyresult != X509_V_OK) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(*certverifyresult != X509_V_OK) {
|
||||
if(SSL_OPTION_PRIM(verifypeer)) {
|
||||
/* We probably never reach this, because SSL_connect() will fail
|
||||
and we return earlier if verifypeer is set? */
|
||||
if(strict)
|
||||
@ -2748,7 +2780,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||
!defined(OPENSSL_IS_BORINGSSL)
|
||||
if(data->set.ssl.verifystatus) {
|
||||
if(SSL_OPTION_PRIM(verifystatus)) {
|
||||
result = verifystatus(conn, connssl);
|
||||
if(result) {
|
||||
X509_free(connssl->server_cert);
|
||||
@ -2793,7 +2825,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
|
||||
will stay in memory until explicitly freed with SSL_SESSION_free(3),
|
||||
regardless of its state. */
|
||||
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
|
||||
sockindex));
|
||||
if(incache) {
|
||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||
infof(data, "old SSL session ID is stale, removing\n");
|
||||
@ -2804,7 +2837,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
|
||||
|
||||
if(!incache) {
|
||||
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
||||
0 /* unknown size */);
|
||||
0 /* unknown size */, sockindex);
|
||||
if(result) {
|
||||
failf(data, "failed to store ssl session");
|
||||
return result;
|
||||
@ -2825,8 +2858,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
|
||||
* operations.
|
||||
*/
|
||||
|
||||
result = servercert(conn, connssl,
|
||||
(data->set.ssl.verifypeer || data->set.ssl.verifyhost));
|
||||
result = servercert(conn, connssl, (SSL_OPTION_PRIM(verifypeer) ||
|
||||
SSL_OPTION_PRIM(verifyhost)), sockindex);
|
||||
|
||||
if(!result)
|
||||
connssl->connecting_state = ssl_connect_done;
|
||||
@ -2973,7 +3006,10 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
|
||||
{
|
||||
if(conn->ssl[connindex].handle)
|
||||
/* SSL is in use */
|
||||
return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
|
||||
return (0 != SSL_pending(conn->ssl[connindex].handle) ||
|
||||
(conn->proxy_ssl[connindex].handle &&
|
||||
0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
|
||||
TRUE : FALSE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@ -3018,8 +3054,18 @@ static ssize_t ossl_send(struct connectdata *conn,
|
||||
/* A failure in the SSL library occurred, usually a protocol error.
|
||||
The OpenSSL error queue contains more information on the error. */
|
||||
sslerror = ERR_get_error();
|
||||
failf(conn->data, "SSL_write() error: %s",
|
||||
ERR_error_string(sslerror, error_buffer));
|
||||
if(sslerror ==
|
||||
ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_WRITE_PENDING, SSL_R_BIO_NOT_SET) &&
|
||||
conn->ssl[sockindex].state == ssl_connection_complete &&
|
||||
conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
|
||||
char ver[120];
|
||||
Curl_ossl_version(ver, 120);
|
||||
failf(conn->data, "Error: %s does not support double SSL tunneling.",
|
||||
ver);
|
||||
}
|
||||
else
|
||||
failf(conn->data, "SSL_write() error: %s",
|
||||
ERR_error_string(sslerror, error_buffer));
|
||||
*curlcode = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
@ -146,11 +146,11 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
errorbuf[0]=0;
|
||||
|
||||
/* PolarSSL only supports SSLv3 and TLSv1 */
|
||||
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
|
||||
if(conn->ssl_config.version == CURL_SSLVERSION_SSLv2) {
|
||||
failf(data, "PolarSSL does not support SSLv2");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
|
||||
else if(conn->ssl_config.version == CURL_SSLVERSION_SSLv3)
|
||||
sni = FALSE; /* SSLv3 has no SNI */
|
||||
|
||||
#ifdef THREADING_SUPPORT
|
||||
@ -180,18 +180,18 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
/* Load the trusted CA */
|
||||
memset(&connssl->cacert, 0, sizeof(x509_crt));
|
||||
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
if(conn->ssl_config.CAfile) {
|
||||
ret = x509_crt_parse_file(&connssl->cacert,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
conn->ssl_config.CAfile);
|
||||
|
||||
if(ret<0) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
#endif /* POLARSSL_ERROR_C */
|
||||
failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
|
||||
data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
|
||||
conn->ssl_config.CAfile, -ret, errorbuf);
|
||||
|
||||
if(data->set.ssl.verifypeer)
|
||||
if(conn->ssl_config.verifypeer)
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
@ -215,27 +215,27 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
/* Load the client certificate */
|
||||
memset(&connssl->clicert, 0, sizeof(x509_crt));
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
if(data->set.ssl.cert) {
|
||||
ret = x509_crt_parse_file(&connssl->clicert,
|
||||
data->set.str[STRING_CERT]);
|
||||
data->set.ssl.cert);
|
||||
|
||||
if(ret) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
#endif /* POLARSSL_ERROR_C */
|
||||
failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
|
||||
data->set.str[STRING_CERT], -ret, errorbuf);
|
||||
data->set.ssl.cert, -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the client private key */
|
||||
if(data->set.str[STRING_KEY]) {
|
||||
if(data->set.ssl.key) {
|
||||
pk_context pk;
|
||||
pk_init(&pk);
|
||||
ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
ret = pk_parse_keyfile(&pk, data->set.ssl.key,
|
||||
data->set.ssl.key_passwd);
|
||||
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
if(ret == 0)
|
||||
@ -249,7 +249,7 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
#endif /* POLARSSL_ERROR_C */
|
||||
failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
|
||||
data->set.str[STRING_KEY], -ret, errorbuf);
|
||||
data->set.ssl.key, -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
@ -258,16 +258,16 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
/* Load the CRL */
|
||||
memset(&connssl->crl, 0, sizeof(x509_crl));
|
||||
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
if(data->set.ssl.CRLfile) {
|
||||
ret = x509_crl_parse_file(&connssl->crl,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
data->set.ssl.CRLfile);
|
||||
|
||||
if(ret) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
#endif /* POLARSSL_ERROR_C */
|
||||
failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
|
||||
data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
|
||||
data->set.ssl.CRLfile, -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CRL_BADFILE;
|
||||
}
|
||||
@ -328,7 +328,8 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
net_send, &conn->sock[sockindex]);
|
||||
|
||||
ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
|
||||
if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
|
||||
if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size,
|
||||
sockindex)) {
|
||||
memcpy(&connssl->ssn, old_session, old_session_size);
|
||||
infof(data, "PolarSSL re-using session\n");
|
||||
}
|
||||
@ -426,7 +427,7 @@ polarssl_connect_step2(struct connectdata *conn,
|
||||
|
||||
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
|
||||
|
||||
if(ret && data->set.ssl.verifypeer) {
|
||||
if(ret && conn->ssl_config.verifypeer) {
|
||||
if(ret & BADCERT_EXPIRED)
|
||||
failf(data, "Cert verify failed: BADCERT_EXPIRED");
|
||||
|
||||
@ -496,7 +497,8 @@ polarssl_connect_step3(struct connectdata *conn,
|
||||
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
|
||||
|
||||
/* Save the current session data for possible re-use */
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
|
||||
sockindex));
|
||||
if(incache) {
|
||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||
infof(data, "old SSL session ID is stale, removing\n");
|
||||
@ -511,7 +513,8 @@ polarssl_connect_step3(struct connectdata *conn,
|
||||
if(new_session) {
|
||||
memcpy(new_session, our_ssl_sessionid, sizeof(ssl_session));
|
||||
|
||||
result = Curl_ssl_addsessionid(conn, new_session, sizeof(ssl_session));
|
||||
result = Curl_ssl_addsessionid(conn, new_session,
|
||||
sizeof(ssl_session), sockindex);
|
||||
}
|
||||
else
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
@ -111,7 +111,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
conn->host.name, conn->remote_port);
|
||||
|
||||
/* check for an existing re-usable credential handle */
|
||||
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) {
|
||||
if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
|
||||
connssl->cred = old_cred;
|
||||
infof(data, "schannel: re-using existing credential handle\n");
|
||||
}
|
||||
@ -120,7 +120,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
memset(&schannel_cred, 0, sizeof(schannel_cred));
|
||||
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(conn->ssl_config.verifypeer) {
|
||||
#ifdef _WIN32_WCE
|
||||
/* certificate validation on CE doesn't seem to work right; we'll
|
||||
do it following a more manual process. */
|
||||
@ -140,14 +140,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof(data, "schannel: disable server certificate revocation checks\n");
|
||||
}
|
||||
|
||||
if(!data->set.ssl.verifyhost) {
|
||||
if(!conn->ssl_config.verifyhost) {
|
||||
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||
infof(data, "schannel: verifyhost setting prevents Schannel from "
|
||||
"comparing the supplied target name with the subject "
|
||||
"names in server certificates. Also disables SNI.\n");
|
||||
}
|
||||
|
||||
switch(data->set.ssl.version) {
|
||||
switch(conn->ssl_config.version) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -512,7 +512,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
||||
#ifdef _WIN32_WCE
|
||||
/* Windows CE doesn't do any server certificate validation.
|
||||
We have to do it manually. */
|
||||
if(data->set.ssl.verifypeer)
|
||||
if(conn->ssl_config.verifypeer)
|
||||
return verify_certificate(conn, sockindex);
|
||||
#endif
|
||||
|
||||
@ -559,7 +559,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
|
||||
/* save the current session data for possible re-use */
|
||||
incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL));
|
||||
incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
|
||||
sockindex));
|
||||
if(incache) {
|
||||
if(old_cred != connssl->cred) {
|
||||
infof(data, "schannel: old credential handle is stale, removing\n");
|
||||
@ -570,7 +571,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
|
||||
|
||||
if(!incache) {
|
||||
result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
|
||||
sizeof(struct curl_schannel_cred));
|
||||
sizeof(struct curl_schannel_cred),
|
||||
sockindex);
|
||||
if(result) {
|
||||
failf(data, "schannel: failed to store credential handle");
|
||||
return result;
|
||||
@ -1416,7 +1418,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
|
||||
if(result == CURLE_OK) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(conn->ssl_config.verifyhost) {
|
||||
TCHAR cert_hostname_buff[128];
|
||||
xcharp_u hostname;
|
||||
xcharp_u cert_hostname;
|
||||
|
248
lib/vtls/vtls.c
248
lib/vtls/vtls.c
@ -65,6 +65,7 @@
|
||||
#include "url.h"
|
||||
#include "progress.h"
|
||||
#include "share.h"
|
||||
#include "multiif.h"
|
||||
#include "timeval.h"
|
||||
#include "curl_md5.h"
|
||||
#include "warnless.h"
|
||||
@ -80,86 +81,84 @@
|
||||
(data->share->specifier & \
|
||||
(1<<CURL_LOCK_DATA_SSL_SESSION)))
|
||||
|
||||
static bool safe_strequal(char* str1, char* str2)
|
||||
{
|
||||
if(str1 && str2)
|
||||
/* both pointers point to something then compare them */
|
||||
return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
|
||||
else
|
||||
/* if both pointers are NULL then treat them as equal */
|
||||
return (!str1 && !str2) ? TRUE : FALSE;
|
||||
}
|
||||
#define CLONE_STRING(var) if(source->var) { \
|
||||
dest->var = strdup(source->var); \
|
||||
if(!dest->var) \
|
||||
return FALSE; \
|
||||
} \
|
||||
else \
|
||||
dest->var = NULL;
|
||||
|
||||
bool
|
||||
Curl_ssl_config_matches(struct ssl_config_data* data,
|
||||
struct ssl_config_data* needle)
|
||||
Curl_ssl_config_matches(struct ssl_primary_config* data,
|
||||
struct ssl_primary_config* needle)
|
||||
{
|
||||
if((data->version == needle->version) &&
|
||||
(data->verifypeer == needle->verifypeer) &&
|
||||
(data->verifyhost == needle->verifyhost) &&
|
||||
safe_strequal(data->CApath, needle->CApath) &&
|
||||
safe_strequal(data->CAfile, needle->CAfile) &&
|
||||
safe_strequal(data->random_file, needle->random_file) &&
|
||||
safe_strequal(data->egdsocket, needle->egdsocket) &&
|
||||
safe_strequal(data->cipher_list, needle->cipher_list))
|
||||
Curl_safe_strequal(data->CApath, needle->CApath) &&
|
||||
Curl_safe_strequal(data->CAfile, needle->CAfile) &&
|
||||
Curl_safe_strequal(data->random_file, needle->random_file) &&
|
||||
Curl_safe_strequal(data->egdsocket, needle->egdsocket) &&
|
||||
Curl_safe_strequal(data->cipher_list, needle->cipher_list))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
Curl_clone_general_ssl_config(struct ssl_general_config *source,
|
||||
struct ssl_general_config *dest)
|
||||
{
|
||||
dest->sessionid = source->sessionid;
|
||||
dest->max_ssl_sessions = source->max_ssl_sessions;
|
||||
}
|
||||
|
||||
bool
|
||||
Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
|
||||
struct ssl_primary_config *dest)
|
||||
{
|
||||
dest->verifyhost = source->verifyhost;
|
||||
dest->verifypeer = source->verifypeer;
|
||||
dest->version = source->version;
|
||||
|
||||
CLONE_STRING(CAfile);
|
||||
CLONE_STRING(CApath);
|
||||
CLONE_STRING(cipher_list);
|
||||
CLONE_STRING(egdsocket);
|
||||
CLONE_STRING(random_file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
Curl_clone_ssl_config(struct ssl_config_data *source,
|
||||
struct ssl_config_data *dest)
|
||||
{
|
||||
dest->sessionid = source->sessionid;
|
||||
dest->verifyhost = source->verifyhost;
|
||||
dest->verifypeer = source->verifypeer;
|
||||
dest->version = source->version;
|
||||
Curl_clone_primary_ssl_config(&source->primary, &dest->primary);
|
||||
dest->enable_beast = source->enable_beast;
|
||||
dest->certverifyresult = source->certverifyresult;
|
||||
dest->fsslctx = source->fsslctx;
|
||||
dest->fsslctxp = source->fsslctxp;
|
||||
dest->certinfo = source->certinfo;
|
||||
|
||||
if(source->CAfile) {
|
||||
dest->CAfile = strdup(source->CAfile);
|
||||
if(!dest->CAfile)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
dest->CAfile = NULL;
|
||||
CLONE_STRING(CRLfile);
|
||||
CLONE_STRING(issuercert);
|
||||
CLONE_STRING(cert);
|
||||
CLONE_STRING(cert_type);
|
||||
CLONE_STRING(key);
|
||||
CLONE_STRING(key_type);
|
||||
CLONE_STRING(key_passwd);
|
||||
|
||||
if(source->CApath) {
|
||||
dest->CApath = strdup(source->CApath);
|
||||
if(!dest->CApath)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
dest->CApath = NULL;
|
||||
|
||||
if(source->cipher_list) {
|
||||
dest->cipher_list = strdup(source->cipher_list);
|
||||
if(!dest->cipher_list)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
dest->cipher_list = NULL;
|
||||
|
||||
if(source->egdsocket) {
|
||||
dest->egdsocket = strdup(source->egdsocket);
|
||||
if(!dest->egdsocket)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
dest->egdsocket = NULL;
|
||||
|
||||
if(source->random_file) {
|
||||
dest->random_file = strdup(source->random_file);
|
||||
if(!dest->random_file)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
dest->random_file = NULL;
|
||||
#ifdef USE_TLS_SRP
|
||||
CLONE_STRING(username);
|
||||
CLONE_STRING(password);
|
||||
dest->authtype = source->authtype;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Curl_free_ssl_config(struct ssl_config_data* sslc)
|
||||
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
|
||||
{
|
||||
Curl_safefree(sslc->CAfile);
|
||||
Curl_safefree(sslc->CApath);
|
||||
@ -244,6 +243,23 @@ int Curl_ssl_backend(void)
|
||||
return (int)CURL_SSL_BACKEND;
|
||||
}
|
||||
|
||||
void Curl_free_ssl_config(struct ssl_config_data* sslc)
|
||||
{
|
||||
Curl_free_primary_ssl_config(&sslc->primary);
|
||||
|
||||
Curl_safefree(sslc->CRLfile);
|
||||
Curl_safefree(sslc->issuercert);
|
||||
Curl_safefree(sslc->cert);
|
||||
Curl_safefree(sslc->cert_type);
|
||||
Curl_safefree(sslc->key);
|
||||
Curl_safefree(sslc->key_type);
|
||||
Curl_safefree(sslc->key_passwd);
|
||||
#ifdef USE_TLS_SRP
|
||||
Curl_safefree(sslc->username);
|
||||
Curl_safefree(sslc->password);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
/* "global" init done? */
|
||||
@ -279,19 +295,40 @@ void Curl_ssl_cleanup(void)
|
||||
static bool ssl_prefs_check(struct SessionHandle *data)
|
||||
{
|
||||
/* check for CURLOPT_SSLVERSION invalid parameter value */
|
||||
if((data->set.ssl.version < 0)
|
||||
|| (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
|
||||
if((data->set.ssl.primary.version < 0)
|
||||
|| (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
|
||||
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CURLcode
|
||||
ssl_connect_init_proxy(struct connectdata *conn, int sockindex) {
|
||||
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
|
||||
if(ssl_connection_complete == conn->ssl[sockindex].state &&
|
||||
!conn->proxy_ssl[sockindex].use) {
|
||||
#ifdef USE_OPENSSL
|
||||
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
|
||||
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
|
||||
#else
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
#endif
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode
|
||||
Curl_ssl_connect(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
if(conn->bits.proxy_ssl_connected[sockindex]) {
|
||||
result = ssl_connect_init_proxy(conn, sockindex);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!ssl_prefs_check(conn->data))
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
@ -312,6 +349,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
if(conn->bits.proxy_ssl_connected[sockindex]) {
|
||||
result = ssl_connect_init_proxy(conn, sockindex);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!ssl_prefs_check(conn->data))
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -335,7 +377,8 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
|
||||
*/
|
||||
bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||
void **ssl_sessionid,
|
||||
size_t *idsize) /* set 0 if unknown */
|
||||
size_t *idsize, /* set 0 if unknown */
|
||||
int sockindex)
|
||||
{
|
||||
struct curl_ssl_session *check;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@ -343,9 +386,16 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||
long *general_age;
|
||||
bool no_match = TRUE;
|
||||
|
||||
const bool isProxy = CONNECT_PROXY_SSL();
|
||||
struct ssl_primary_config * const ssl_config = isProxy ?
|
||||
&conn->proxy_ssl_config :
|
||||
&conn->ssl_config;
|
||||
const char * const name = isProxy ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
int port = isProxy ? (int)conn->port : conn->remote_port;
|
||||
*ssl_sessionid = NULL;
|
||||
|
||||
if(!conn->ssl_config.sessionid)
|
||||
if(!data->set.general_ssl.sessionid)
|
||||
/* session ID re-use is disabled */
|
||||
return TRUE;
|
||||
|
||||
@ -357,14 +407,14 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||
else
|
||||
general_age = &data->state.sessionage;
|
||||
|
||||
for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
|
||||
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
|
||||
check = &data->state.session[i];
|
||||
if(!check->sessionid)
|
||||
/* not session ID means blank entry */
|
||||
continue;
|
||||
if(Curl_raw_equal(conn->host.name, check->name) &&
|
||||
(conn->remote_port == check->remote_port) &&
|
||||
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
|
||||
if(Curl_raw_equal(name, check->name) &&
|
||||
(port == check->remote_port) &&
|
||||
Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
|
||||
/* yes, we have a session ID! */
|
||||
(*general_age)++; /* increase general age */
|
||||
check->age = *general_age; /* set this as used in this age */
|
||||
@ -397,7 +447,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
|
||||
session->sessionid = NULL;
|
||||
session->age = 0; /* fresh */
|
||||
|
||||
Curl_free_ssl_config(&session->ssl_config);
|
||||
Curl_free_primary_ssl_config(&session->ssl_config);
|
||||
|
||||
Curl_safefree(session->name);
|
||||
}
|
||||
@ -414,7 +464,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
|
||||
if(SSLSESSION_SHARED(data))
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
|
||||
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
|
||||
struct curl_ssl_session *check = &data->state.session[i];
|
||||
|
||||
if(check->sessionid == ssl_sessionid) {
|
||||
@ -435,7 +485,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
|
||||
*/
|
||||
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||
void *ssl_sessionid,
|
||||
size_t idsize)
|
||||
size_t idsize,
|
||||
int sockindex)
|
||||
{
|
||||
size_t i;
|
||||
struct SessionHandle *data=conn->data; /* the mother of all structs */
|
||||
@ -448,7 +499,12 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||
IT. We still store it here in case the re-using is again enabled for an
|
||||
upcoming transfer */
|
||||
|
||||
clone_host = strdup(conn->host.name);
|
||||
const bool isProxy = CONNECT_PROXY_SSL();
|
||||
struct ssl_primary_config * const ssl_config = isProxy ?
|
||||
&conn->proxy_ssl_config :
|
||||
&conn->ssl_config;
|
||||
|
||||
clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
|
||||
if(!clone_host)
|
||||
return CURLE_OUT_OF_MEMORY; /* bail out */
|
||||
|
||||
@ -465,14 +521,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* find an empty slot for us, or find the oldest */
|
||||
for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
|
||||
for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
|
||||
data->state.session[i].sessionid; i++) {
|
||||
if(data->state.session[i].age < oldest_age) {
|
||||
oldest_age = data->state.session[i].age;
|
||||
store = &data->state.session[i];
|
||||
}
|
||||
}
|
||||
if(i == data->set.ssl.max_ssl_sessions)
|
||||
if(i == data->set.general_ssl.max_ssl_sessions)
|
||||
/* cache is full, we must "kill" the oldest entry! */
|
||||
Curl_ssl_kill_session(store);
|
||||
else
|
||||
@ -485,14 +541,15 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||
/* free it if there's one already present */
|
||||
free(store->name);
|
||||
store->name = clone_host; /* clone host name */
|
||||
store->remote_port = conn->remote_port; /* port number */
|
||||
/* port number */
|
||||
store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
|
||||
|
||||
|
||||
/* Unlock */
|
||||
if(SSLSESSION_SHARED(data))
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
|
||||
|
||||
if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
|
||||
if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
|
||||
store->sessionid = NULL; /* let caller free sessionid */
|
||||
free(clone_host);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@ -507,7 +564,7 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
||||
size_t i;
|
||||
/* kill the session ID cache if not shared */
|
||||
if(data->state.session && !SSLSESSION_SHARED(data)) {
|
||||
for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
|
||||
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
|
||||
/* the single-killer function handles empty table slots */
|
||||
Curl_ssl_kill_session(&data->state.session[i]);
|
||||
|
||||
@ -518,6 +575,43 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
||||
curlssl_close_all(data);
|
||||
}
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_DARWINSSL) || defined(USE_NSS)
|
||||
/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. */
|
||||
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if(connssl->connecting_state == ssl_connect_2_writing) {
|
||||
/* write mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
else if(connssl->connecting_state == ssl_connect_2_reading) {
|
||||
/* read mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#else
|
||||
int Curl_ssl_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
(void)conn;
|
||||
(void)socks;
|
||||
(void)numsocks;
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
/* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
|
||||
#endif
|
||||
|
||||
void Curl_ssl_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
|
||||
@ -575,7 +669,7 @@ CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* store the info in the SSL section */
|
||||
data->set.ssl.max_ssl_sessions = amount;
|
||||
data->set.general_ssl.max_ssl_sessions = amount;
|
||||
data->state.session = session;
|
||||
data->state.sessionage = 1; /* this is brand new */
|
||||
return CURLE_OK;
|
||||
|
@ -45,11 +45,18 @@
|
||||
#define ALPN_HTTP_1_1_LENGTH 8
|
||||
#define ALPN_HTTP_1_1 "http/1.1"
|
||||
|
||||
bool Curl_ssl_config_matches(struct ssl_config_data* data,
|
||||
struct ssl_config_data* needle);
|
||||
bool Curl_ssl_config_matches(struct ssl_primary_config* data,
|
||||
struct ssl_primary_config* needle);
|
||||
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
|
||||
struct ssl_primary_config *dest);
|
||||
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||
struct ssl_config_data* dest);
|
||||
void Curl_clone_general_ssl_config(struct ssl_general_config *source,
|
||||
struct ssl_general_config *dest);
|
||||
void Curl_free_ssl_config(struct ssl_config_data* sslc);
|
||||
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
|
||||
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
unsigned int Curl_rand(struct SessionHandle *);
|
||||
|
||||
@ -94,11 +101,13 @@ CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
|
||||
/* extract a session ID */
|
||||
bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||
void **ssl_sessionid,
|
||||
size_t *idsize) /* set 0 if unknown */;
|
||||
size_t *idsize, /* set 0 if unknown */
|
||||
int sockindex);
|
||||
/* add a new session ID */
|
||||
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||
void *ssl_sessionid,
|
||||
size_t idsize);
|
||||
size_t idsize,
|
||||
int sockindex);
|
||||
/* Kill a single session ID entry in the cache */
|
||||
void Curl_ssl_kill_session(struct curl_ssl_session *session);
|
||||
/* delete a session from the cache */
|
||||
|
@ -634,6 +634,8 @@
|
||||
d c 0
|
||||
d CURLPROXY_HTTP_1_0...
|
||||
d c 1
|
||||
d CURLPROXY_HTTPS...
|
||||
d c 2
|
||||
d CURLPROXY_SOCKS4...
|
||||
d c 4
|
||||
d CURLPROXY_SOCKS5...
|
||||
|
@ -66,6 +66,9 @@ static void free_config_fields(struct OperationConfig *config)
|
||||
Curl_safefree(config->tls_username);
|
||||
Curl_safefree(config->tls_password);
|
||||
Curl_safefree(config->tls_authtype);
|
||||
Curl_safefree(config->proxy_tls_username);
|
||||
Curl_safefree(config->proxy_tls_password);
|
||||
Curl_safefree(config->proxy_tls_authtype);
|
||||
Curl_safefree(config->proxyuserpwd);
|
||||
Curl_safefree(config->proxy);
|
||||
|
||||
@ -97,15 +100,24 @@ static void free_config_fields(struct OperationConfig *config)
|
||||
config->url_out = NULL;
|
||||
|
||||
Curl_safefree(config->cipher_list);
|
||||
Curl_safefree(config->proxy_cipher_list);
|
||||
Curl_safefree(config->cert);
|
||||
Curl_safefree(config->proxy_cert);
|
||||
Curl_safefree(config->cert_type);
|
||||
Curl_safefree(config->proxy_cert_type);
|
||||
Curl_safefree(config->cacert);
|
||||
Curl_safefree(config->proxy_cacert);
|
||||
Curl_safefree(config->capath);
|
||||
Curl_safefree(config->proxy_capath);
|
||||
Curl_safefree(config->crlfile);
|
||||
Curl_safefree(config->pinnedpubkey);
|
||||
Curl_safefree(config->proxy_crlfile);
|
||||
Curl_safefree(config->key);
|
||||
Curl_safefree(config->proxy_key);
|
||||
Curl_safefree(config->key_type);
|
||||
Curl_safefree(config->proxy_key_type);
|
||||
Curl_safefree(config->key_passwd);
|
||||
Curl_safefree(config->proxy_key_passwd);
|
||||
Curl_safefree(config->pubkey);
|
||||
Curl_safefree(config->hostpubmd5);
|
||||
Curl_safefree(config->engine);
|
||||
|
@ -77,6 +77,9 @@ struct OperationConfig {
|
||||
char *tls_username;
|
||||
char *tls_password;
|
||||
char *tls_authtype;
|
||||
char *proxy_tls_username;
|
||||
char *proxy_tls_password;
|
||||
char *proxy_tls_authtype;
|
||||
char *proxyuserpwd;
|
||||
char *proxy;
|
||||
int proxyver; /* set to CURLPROXY_HTTP* define */
|
||||
@ -105,15 +108,24 @@ struct OperationConfig {
|
||||
struct getout *url_get; /* point to the node to fill in URL */
|
||||
struct getout *url_out; /* point to the node to fill in outfile */
|
||||
char *cipher_list;
|
||||
char *proxy_cipher_list;
|
||||
char *cert;
|
||||
char *proxy_cert;
|
||||
char *cert_type;
|
||||
char *proxy_cert_type;
|
||||
char *cacert;
|
||||
char *proxy_cacert;
|
||||
char *capath;
|
||||
char *proxy_capath;
|
||||
char *crlfile;
|
||||
char *proxy_crlfile;
|
||||
char *pinnedpubkey;
|
||||
char *key;
|
||||
char *proxy_key;
|
||||
char *key_type;
|
||||
char *proxy_key_type;
|
||||
char *key_passwd;
|
||||
char *proxy_key_passwd;
|
||||
char *pubkey;
|
||||
char *hostpubmd5;
|
||||
char *engine;
|
||||
@ -126,6 +138,8 @@ struct OperationConfig {
|
||||
bool globoff;
|
||||
bool use_httpget;
|
||||
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
|
||||
bool proxy_insecure_ok; /* set TRUE to allow insecure SSL connects
|
||||
for proxy */
|
||||
bool verifystatus;
|
||||
bool create_dirs;
|
||||
bool ftp_create_dirs;
|
||||
@ -141,6 +155,7 @@ struct OperationConfig {
|
||||
struct curl_slist *postquote;
|
||||
struct curl_slist *prequote;
|
||||
long ssl_version;
|
||||
long proxy_ssl_version;
|
||||
long ip_version;
|
||||
curl_TimeCond timecond;
|
||||
time_t condtime;
|
||||
@ -199,6 +214,7 @@ struct OperationConfig {
|
||||
bool xattr; /* store metadata in extended attributes */
|
||||
long gssapi_delegation;
|
||||
bool ssl_allow_beast; /* allow this SSL vulnerability */
|
||||
bool proxy_ssl_allow_beast; /* allow this SSL vulnerability for proxy*/
|
||||
|
||||
bool use_metalink; /* process given URLs as metalink XML file */
|
||||
metalinkfile *metalinkfile_list; /* point to the first node */
|
||||
|
@ -221,6 +221,24 @@ static const struct LongShort aliases[]= {
|
||||
{"Ep", "pinnedpubkey", TRUE},
|
||||
{"Eq", "cert-status", FALSE},
|
||||
{"Er", "false-start", FALSE},
|
||||
{"Es", "proxy-sslv2", FALSE},
|
||||
{"Et", "proxy-sslv3", FALSE},
|
||||
{"Eu", "proxy-tlsuser", TRUE},
|
||||
{"Ev", "proxy-tlspassword", TRUE},
|
||||
{"Ew", "proxy-tlsauthtype", TRUE},
|
||||
{"Ex", "proxy-cert", TRUE},
|
||||
{"Ey", "proxy-cert-type", TRUE},
|
||||
{"Ez", "proxy-key", TRUE},
|
||||
{"E0", "proxy-key-type", TRUE},
|
||||
{"E1", "proxy-pass", TRUE},
|
||||
{"E2", "proxy-ciphers", TRUE},
|
||||
{"E3", "proxy-crlfile", TRUE},
|
||||
{"E4", "proxy-ssl-allow-beast", FALSE},
|
||||
{"E5", "login-options", TRUE},
|
||||
{"E6", "proxy-cacert", TRUE},
|
||||
{"E7", "proxy-capath", TRUE},
|
||||
{"E8", "proxy-insecure", FALSE},
|
||||
{"E9", "proxy-tlsv1", FALSE},
|
||||
{"f", "fail", FALSE},
|
||||
{"F", "form", TRUE},
|
||||
{"Fs", "form-string", TRUE},
|
||||
@ -377,6 +395,20 @@ done:
|
||||
*certname_place = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
GetFileAndPassword(char *nextarg, char **file, char **password)
|
||||
{
|
||||
char *certname, *passphrase;
|
||||
parse_cert_parameter(nextarg, &certname, &passphrase);
|
||||
Curl_safefree(*file);
|
||||
*file = certname;
|
||||
if(passphrase) {
|
||||
Curl_safefree(*password);
|
||||
*password = passphrase;
|
||||
}
|
||||
cleanarg(nextarg);
|
||||
}
|
||||
|
||||
ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
char *nextarg, /* NULL if unset */
|
||||
bool *usedarg, /* set to TRUE if the arg
|
||||
@ -1301,6 +1333,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
case 'E':
|
||||
switch(subletter) {
|
||||
case '\0': /* certificate file */
|
||||
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
|
||||
break;
|
||||
case 'a': /* CA info PEM file */
|
||||
/* CA info PEM file */
|
||||
GetStr(&config->cacert, nextarg);
|
||||
@ -1381,19 +1416,84 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'r': /* --false-start */
|
||||
config->falsestart = TRUE;
|
||||
break;
|
||||
|
||||
default: /* certificate file */
|
||||
{
|
||||
char *certname, *passphrase;
|
||||
parse_cert_parameter(nextarg, &certname, &passphrase);
|
||||
Curl_safefree(config->cert);
|
||||
config->cert = certname;
|
||||
if(passphrase) {
|
||||
Curl_safefree(config->key_passwd);
|
||||
config->key_passwd = passphrase;
|
||||
case 's':
|
||||
/* SSL version 2 for proxy */
|
||||
config->proxy_ssl_version = CURL_SSLVERSION_SSLv2;
|
||||
break;
|
||||
case 't':
|
||||
/* SSL version 3 for proxy */
|
||||
config->proxy_ssl_version = CURL_SSLVERSION_SSLv3;
|
||||
break;
|
||||
case 'u': /* TLS username for proxy */
|
||||
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
||||
GetStr(&config->proxy_tls_username, nextarg);
|
||||
else
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
case 'v': /* TLS password for proxy */
|
||||
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
||||
GetStr(&config->proxy_tls_password, nextarg);
|
||||
else
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
case 'w': /* TLS authentication type for proxy */
|
||||
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
|
||||
GetStr(&config->proxy_tls_authtype, nextarg);
|
||||
if(!strequal(config->proxy_tls_authtype, "SRP"))
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
|
||||
}
|
||||
else
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
case 'x': /* certificate file for proxy */
|
||||
GetFileAndPassword(nextarg, &config->proxy_cert,
|
||||
&config->proxy_key_passwd);
|
||||
break;
|
||||
case 'y': /* cert file type for proxy */
|
||||
GetStr(&config->proxy_cert_type, nextarg);
|
||||
break;
|
||||
case 'z': /* private key file for proxy */
|
||||
GetStr(&config->proxy_key, nextarg);
|
||||
break;
|
||||
case '0': /* private key file type for proxy */
|
||||
GetStr(&config->proxy_key_type, nextarg);
|
||||
break;
|
||||
case '1': /* private key passphrase for proxy */
|
||||
GetStr(&config->proxy_key_passwd, nextarg);
|
||||
cleanarg(nextarg);
|
||||
}
|
||||
break;
|
||||
case '2': /* ciphers for proxy */
|
||||
GetStr(&config->proxy_cipher_list, nextarg);
|
||||
break;
|
||||
case '3': /* CRL info PEM file for proxy */
|
||||
/* CRL file */
|
||||
GetStr(&config->proxy_crlfile, nextarg);
|
||||
break;
|
||||
case '4': /* no empty SSL fragments for proxy */
|
||||
if(curlinfo->features & CURL_VERSION_SSL)
|
||||
config->proxy_ssl_allow_beast = toggle;
|
||||
break;
|
||||
case '5': /* --login-options */
|
||||
GetStr(&config->login_options, nextarg);
|
||||
break;
|
||||
case '6': /* CA info PEM file for proxy */
|
||||
/* CA info PEM file */
|
||||
GetStr(&config->proxy_cacert, nextarg);
|
||||
break;
|
||||
case '7': /* CA info PEM file for proxy */
|
||||
/* CA cert directory */
|
||||
GetStr(&config->proxy_capath, nextarg);
|
||||
break;
|
||||
case '8': /* allow insecure SSL connects for proxy */
|
||||
config->proxy_insecure_ok = toggle;
|
||||
break;
|
||||
case '9':
|
||||
/* TLS version 1 for proxy */
|
||||
config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
|
||||
break;
|
||||
|
||||
default: /* unknown flag */
|
||||
return PARAM_OPTION_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
|
@ -171,9 +171,35 @@ static const char *const helptext[] = {
|
||||
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
|
||||
" --proxy-basic Use Basic authentication on the proxy (H)",
|
||||
" --proxy-digest Use Digest authentication on the proxy (H)",
|
||||
" --proxy-cacert FILE "
|
||||
"CA certificate to verify peer against for proxy (SSL)",
|
||||
" --proxy-capath DIR "
|
||||
"CA directory to verify peer against for proxy (SSL)",
|
||||
" --proxy-cert CERT[:PASSWD] "
|
||||
"Client certificate file and password for proxy (SSL)",
|
||||
" --proxy-cert-type TYPE "
|
||||
"Certificate file type (DER/PEM/ENG) for proxy (SSL)",
|
||||
" --proxy-ciphers LIST SSL ciphers to use for proxy (SSL)",
|
||||
" --proxy-crlfile FILE "
|
||||
"Get a CRL list in PEM format from the given file for proxy",
|
||||
" --proxy-insecure "
|
||||
"Allow connections to SSL sites without certs for proxy (H)",
|
||||
" --proxy-key KEY Private key file name for proxy (SSL)",
|
||||
" --proxy-key-type TYPE "
|
||||
"Private key file type for proxy (DER/PEM/ENG) (SSL)",
|
||||
" --proxy-negotiate "
|
||||
"Use HTTP Negotiate (SPNEGO) authentication on the proxy (H)",
|
||||
" --proxy-ntlm Use NTLM authentication on the proxy (H)",
|
||||
" --proxy-pass PASS Pass phrase for the private key for proxy (SSL)",
|
||||
" --proxy-ssl-allow-beast "
|
||||
"Allow security flaw to improve interop for proxy (SSL)",
|
||||
" --proxy-sslv2 Use SSLv2 for proxy (SSL)",
|
||||
" --proxy-sslv3 Use SSLv3 for proxy (SSL)",
|
||||
" --proxy-tlsv1 Use TLSv1 for proxy (SSL)",
|
||||
" --proxy-tlsuser USER TLS username for proxy",
|
||||
" --proxy-tlspassword STRING TLS password for proxy",
|
||||
" --proxy-tlsauthtype STRING "
|
||||
"TLS authentication type for proxy (default SRP)",
|
||||
" --proxy-service-name NAME SPNEGO proxy service name",
|
||||
" --service-name NAME SPNEGO service name",
|
||||
" -U, --proxy-user USER[:PASSWORD] Proxy user and password",
|
||||
|
@ -870,8 +870,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
|
||||
/* new in libcurl 7.10 */
|
||||
if(config->socksproxy) {
|
||||
my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
|
||||
my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
|
||||
my_setopt_str(curl, CURLOPT_SOCKS_PROXY, config->socksproxy);
|
||||
my_setopt_enum(curl, CURLOPT_SOCKS_PROXYTYPE,
|
||||
(long)config->socksver);
|
||||
}
|
||||
|
||||
/* new in libcurl 7.10.6 */
|
||||
@ -999,6 +1000,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
|
||||
|
||||
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
|
||||
my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
|
||||
|
||||
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
|
||||
|
||||
@ -1016,19 +1018,36 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
|
||||
if(config->cacert)
|
||||
my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
|
||||
if(config->proxy_cacert)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
|
||||
if(config->capath)
|
||||
my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
|
||||
if(config->proxy_capath)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_CAPATH, config->proxy_capath);
|
||||
else if(config->capath) /* CURLOPT_PROXY_CAPATH default is capath */
|
||||
my_setopt_str(curl, CURLOPT_PROXY_CAPATH, config->capath);
|
||||
|
||||
if(config->crlfile)
|
||||
my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
|
||||
if(config->proxy_crlfile)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
|
||||
else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
|
||||
my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
|
||||
|
||||
if(config->pinnedpubkey)
|
||||
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
|
||||
|
||||
if(curlinfo->features & CURL_VERSION_SSL) {
|
||||
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
|
||||
my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
|
||||
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
|
||||
my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
|
||||
config->proxy_cert_type);
|
||||
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
|
||||
my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
|
||||
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
|
||||
my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
|
||||
config->proxy_key_type);
|
||||
|
||||
if(config->insecure_ok) {
|
||||
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
@ -1039,6 +1058,13 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
/* libcurl default is strict verifyhost -> 2L */
|
||||
/* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
|
||||
}
|
||||
if(config->proxy_insecure_ok) {
|
||||
my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
|
||||
my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
else {
|
||||
my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
|
||||
}
|
||||
|
||||
if(config->verifystatus)
|
||||
my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
|
||||
@ -1047,6 +1073,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
|
||||
|
||||
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
|
||||
my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
|
||||
config->proxy_ssl_version);
|
||||
}
|
||||
if(config->path_as_is)
|
||||
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
|
||||
@ -1147,6 +1175,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
if(config->cipher_list)
|
||||
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
|
||||
|
||||
if(config->proxy_cipher_list)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
|
||||
config->proxy_cipher_list);
|
||||
|
||||
/* new in libcurl 7.9.2: */
|
||||
if(config->disable_epsv)
|
||||
/* disable it */
|
||||
@ -1320,6 +1352,15 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
if(config->tls_authtype)
|
||||
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
|
||||
config->tls_authtype);
|
||||
if(config->proxy_tls_username)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
|
||||
config->proxy_tls_username);
|
||||
if(config->proxy_tls_password)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
|
||||
config->proxy_tls_password);
|
||||
if(config->proxy_tls_authtype)
|
||||
my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
|
||||
config->proxy_tls_authtype);
|
||||
}
|
||||
|
||||
/* new in 7.22.0 */
|
||||
@ -1331,6 +1372,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
if(config->ssl_allow_beast)
|
||||
my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST);
|
||||
|
||||
if(config->proxy_ssl_allow_beast)
|
||||
my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
|
||||
(long)CURLSSLOPT_ALLOW_BEAST);
|
||||
|
||||
if(config->mail_auth)
|
||||
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
||||
|
||||
|
@ -45,6 +45,15 @@
|
||||
const NameValue setopt_nv_CURLPROXY[] = {
|
||||
NV(CURLPROXY_HTTP),
|
||||
NV(CURLPROXY_HTTP_1_0),
|
||||
NV(CURLPROXY_HTTPS),
|
||||
NV(CURLPROXY_SOCKS4),
|
||||
NV(CURLPROXY_SOCKS5),
|
||||
NV(CURLPROXY_SOCKS4A),
|
||||
NV(CURLPROXY_SOCKS5_HOSTNAME),
|
||||
NVEND,
|
||||
};
|
||||
|
||||
const NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
|
||||
NV(CURLPROXY_SOCKS4),
|
||||
NV(CURLPROXY_SOCKS5),
|
||||
NV(CURLPROXY_SOCKS4A),
|
||||
@ -149,6 +158,8 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
|
||||
NV1(CURLOPT_SSL_VERIFYHOST, 1),
|
||||
NV1(CURLOPT_SSL_ENABLE_NPN, 1),
|
||||
NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
|
||||
NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1),
|
||||
NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1),
|
||||
NVEND
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,7 @@ typedef struct {
|
||||
} NameValueUnsigned;
|
||||
|
||||
extern const NameValue setopt_nv_CURLPROXY[];
|
||||
extern const NameValue setopt_nv_CURL_SOCKS_PROXY[];
|
||||
extern const NameValue setopt_nv_CURL_HTTP_VERSION[];
|
||||
extern const NameValue setopt_nv_CURL_SSLVERSION[];
|
||||
extern const NameValue setopt_nv_CURL_TIMECOND[];
|
||||
@ -60,6 +61,7 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
|
||||
#define setopt_nv_CURLOPT_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
|
||||
#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
|
||||
#define setopt_nv_CURLOPT_SSLVERSION setopt_nv_CURL_SSLVERSION
|
||||
#define setopt_nv_CURLOPT_PROXY_SSLVERSION setopt_nv_CURL_SSLVERSION
|
||||
#define setopt_nv_CURLOPT_TIMECONDITION setopt_nv_CURL_TIMECOND
|
||||
#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
|
||||
#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
|
||||
@ -67,6 +69,7 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
|
||||
#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO
|
||||
#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO
|
||||
#define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY
|
||||
#define setopt_nv_CURLOPT_SOCKS_PROXYTYPE setopt_nv_CURL_SOCKS_PROXY
|
||||
#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
|
||||
|
||||
/* Intercept setopt calls for --libcurl */
|
||||
|
@ -52,6 +52,7 @@ typedef enum {
|
||||
VAR_FTP_ENTRY_PATH,
|
||||
VAR_REDIRECT_URL,
|
||||
VAR_SSL_VERIFY_RESULT,
|
||||
VAR_PROXY_SSL_VERIFY_RESULT,
|
||||
VAR_EFFECTIVE_FILENAME,
|
||||
VAR_PRIMARY_IP,
|
||||
VAR_PRIMARY_PORT,
|
||||
@ -90,6 +91,7 @@ static const struct variable replacements[]={
|
||||
{"ftp_entry_path", VAR_FTP_ENTRY_PATH},
|
||||
{"redirect_url", VAR_REDIRECT_URL},
|
||||
{"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
|
||||
{"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT},
|
||||
{"filename_effective", VAR_EFFECTIVE_FILENAME},
|
||||
{"remote_ip", VAR_PRIMARY_IP},
|
||||
{"remote_port", VAR_PRIMARY_PORT},
|
||||
@ -250,6 +252,12 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
|
||||
&longinfo))
|
||||
fprintf(stream, "%ld", longinfo);
|
||||
break;
|
||||
case VAR_PROXY_SSL_VERIFY_RESULT:
|
||||
if(CURLE_OK ==
|
||||
curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT,
|
||||
&longinfo))
|
||||
fprintf(stream, "%ld", longinfo);
|
||||
break;
|
||||
case VAR_EFFECTIVE_FILENAME:
|
||||
if(outs->filename)
|
||||
fprintf(stream, "%s", outs->filename);
|
||||
|
Loading…
x
Reference in New Issue
Block a user