Compare commits
22 Commits
main
...
HTTPS-prox
Author | SHA1 | Date | |
---|---|---|---|
|
ed24d41cb1 | ||
|
cc9b053d84 | ||
|
3e7a1ff9a6 | ||
|
e21bd4ecb5 | ||
|
4bb13975a8 | ||
|
4e28002898 | ||
|
ec6d8a38ae | ||
|
127a7b0257 | ||
|
043c5f5c33 | ||
|
171de1bef8 | ||
|
f956ebf252 | ||
|
68a7d38aa0 | ||
|
cd2644fe2c | ||
|
1c5997ae9d | ||
|
f9087b7499 | ||
|
7df237b0b1 | ||
|
211b265ffd | ||
|
316054e8cd | ||
|
f7e2cd278a | ||
|
b505df4b68 | ||
|
e58bd8e41a | ||
|
3d90ec5448 |
@ -237,6 +237,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
|
||||
@ -462,7 +463,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
|
||||
@ -492,6 +509,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
|
||||
@ -603,6 +622,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
|
||||
|
@ -622,6 +622,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 */
|
||||
@ -1188,7 +1189,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
|
||||
@ -1672,6 +1674,70 @@ typedef enum {
|
||||
/* Set E-xclusive stream dependency on another CURL handle */
|
||||
CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
|
||||
|
||||
/* The CApath or CAfile used to validate the proxy certificate
|
||||
this option is used only if PROXY_SSL_VERIFYPEER is true */
|
||||
CINIT(PROXY_CAINFO, STRINGPOINT, 242),
|
||||
|
||||
/* The CApath directory used to validate the proxy certificate
|
||||
this option is used only if PROXY_SSL_VERIFYPEER is true */
|
||||
CINIT(PROXY_CAPATH, STRINGPOINT, 243),
|
||||
|
||||
/* Set if we should verify the proxy in ssl handshake,
|
||||
set 1 to verify. */
|
||||
CINIT(PROXY_SSL_VERIFYPEER, LONG, 244),
|
||||
|
||||
/* 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, 245),
|
||||
|
||||
/* What version to specifically try to use for proxy.
|
||||
See CURL_SSLVERSION defines below. */
|
||||
CINIT(PROXY_SSLVERSION, LONG, 246),
|
||||
|
||||
/* Set a username for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 247),
|
||||
|
||||
/* Set a password for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 248),
|
||||
|
||||
/* Set authentication type for authenticated TLS for proxy */
|
||||
CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 249),
|
||||
|
||||
/* name of the file keeping your private SSL-certificate for proxy */
|
||||
CINIT(PROXY_SSLCERT, STRINGPOINT, 250),
|
||||
|
||||
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
|
||||
proxy */
|
||||
CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 251),
|
||||
|
||||
/* name of the file keeping your private SSL-key for proxy */
|
||||
CINIT(PROXY_SSLKEY, STRINGPOINT, 252),
|
||||
|
||||
/* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
|
||||
proxy */
|
||||
CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 253),
|
||||
|
||||
/* password for the SSL private key for proxy */
|
||||
CINIT(PROXY_KEYPASSWD, STRINGPOINT, 254),
|
||||
|
||||
/* Specify which SSL ciphers to use for proxy */
|
||||
CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 255),
|
||||
|
||||
/* CRL file for proxy */
|
||||
CINIT(PROXY_CRLFILE, STRINGPOINT, 256),
|
||||
|
||||
/* Enable/disable specific SSL features with a bitmask for proxy, see
|
||||
CURLSSLOPT_* */
|
||||
CINIT(PROXY_SSL_OPTIONS, LONG, 257),
|
||||
|
||||
/* Name of socks proxy to use. */
|
||||
CINIT(SOCKS_PROXY, STRINGPOINT, 258),
|
||||
|
||||
/* indicates type of proxy. accepted values are CURLPROXY_SOCKS4,
|
||||
CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
|
||||
CINIT(SOCKS_PROXYTYPE, LONG, 259),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@ -2167,9 +2233,10 @@ typedef enum {
|
||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
|
||||
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 45,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 44
|
||||
CURLINFO_LASTONE = 45
|
||||
} 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));
|
||||
}
|
||||
|
||||
|
@ -137,8 +137,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;
|
||||
}
|
||||
|
128
lib/ftp.c
128
lib/ftp.c
@ -491,7 +491,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");
|
||||
@ -732,7 +732,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",
|
||||
@ -1842,84 +1842,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)
|
||||
{
|
||||
@ -1927,11 +1849,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;
|
||||
@ -2055,7 +1973,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 */
|
||||
@ -2065,8 +1985,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;
|
||||
}
|
||||
}
|
||||
@ -2107,6 +2026,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 */
|
||||
@ -2755,7 +2678,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 */
|
||||
|
||||
@ -2800,7 +2726,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);
|
||||
}
|
||||
}
|
||||
@ -2842,7 +2768,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 */
|
||||
@ -3670,10 +3596,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
/* 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)) {
|
||||
@ -3685,6 +3607,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 */
|
||||
@ -4252,8 +4186,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;
|
||||
|
52
lib/http.c
52
lib/http.c
@ -287,8 +287,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;
|
||||
@ -642,7 +642,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;
|
||||
}
|
||||
@ -1092,8 +1092,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
|
||||
@ -1345,10 +1345,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;
|
||||
@ -1391,49 +1394,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) || \
|
||||
defined(USE_MBEDTLS)
|
||||
/* 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"
|
||||
@ -642,6 +643,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];
|
||||
@ -1236,7 +1240,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);
|
||||
}
|
||||
@ -1247,6 +1253,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
@ -116,6 +116,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;
|
||||
|
@ -859,7 +859,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 = "";
|
||||
|
||||
|
@ -1311,7 +1311,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 */
|
||||
|
@ -331,6 +331,8 @@ struct ssl_connect_data {
|
||||
gsk_handle handle;
|
||||
int iocport;
|
||||
ssl_connect_state connecting_state;
|
||||
int localfd;
|
||||
int remotefd;
|
||||
#endif
|
||||
#ifdef USE_AXTLS
|
||||
SSL_CTX* ssl_ctx;
|
||||
@ -359,27 +361,37 @@ 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*/
|
||||
bool no_revoke; /* disable SSL certificate revocation checks */
|
||||
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) */
|
||||
@ -387,6 +399,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 */
|
||||
@ -394,7 +411,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 */
|
||||
@ -507,6 +524,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
|
||||
@ -541,6 +559,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
|
||||
@ -553,6 +572,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 {
|
||||
@ -840,6 +862,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.
|
||||
@ -889,10 +919,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
|
||||
@ -917,10 +952,6 @@ struct connectdata {
|
||||
|
||||
char *oauth_bearer; /* bearer token for OAuth 2.0, 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 */
|
||||
|
||||
@ -935,7 +966,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 */
|
||||
|
||||
@ -1061,9 +1094,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
|
||||
@ -1374,8 +1404,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 */
|
||||
@ -1385,25 +1413,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 */
|
||||
@ -1428,10 +1447,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 */
|
||||
@ -1545,7 +1560,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 */
|
||||
@ -1609,9 +1627,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*/
|
||||
bool ssl_no_revoke; /* disable SSL certificate revocation checks */
|
||||
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(SSL_CONN_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(SSL_CONN_CONFIG(CAfile)) {
|
||||
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
|
||||
SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
|
||||
infof(data, "error reading ca cert file %s \n",
|
||||
data->set.ssl.CAfile);
|
||||
if(data->set.ssl.verifypeer) {
|
||||
SSL_CONN_CONFIG(CAfile));
|
||||
if(SSL_CONN_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", SSL_CONN_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(SSL_SET_OPTION(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);
|
||||
SSL_SET_OPTION(cert), NULL);
|
||||
if(ssl_fcn_return == SSL_OK) {
|
||||
infof(data, "successfully read cert file %s \n",
|
||||
data->set.str[STRING_CERT]);
|
||||
SSL_SET_OPTION(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]);
|
||||
SSL_SET_OPTION(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(SSL_SET_OPTION(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);
|
||||
SSL_SET_OPTION(key), NULL);
|
||||
if(ssl_fcn_return == SSL_OK) {
|
||||
infof(data, "successfully read key file %s \n",
|
||||
data->set.str[STRING_KEY]);
|
||||
SSL_SET_OPTION(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]);
|
||||
SSL_SET_OPTION(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],
|
||||
@ -287,13 +288,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
const char *dns_altname;
|
||||
int8_t found_subject_alt_names = 0;
|
||||
int8_t found_subject_alt_name_matching_conn = 0;
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const char * const dispname = SSL_IS_PROXY() ?
|
||||
conn->http_proxy.host.dispname : conn->host.dispname;
|
||||
|
||||
/* Here, gtls.c gets the peer certificates and fails out depending on
|
||||
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
|
||||
*/
|
||||
|
||||
/* Verify server's certificate */
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
if(ssl_verify_cert(ssl) != SSL_OK) {
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "server cert verify failed");
|
||||
@ -324,8 +329,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
found_subject_alt_names = 1;
|
||||
|
||||
infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
|
||||
dns_altname, conn->host.name);
|
||||
if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
|
||||
dns_altname, hostname);
|
||||
if(Curl_cert_hostcheck(dns_altname, hostname)) {
|
||||
found_subject_alt_name_matching_conn = 1;
|
||||
break;
|
||||
}
|
||||
@ -333,23 +338,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* RFC2818 checks */
|
||||
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
/* Break connection ! */
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "\tsubjectAltName(s) do not match %s\n",
|
||||
conn->host.dispname);
|
||||
failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else
|
||||
infof(data, "\tsubjectAltName(s) do not match %s\n",
|
||||
conn->host.dispname);
|
||||
infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
|
||||
}
|
||||
else if(found_subject_alt_names == 0) {
|
||||
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
|
||||
CN as a legacy fallback */
|
||||
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
|
||||
if(peer_CN == NULL) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "unable to obtain common name from peer certificate");
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
@ -358,17 +361,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
infof(data, "unable to obtain common name from peer certificate");
|
||||
}
|
||||
else {
|
||||
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
/* Break connection ! */
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
||||
peer_CN, conn->host.dispname);
|
||||
peer_CN, dispname);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else
|
||||
infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
||||
peer_CN, conn->host.dispname);
|
||||
peer_CN, dispname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,7 +384,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");
|
||||
|
||||
|
@ -117,7 +117,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(SSL_CONN_CONFIG(version)) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
|
||||
@ -168,7 +168,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
switch(data->set.ssl.version) {
|
||||
switch(SSL_CONN_CONFIG(version)) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
|
||||
@ -191,18 +191,18 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
/* load trusted cacert */
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
if(SSL_CONN_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) {
|
||||
SSL_CONN_CONFIG(CAfile),
|
||||
SSL_CONN_CONFIG(CApath))) {
|
||||
if(SSL_CONN_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");
|
||||
SSL_CONN_CONFIG(CAfile)?
|
||||
SSL_CONN_CONFIG(CAfile): "none",
|
||||
SSL_CONN_CONFIG(CApath)?
|
||||
SSL_CONN_CONFIG(CApath) : "none");
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else {
|
||||
@ -219,25 +219,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]:
|
||||
SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
|
||||
"none",
|
||||
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
|
||||
SSL_CONN_CONFIG(CApath) ? SSL_CONN_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(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
|
||||
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
|
||||
|
||||
if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
|
||||
if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(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(SSL_SET_OPTION(key_type));
|
||||
if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
|
||||
file_type) != 1) {
|
||||
failf(data, "unable to set private key");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -250,7 +250,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,
|
||||
SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
|
||||
SSL_VERIFY_NONE,
|
||||
NULL);
|
||||
|
||||
#ifdef HAVE_SNI
|
||||
@ -259,13 +260,15 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
#ifdef ENABLE_IPV6
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
size_t hostname_len = strlen(conn->host.name);
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
size_t hostname_len = strlen(hostname);
|
||||
if((hostname_len < USHRT_MAX) &&
|
||||
(0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
|
||||
(0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
|
||||
#ifdef ENABLE_IPV6
|
||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
|
||||
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
|
||||
#endif
|
||||
(CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
|
||||
(CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
|
||||
(unsigned short)hostname_len) != 1)) {
|
||||
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||
"TLS extension\n");
|
||||
@ -284,7 +287,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
#ifdef NO_FILESYSTEM
|
||||
else if(data->set.ssl.verifypeer) {
|
||||
else if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
|
||||
" with \"no filesystem\". Either disable peer verification"
|
||||
" (insecure) or if you are building an application with libcurl you"
|
||||
@ -303,7 +306,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",
|
||||
@ -332,13 +335,17 @@ cyassl_connect_step2(struct connectdata *conn,
|
||||
int ret = -1;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const char * const dispname = SSL_IS_PROXY() ?
|
||||
conn->http_proxy.host.dispname : conn->host.dispname;
|
||||
|
||||
conn->recv[sockindex] = cyassl_recv;
|
||||
conn->send[sockindex] = cyassl_send;
|
||||
|
||||
/* Enable RFC2818 checks */
|
||||
if(data->set.ssl.verifyhost) {
|
||||
ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
ret = CyaSSL_check_domain_name(conssl->handle, hostname);
|
||||
if(ret == SSL_FAILURE)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -362,31 +369,31 @@ cyassl_connect_step2(struct connectdata *conn,
|
||||
else if(DOMAIN_NAME_MISMATCH == detail) {
|
||||
#if 1
|
||||
failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
|
||||
conn->host.dispname);
|
||||
dispname);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
#else
|
||||
/* When the CyaSSL_check_domain_name() is used and you desire to continue
|
||||
* on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
|
||||
* on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0',
|
||||
* 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) {
|
||||
* in and out based on the 'conn->ssl_config.verifyhost' value. */
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
failf(data,
|
||||
"\tsubject alt name(s) or common name do not match \"%s\"\n",
|
||||
conn->host.dispname);
|
||||
dispname);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else {
|
||||
infof(data,
|
||||
"\tsubject alt name(s) and/or common name do not match \"%s\"\n",
|
||||
conn->host.dispname);
|
||||
dispname);
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
|
||||
else if(ASN_NO_SIGNER_E == detail) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "\tCA signer not available for verification\n");
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
@ -466,7 +473,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");
|
||||
@ -477,7 +485,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));
|
||||
|
||||
|
319
lib/vtls/gskit.c
319
lib/vtls/gskit.c
@ -81,6 +81,10 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
/* Directions. */
|
||||
#define SOS_READ 0x01
|
||||
#define SOS_WRITE 0x02
|
||||
|
||||
/* SSL version flags. */
|
||||
#define CURL_GSKPROTO_SSLV2 0
|
||||
#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
|
||||
@ -289,10 +293,11 @@ static CURLcode set_callback(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_ciphers(struct SessionHandle *data,
|
||||
static CURLcode set_ciphers(struct connectdata *conn,
|
||||
gsk_handle h, unsigned int *protoflags)
|
||||
{
|
||||
const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
struct SessionHandle *data = conn->data;
|
||||
const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
|
||||
const char *clp;
|
||||
const gskit_cipher *ctp;
|
||||
int i;
|
||||
@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
|
||||
connssl->iocport = -1;
|
||||
}
|
||||
|
||||
/* SSL over SSL
|
||||
* Problems:
|
||||
* 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
|
||||
* pipe an SSL stream into another, it is therefore needed to have a pair
|
||||
* of such communicating sockets and handle the pipelining explicitly.
|
||||
* 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
|
||||
* be used to produce the pipeline.
|
||||
* The solution is to simulate socketpair() for AF_INET with low-level API
|
||||
* listen(), bind() and connect().
|
||||
*/
|
||||
|
||||
static void close_one(struct ssl_connect_data *conn,
|
||||
struct SessionHandle *data)
|
||||
static int
|
||||
inetsocketpair(int sv[2])
|
||||
{
|
||||
if(conn->handle) {
|
||||
gskit_status(data, gsk_secure_soc_close(&conn->handle),
|
||||
"gsk_secure_soc_close()", 0);
|
||||
conn->handle = (gsk_handle) NULL;
|
||||
int lfd; /* Listening socket. */
|
||||
int sfd; /* Server socket. */
|
||||
int cfd; /* Client socket. */
|
||||
int len;
|
||||
struct sockaddr_in addr1;
|
||||
struct sockaddr_in addr2;
|
||||
|
||||
/* Create listening socket on a local dynamic port. */
|
||||
lfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(lfd < 0)
|
||||
return -1;
|
||||
memset((char *) &addr1, 0, sizeof addr1);
|
||||
addr1.sin_family = AF_INET;
|
||||
addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr1.sin_port = 0;
|
||||
if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
|
||||
listen(lfd, 2) < 0) {
|
||||
close(lfd);
|
||||
return -1;
|
||||
}
|
||||
if(conn->iocport >= 0)
|
||||
close_async_handshake(conn);
|
||||
|
||||
/* Get the allocated port. */
|
||||
len = sizeof addr1;
|
||||
if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
|
||||
close(lfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create the client socket. */
|
||||
cfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(cfd < 0) {
|
||||
close(lfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Request unblocking connection to the listening socket. */
|
||||
curlx_nonblock(cfd, TRUE);
|
||||
if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
|
||||
errno != EINPROGRESS) {
|
||||
close(lfd);
|
||||
close(cfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the client dynamic port for intrusion check below. */
|
||||
len = sizeof addr2;
|
||||
if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
|
||||
close(lfd);
|
||||
close(cfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Accept the incoming connection and get the server socket. */
|
||||
curlx_nonblock(lfd, TRUE);
|
||||
for (;;) {
|
||||
len = sizeof addr1;
|
||||
sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
|
||||
if(sfd < 0) {
|
||||
close(lfd);
|
||||
close(cfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for possible intrusion from an external process. */
|
||||
if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
|
||||
addr1.sin_port == addr2.sin_port)
|
||||
break;
|
||||
|
||||
/* Intrusion: reject incoming connection. */
|
||||
close(sfd);
|
||||
}
|
||||
|
||||
/* Done, return sockets and succeed. */
|
||||
close(lfd);
|
||||
curlx_nonblock(cfd, FALSE);
|
||||
sv[0] = cfd;
|
||||
sv[1] = sfd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
|
||||
int directions)
|
||||
{
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
|
||||
fd_set fds_read;
|
||||
fd_set fds_write;
|
||||
int n;
|
||||
int m;
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct timeval tv = {0, 0};
|
||||
char buf[CURL_MAX_WRITE_SIZE];
|
||||
|
||||
if(!connssl->use || !connproxyssl->use)
|
||||
return 0; /* No SSL over SSL: OK. */
|
||||
|
||||
FD_ZERO(&fds_read);
|
||||
FD_ZERO(&fds_write);
|
||||
n = -1;
|
||||
if(directions & SOS_READ) {
|
||||
FD_SET(connssl->remotefd, &fds_write);
|
||||
n = connssl->remotefd;
|
||||
}
|
||||
if(directions & SOS_WRITE) {
|
||||
FD_SET(connssl->remotefd, &fds_read);
|
||||
n = connssl->remotefd;
|
||||
FD_SET(conn->sock[sockindex], &fds_write);
|
||||
if(n < conn->sock[sockindex])
|
||||
n = conn->sock[sockindex];
|
||||
}
|
||||
i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
|
||||
if(i < 0)
|
||||
return -1; /* Select error. */
|
||||
|
||||
if(FD_ISSET(connssl->remotefd, &fds_write)) {
|
||||
/* Try getting data from HTTPS proxy and pipe it upstream. */
|
||||
n = 0;
|
||||
i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
|
||||
switch(i) {
|
||||
case GSK_OK:
|
||||
if(n) {
|
||||
i = write(connssl->remotefd, buf, n);
|
||||
if(i < 0)
|
||||
return -1;
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case GSK_OS400_ERROR_TIMED_OUT:
|
||||
case GSK_WOULD_BLOCK:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(FD_ISSET(connssl->remotefd, &fds_read) &&
|
||||
FD_ISSET(conn->sock[sockindex], &fds_write)) {
|
||||
/* Pipe data to HTTPS proxy. */
|
||||
n = read(connssl->remotefd, buf, sizeof buf);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
if(n) {
|
||||
i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
|
||||
if(i != GSK_OK || n != m)
|
||||
return -1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret; /* OK */
|
||||
}
|
||||
|
||||
|
||||
static void close_one(struct ssl_connect_data *connssl,
|
||||
struct connectdata *conn, int sockindex)
|
||||
{
|
||||
if(connssl->handle) {
|
||||
gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
|
||||
"gsk_secure_soc_close()", 0);
|
||||
/* Last chance to drain output. */
|
||||
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
|
||||
;
|
||||
connssl->handle = (gsk_handle) NULL;
|
||||
if(connssl->localfd >= 0) {
|
||||
close(connssl->localfd);
|
||||
connssl->localfd = -1;
|
||||
}
|
||||
if(connssl->remotefd >= 0) {
|
||||
close(connssl->remotefd);
|
||||
connssl->remotefd = -1;
|
||||
}
|
||||
}
|
||||
if(connssl->iocport >= 0)
|
||||
close_async_handshake(connssl);
|
||||
}
|
||||
|
||||
|
||||
@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
|
||||
const void *mem, size_t len, CURLcode *curlcode)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode cc;
|
||||
CURLcode cc = CURLE_SEND_ERROR;
|
||||
int written;
|
||||
|
||||
cc = gskit_status(data,
|
||||
gsk_secure_soc_write(conn->ssl[sockindex].handle,
|
||||
(char *) mem, (int) len, &written),
|
||||
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
|
||||
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
|
||||
cc = gskit_status(data,
|
||||
gsk_secure_soc_write(conn->ssl[sockindex].handle,
|
||||
(char *) mem, (int) len, &written),
|
||||
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
|
||||
if(cc == CURLE_OK)
|
||||
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
|
||||
cc = CURLE_SEND_ERROR;
|
||||
}
|
||||
if(cc != CURLE_OK) {
|
||||
*curlcode = cc;
|
||||
written = -1;
|
||||
@ -539,15 +727,23 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
|
||||
struct SessionHandle *data = conn->data;
|
||||
int buffsize;
|
||||
int nread;
|
||||
CURLcode cc;
|
||||
CURLcode cc = CURLE_RECV_ERROR;
|
||||
|
||||
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
|
||||
cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
|
||||
buf, buffsize, &nread),
|
||||
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
|
||||
if(cc != CURLE_OK) {
|
||||
if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
|
||||
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
|
||||
cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
|
||||
buf, buffsize, &nread),
|
||||
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
|
||||
}
|
||||
switch(cc) {
|
||||
case CURLE_OK:
|
||||
break;
|
||||
case CURLE_OPERATION_TIMEDOUT:
|
||||
cc = CURLE_AGAIN;
|
||||
default:
|
||||
*curlcode = cc;
|
||||
nread = -1;
|
||||
break;
|
||||
}
|
||||
return (ssize_t) nread;
|
||||
}
|
||||
@ -560,18 +756,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
gsk_handle envir;
|
||||
CURLcode result;
|
||||
int rc;
|
||||
char *keyringfile;
|
||||
char *keyringpwd;
|
||||
char *keyringlabel;
|
||||
char *sni;
|
||||
const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
|
||||
const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
|
||||
const char * const keyringlabel = SSL_SET_OPTION(cert);
|
||||
const long int ssl_version = SSL_CONN_CONFIG(version);
|
||||
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
|
||||
const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
|
||||
conn->host.name;
|
||||
const char *sni;
|
||||
unsigned int protoflags;
|
||||
long timeout;
|
||||
Qso_OverlappedIO_t commarea;
|
||||
int sockpair[2];
|
||||
static const int sobufsize = CURL_MAX_WRITE_SIZE;
|
||||
|
||||
/* Create SSL environment, start (preferably asynchronous) handshake. */
|
||||
|
||||
connssl->handle = (gsk_handle) NULL;
|
||||
connssl->iocport = -1;
|
||||
connssl->localfd = -1;
|
||||
connssl->remotefd = -1;
|
||||
|
||||
/* GSKit supports two ways of specifying an SSL context: either by
|
||||
* application identifier (that should have been defined at the system
|
||||
@ -586,9 +790,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
* application identifier mode is tried first, as recommended in IBM doc.
|
||||
*/
|
||||
|
||||
keyringfile = data->set.str[STRING_SSL_CAFILE];
|
||||
keyringpwd = data->set.str[STRING_KEY_PASSWD];
|
||||
keyringlabel = data->set.str[STRING_CERT];
|
||||
envir = (gsk_handle) NULL;
|
||||
|
||||
if(keyringlabel && *keyringlabel && !keyringpwd &&
|
||||
@ -613,18 +814,36 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Establish a pipelining socket pair for SSL over SSL. */
|
||||
if(conn->proxy_ssl[sockindex].use) {
|
||||
if(inetsocketpair(sockpair))
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
connssl->localfd = sockpair[0];
|
||||
connssl->remotefd = sockpair[1];
|
||||
setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
|
||||
(void *) sobufsize, sizeof sobufsize);
|
||||
setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
|
||||
(void *) sobufsize, sizeof sobufsize);
|
||||
setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
|
||||
(void *) sobufsize, sizeof sobufsize);
|
||||
setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
|
||||
(void *) sobufsize, sizeof sobufsize);
|
||||
curlx_nonblock(connssl->localfd, TRUE);
|
||||
curlx_nonblock(connssl->remotefd, TRUE);
|
||||
}
|
||||
|
||||
/* Determine which SSL/TLS version should be enabled. */
|
||||
protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
|
||||
CURL_GSKPROTO_TLSV12_MASK;
|
||||
sni = conn->host.name;
|
||||
switch (data->set.ssl.version) {
|
||||
sni = hostname;
|
||||
switch (ssl_version) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
protoflags = CURL_GSKPROTO_SSLV2_MASK;
|
||||
sni = (char *) NULL;
|
||||
sni = NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
protoflags = CURL_GSKPROTO_SSLV3_MASK;
|
||||
sni = (char *) NULL;
|
||||
sni = NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
protoflags = CURL_GSKPROTO_TLSV10_MASK |
|
||||
@ -661,9 +880,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
(timeout + 999) / 1000);
|
||||
}
|
||||
if(!result)
|
||||
result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
|
||||
result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
|
||||
if(!result)
|
||||
result = set_ciphers(data, connssl->handle, &protoflags);
|
||||
result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
|
||||
connssl->localfd: conn->sock[sockindex]);
|
||||
if(!result)
|
||||
result = set_ciphers(conn, connssl->handle, &protoflags);
|
||||
if(!protoflags) {
|
||||
failf(data, "No SSL protocol/cipher combination enabled");
|
||||
result = CURLE_SSL_CIPHER;
|
||||
@ -706,7 +928,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
if(!result)
|
||||
result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
|
||||
data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
|
||||
verifypeer? GSK_SERVER_AUTH_FULL:
|
||||
GSK_SERVER_AUTH_PASSTHRU, FALSE);
|
||||
|
||||
if(!result) {
|
||||
@ -730,6 +952,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
else if(errno != ENOBUFS)
|
||||
result = gskit_status(data, GSK_ERROR_IO,
|
||||
"QsoCreateIOCompletionPort()", 0);
|
||||
else if(conn->proxy_ssl[sockindex].use) {
|
||||
/* Cannot pipeline while handshaking synchronously. */
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
else {
|
||||
/* No more completion port available. Use synchronous IO. */
|
||||
result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
|
||||
@ -742,7 +968,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
|
||||
/* Error: rollback. */
|
||||
close_one(connssl, data);
|
||||
close_one(connssl, conn, sockindex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -913,6 +1139,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
|
||||
result = gskit_connect_step1(conn, sockindex);
|
||||
}
|
||||
|
||||
/* Handle handshake pipelining. */
|
||||
if(!result)
|
||||
if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
/* Step 2: check if handshake is over. */
|
||||
if(!result && connssl->connecting_state == ssl_connect_2) {
|
||||
/* check allowed time left */
|
||||
@ -927,12 +1158,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
|
||||
result = gskit_connect_step2(conn, sockindex, nonblocking);
|
||||
}
|
||||
|
||||
/* Handle handshake pipelining. */
|
||||
if(!result)
|
||||
if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
|
||||
result = CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
/* Step 3: gather certificate info, verify host. */
|
||||
if(!result && connssl->connecting_state == ssl_connect_3)
|
||||
result = gskit_connect_step3(conn, sockindex);
|
||||
|
||||
if(result)
|
||||
close_one(connssl, data);
|
||||
close_one(connssl, conn, sockindex);
|
||||
else if(connssl->connecting_state == ssl_connect_done) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
@ -976,11 +1212,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
|
||||
|
||||
void Curl_gskit_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
|
||||
if(connssl->use)
|
||||
close_one(connssl, data);
|
||||
close_one(&conn->ssl[sockindex], conn, sockindex);
|
||||
close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
|
||||
}
|
||||
|
||||
|
||||
@ -999,7 +1232,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
|
||||
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
|
||||
return 0;
|
||||
|
||||
close_one(connssl, data);
|
||||
close_one(connssl, conn, sockindex);
|
||||
rc = 0;
|
||||
what = Curl_socket_ready(conn->sock[sockindex],
|
||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||
|
231
lib/vtls/gtls.c
231
lib/vtls/gtls.c
@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
|
||||
{
|
||||
return gnutls_record_send((gnutls_session_t) s, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
|
||||
{
|
||||
return gnutls_record_recv((gnutls_session_t) s, buf, len);
|
||||
}
|
||||
|
||||
/* Curl_gtls_init()
|
||||
*
|
||||
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
|
||||
@ -373,6 +383,9 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
void *ssl_sessionid;
|
||||
size_t ssl_idsize;
|
||||
bool sni = TRUE; /* default is SNI enabled */
|
||||
void *transport_ptr = NULL;
|
||||
gnutls_push_func gnutls_transport_push = NULL;
|
||||
gnutls_pull_func gnutls_transport_pull = NULL;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct in6_addr addr;
|
||||
#else
|
||||
@ -403,6 +416,9 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
const char *err = NULL;
|
||||
#endif
|
||||
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
|
||||
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
||||
/* to make us tolerant against being called more than once for the
|
||||
same connection */
|
||||
@ -412,11 +428,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(SSL_CONN_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(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
|
||||
sni = FALSE; /* SSLv3 has no SNI */
|
||||
|
||||
/* allocate a cred struct */
|
||||
@ -427,8 +443,8 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
|
||||
#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_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
|
||||
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
|
||||
|
||||
rc = gnutls_srp_allocate_client_credentials(
|
||||
&conn->ssl[sockindex].srp_client_cred);
|
||||
@ -440,8 +456,8 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
|
||||
rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
|
||||
srp_client_cred,
|
||||
data->set.ssl.username,
|
||||
data->set.ssl.password);
|
||||
SSL_SET_OPTION(username),
|
||||
SSL_SET_OPTION(password));
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data, "gnutls_srp_set_client_cred() failed: %s",
|
||||
gnutls_strerror(rc));
|
||||
@ -450,56 +466,56 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.ssl.CAfile) {
|
||||
if(SSL_CONN_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,
|
||||
SSL_CONN_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)
|
||||
SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
|
||||
if(SSL_CONN_CONFIG(verifypeer))
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else
|
||||
infof(data, "found %d certificates in %s\n",
|
||||
rc, data->set.ssl.CAfile);
|
||||
infof(data, "found %d certificates in %s\n", rc,
|
||||
SSL_CONN_CONFIG(CAfile));
|
||||
}
|
||||
|
||||
#ifdef HAS_CAPATH
|
||||
if(data->set.ssl.CApath) {
|
||||
if(SSL_CONN_CONFIG(CApath)) {
|
||||
/* set the trusted CA cert directory */
|
||||
rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
|
||||
data->set.ssl.CApath,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
SSL_CONN_CONFIG(CApath),
|
||||
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)
|
||||
SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
|
||||
if(SSL_CONN_CONFIG(verifypeer))
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
else
|
||||
infof(data, "found %d certificates in %s\n",
|
||||
rc, data->set.ssl.CApath);
|
||||
rc, SSL_CONN_CONFIG(CApath));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.ssl.CRLfile) {
|
||||
if(SSL_SET_OPTION(CRLfile)) {
|
||||
/* set the CRL list file */
|
||||
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
|
||||
data->set.ssl.CRLfile,
|
||||
SSL_SET_OPTION(CRLfile),
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
if(rc < 0) {
|
||||
failf(data, "error reading crl file %s (%s)",
|
||||
data->set.ssl.CRLfile, gnutls_strerror(rc));
|
||||
SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
|
||||
return CURLE_SSL_CRL_BADFILE;
|
||||
}
|
||||
else
|
||||
infof(data, "found %d CRL in %s\n",
|
||||
rc, data->set.ssl.CRLfile);
|
||||
rc, SSL_SET_OPTION(CRLfile));
|
||||
}
|
||||
|
||||
/* Initialize TLS session as a client */
|
||||
@ -512,13 +528,13 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
/* convenient assign */
|
||||
session = conn->ssl[sockindex].session;
|
||||
|
||||
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 &&
|
||||
(gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
|
||||
strlen(conn->host.name)) < 0))
|
||||
(gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
|
||||
strlen(hostname)) < 0))
|
||||
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||
"TLS extension\n");
|
||||
|
||||
@ -539,13 +555,13 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
if(rc != GNUTLS_E_SUCCESS)
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
|
||||
if(data->set.ssl.cipher_list != NULL) {
|
||||
if(SSL_CONN_CONFIG(cipher_list) != NULL) {
|
||||
failf(data, "can't pass a custom cipher list to older GnuTLS"
|
||||
" versions");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
switch (data->set.ssl.version) {
|
||||
switch (SSL_CONN_CONFIG(version) {
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
protocol_priority[0] = GNUTLS_SSL3;
|
||||
break;
|
||||
@ -580,7 +596,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 (SSL_CONN_CONFIG(version)) {
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
|
||||
sni = false;
|
||||
@ -655,8 +671,8 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
||||
if(SSL_SET_OPTION(cert)) {
|
||||
if(SSL_SET_OPTION(key_passwd)) {
|
||||
#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
|
||||
const unsigned int supported_key_encryption_algorithms =
|
||||
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
|
||||
@ -665,11 +681,11 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
GNUTLS_PKCS_USE_PBES2_AES_256;
|
||||
rc = gnutls_certificate_set_x509_key_file2(
|
||||
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.str[STRING_KEY_PASSWD],
|
||||
SSL_SET_OPTION(cert),
|
||||
SSL_SET_OPTION(key) ?
|
||||
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
|
||||
do_file_type(SSL_SET_OPTION(cert_type)),
|
||||
SSL_SET_OPTION(key_passwd),
|
||||
supported_key_encryption_algorithms);
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data,
|
||||
@ -683,15 +699,14 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc = gnutls_certificate_set_x509_key_file(
|
||||
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]) );
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data, "error reading X.509 key or certificate file: %s",
|
||||
gnutls_strerror(rc));
|
||||
SSL_SET_OPTION(cert),
|
||||
SSL_SET_OPTION(key) ?
|
||||
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
|
||||
do_file_type(SSL_SET_OPTION(cert_type)) ) !=
|
||||
GNUTLS_E_SUCCESS) {
|
||||
failf(data, "error reading X.509 key or certificate file");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
@ -699,7 +714,7 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
/* put the credentials to the current session */
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
|
||||
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
|
||||
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
|
||||
conn->ssl[sockindex].srp_client_cred);
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
@ -718,19 +733,30 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
/* set the connection handle (file descriptor for the socket) */
|
||||
gnutls_transport_set_ptr(session,
|
||||
GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
|
||||
if(conn->proxy_ssl[sockindex].use) {
|
||||
transport_ptr = conn->proxy_ssl[sockindex].session;
|
||||
gnutls_transport_push = Curl_gtls_push_ssl;
|
||||
gnutls_transport_pull = Curl_gtls_pull_ssl;
|
||||
}
|
||||
else {
|
||||
/* file descriptor for the socket */
|
||||
transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
|
||||
gnutls_transport_push = Curl_gtls_push;
|
||||
gnutls_transport_pull = Curl_gtls_pull;
|
||||
}
|
||||
|
||||
/* set the connection handle */
|
||||
gnutls_transport_set_ptr(session, transport_ptr);
|
||||
|
||||
/* register callback functions to send and receive data. */
|
||||
gnutls_transport_set_push_function(session, Curl_gtls_push);
|
||||
gnutls_transport_set_pull_function(session, Curl_gtls_pull);
|
||||
gnutls_transport_set_push_function(session, gnutls_transport_push);
|
||||
gnutls_transport_set_pull_function(session, gnutls_transport_pull);
|
||||
|
||||
/* lowat must be set to zero when using custom push and pull functions. */
|
||||
gnutls_transport_set_lowat(session, 0);
|
||||
|
||||
#ifdef HAS_OCSP
|
||||
if(data->set.ssl.verifystatus) {
|
||||
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||
rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
|
||||
@ -742,7 +768,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);
|
||||
|
||||
@ -837,8 +863,9 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
gnutls_datum_t proto;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
gnutls_protocol_t version = gnutls_protocol_get_version(session);
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
|
||||
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
|
||||
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
|
||||
@ -856,13 +883,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(SSL_CONN_CONFIG(verifypeer) ||
|
||||
SSL_CONN_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
|
||||
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
|
||||
&& SSL_SET_OPTION(username) != NULL
|
||||
&& !SSL_CONN_CONFIG(verifypeer)
|
||||
&& gnutls_cipher_get(session)) {
|
||||
/* no peer cert, but auth is ok if we have SRP user and cipher and no
|
||||
peer verify */
|
||||
@ -895,7 +922,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_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
|
||||
@ -911,10 +938,11 @@ 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(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "server certificate verification failed. CAfile: %s "
|
||||
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
|
||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
||||
"CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
|
||||
"none",
|
||||
SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
|
||||
return CURLE_SSL_CACERT;
|
||||
}
|
||||
else
|
||||
@ -927,7 +955,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
infof(data, "\t server certificate verification SKIPPED\n");
|
||||
|
||||
#ifdef HAS_OCSP
|
||||
if(data->set.ssl.verifystatus) {
|
||||
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
|
||||
gnutls_datum_t status_request;
|
||||
gnutls_ocsp_resp_t ocsp_resp;
|
||||
@ -1072,7 +1100,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
|
||||
alternative name PKIX extension. Returns non zero on success, and zero on
|
||||
failure. */
|
||||
rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
|
||||
rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030306
|
||||
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
|
||||
addresses. */
|
||||
@ -1088,10 +1116,10 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
|
||||
if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
|
||||
addrlen = 4;
|
||||
#ifdef ENABLE_IPV6
|
||||
else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
|
||||
else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
|
||||
addrlen = 16;
|
||||
#endif
|
||||
|
||||
@ -1116,15 +1144,18 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
#endif
|
||||
if(!rc) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
const char * const dispname = SSL_IS_PROXY() ?
|
||||
conn->http_proxy.host.dispname : conn->host.dispname;
|
||||
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
failf(data, "SSL: certificate subject name (%s) does not match "
|
||||
"target host name '%s'", certbuf, conn->host.dispname);
|
||||
"target host name '%s'", certbuf, dispname);
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
else
|
||||
infof(data, "\t common name: %s (does not match '%s')\n",
|
||||
certbuf, conn->host.dispname);
|
||||
certbuf, dispname);
|
||||
}
|
||||
else
|
||||
infof(data, "\t common name: %s (matched)\n", certbuf);
|
||||
@ -1133,7 +1164,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(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "server cert expiration date verify failed");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1143,7 +1174,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
if(certclock < time(NULL)) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "server certificate expiration date has passed.");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
@ -1158,7 +1189,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(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "server cert activation date verify failed");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
@ -1168,7 +1199,7 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
if(certclock > time(NULL)) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
failf(data, "server certificate not activated yet.");
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
@ -1276,7 +1307,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 */
|
||||
@ -1284,7 +1316,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;
|
||||
@ -1365,6 +1398,20 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
|
||||
{
|
||||
bool res = FALSE;
|
||||
if(conn->ssl[connindex].session &&
|
||||
0 != gnutls_record_check_pending(conn->ssl[connindex].session))
|
||||
res = TRUE;
|
||||
|
||||
if(conn->proxy_ssl[connindex].session &&
|
||||
0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
|
||||
res = TRUE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t gtls_send(struct connectdata *conn,
|
||||
int sockindex,
|
||||
const void *mem,
|
||||
@ -1384,29 +1431,29 @@ static ssize_t gtls_send(struct connectdata *conn,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void close_one(struct connectdata *conn,
|
||||
int idx)
|
||||
static void close_one(struct ssl_connect_data *ssl)
|
||||
{
|
||||
if(conn->ssl[idx].session) {
|
||||
gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
|
||||
gnutls_deinit(conn->ssl[idx].session);
|
||||
conn->ssl[idx].session = NULL;
|
||||
if(ssl->session) {
|
||||
gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
|
||||
gnutls_deinit(ssl->session);
|
||||
ssl->session = NULL;
|
||||
}
|
||||
if(conn->ssl[idx].cred) {
|
||||
gnutls_certificate_free_credentials(conn->ssl[idx].cred);
|
||||
conn->ssl[idx].cred = NULL;
|
||||
if(ssl->cred) {
|
||||
gnutls_certificate_free_credentials(ssl->cred);
|
||||
ssl->cred = NULL;
|
||||
}
|
||||
#ifdef USE_TLS_SRP
|
||||
if(conn->ssl[idx].srp_client_cred) {
|
||||
gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
|
||||
conn->ssl[idx].srp_client_cred = NULL;
|
||||
if(ssl->srp_client_cred) {
|
||||
gnutls_srp_free_client_credentials(ssl->srp_client_cred);
|
||||
ssl->srp_client_cred = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Curl_gtls_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
close_one(conn, sockindex);
|
||||
close_one(&conn->ssl[sockindex]);
|
||||
close_one(&conn->proxy_ssl[sockindex]);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1472,8 +1519,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
|
||||
gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
|
||||
&& data->set.ssl.username != NULL)
|
||||
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
|
||||
&& SSL_SET_OPTION(username) != NULL)
|
||||
gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
|
||||
#endif
|
||||
|
||||
@ -1539,8 +1586,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) {
|
||||
ssl_seeded = TRUE;
|
||||
}
|
||||
return 0;
|
||||
|
@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
|
||||
CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *done);
|
||||
bool Curl_gtls_data_pending(const struct connectdata *conn,
|
||||
int connindex);
|
||||
|
||||
/* close a SSL connection */
|
||||
void Curl_gtls_close(struct connectdata *conn, int sockindex);
|
||||
@ -78,7 +80,7 @@ bool Curl_gtls_cert_status_request(void);
|
||||
#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
|
||||
#define curlssl_version Curl_gtls_version
|
||||
#define curlssl_check_cxn(x) ((void)x, -1)
|
||||
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
|
||||
#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
|
||||
#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
|
||||
#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
|
||||
#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
|
||||
|
170
lib/vtls/nss.c
170
lib/vtls/nss.c
@ -319,9 +319,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))
|
||||
@ -554,6 +553,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
||||
SECStatus status;
|
||||
CURLcode result;
|
||||
struct ssl_connect_data *ssl = conn->ssl;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
(void)sockindex; /* unused */
|
||||
|
||||
@ -571,8 +571,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
||||
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
|
||||
PK11_IsPresent(slot);
|
||||
|
||||
status = PK11_Authenticate(slot, PR_TRUE,
|
||||
conn->data->set.str[STRING_KEY_PASSWD]);
|
||||
status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
|
||||
PK11_FreeSlot(slot);
|
||||
|
||||
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
|
||||
@ -651,7 +650,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(SSL_CONN_CONFIG(verifystatus)) {
|
||||
SECStatus cacheResult;
|
||||
|
||||
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
|
||||
@ -677,7 +676,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!conn->data->set.ssl.verifypeer) {
|
||||
if(!SSL_CONN_CONFIG(verifypeer)) {
|
||||
infof(conn->data, "skipping SSL peer certificate verification\n");
|
||||
return SECSuccess;
|
||||
}
|
||||
@ -897,9 +896,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
|
||||
CERTCertificate *cert;
|
||||
|
||||
/* remember the cert verification result */
|
||||
data->set.ssl.certverifyresult = err;
|
||||
if(SSL_IS_PROXY())
|
||||
data->set.proxy_ssl.certverifyresult = err;
|
||||
else
|
||||
data->set.ssl.certverifyresult = err;
|
||||
|
||||
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
|
||||
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
|
||||
/* we are asked not to verify the host name */
|
||||
return SECSuccess;
|
||||
|
||||
@ -1334,38 +1336,57 @@ Curl_nss_check_cxn(struct connectdata *conn)
|
||||
return -1; /* connection status unknown */
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when an SSL connection is closed.
|
||||
*/
|
||||
void Curl_nss_close(struct connectdata *conn, int sockindex)
|
||||
static void nss_close(struct ssl_connect_data *connssl)
|
||||
{
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
/* before the cleanup, check whether we are using a client certificate */
|
||||
const bool client_cert = (connssl->client_nickname != NULL)
|
||||
|| (connssl->obj_clicert != NULL);
|
||||
|
||||
free(connssl->client_nickname);
|
||||
connssl->client_nickname = NULL;
|
||||
|
||||
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
|
||||
Curl_llist_destroy(connssl->obj_list, NULL);
|
||||
connssl->obj_list = NULL;
|
||||
connssl->obj_clicert = NULL;
|
||||
|
||||
if(connssl->handle) {
|
||||
/* NSS closes the socket we previously handed to it, so we must mark it
|
||||
as closed to avoid double close */
|
||||
fake_sclose(conn->sock[sockindex]);
|
||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
|
||||
if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
|
||||
if(client_cert)
|
||||
/* A server might require different authentication based on the
|
||||
* particular path being requested by the client. To support this
|
||||
* scenario, we must ensure that a connection will never reuse the
|
||||
* authentication data from a previous connection. */
|
||||
SSL_InvalidateSession(connssl->handle);
|
||||
|
||||
free(connssl->client_nickname);
|
||||
connssl->client_nickname = NULL;
|
||||
/* destroy all NSS objects in order to avoid failure of NSS shutdown */
|
||||
Curl_llist_destroy(connssl->obj_list, NULL);
|
||||
connssl->obj_list = NULL;
|
||||
connssl->obj_clicert = NULL;
|
||||
|
||||
PR_Close(connssl->handle);
|
||||
connssl->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when an SSL connection is closed.
|
||||
*/
|
||||
void Curl_nss_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
|
||||
|
||||
if(connssl->handle || connssl_proxy->handle) {
|
||||
/* NSS closes the socket we previously handed to it, so we must mark it
|
||||
as closed to avoid double close */
|
||||
fake_sclose(conn->sock[sockindex]);
|
||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(connssl->handle)
|
||||
/* nss_close(connssl) will transitively close also connssl_proxy->handle
|
||||
if both are used. Clear it to avoid a double close leading to crash. */
|
||||
connssl_proxy->handle = NULL;
|
||||
|
||||
nss_close(connssl);
|
||||
nss_close(connssl_proxy);
|
||||
}
|
||||
|
||||
/* return true if NSS can provide error code (and possibly msg) for the
|
||||
error */
|
||||
static bool is_nss_error(CURLcode err)
|
||||
@ -1404,8 +1425,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 = SSL_CONN_CONFIG(CAfile);
|
||||
const char *capath = SSL_CONN_CONFIG(CApath);
|
||||
|
||||
if(cafile) {
|
||||
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
|
||||
@ -1453,9 +1474,10 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
}
|
||||
|
||||
static CURLcode nss_init_sslver(SSLVersionRange *sslver,
|
||||
struct SessionHandle *data)
|
||||
struct SessionHandle *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
switch(data->set.ssl.version) {
|
||||
switch (SSL_CONN_CONFIG(version)) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -1556,6 +1578,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
CURLcode result;
|
||||
bool second_layer = FALSE;
|
||||
|
||||
SSLVersionRange sslver = {
|
||||
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
|
||||
@ -1614,18 +1637,18 @@ 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) ?
|
||||
PR_FALSE : PR_TRUE;
|
||||
ssl_no_cache = (data->set.general_ssl.sessionid
|
||||
&& SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
|
||||
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
/* enable/disable the requested SSL version(s) */
|
||||
if(nss_init_sslver(&sslver, data) != CURLE_OK)
|
||||
if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
|
||||
goto error;
|
||||
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
ssl_cbc_random_iv = !data->set.ssl_enable_beast;
|
||||
ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
|
||||
#ifdef SSL_CBC_RANDOM_IV
|
||||
/* unless the user explicitly asks to allow the protocol vulnerability, we
|
||||
use the work-around */
|
||||
@ -1637,14 +1660,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(SSL_CONN_CONFIG(cipher_list)) {
|
||||
if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
|
||||
result = CURLE_SSL_CIPHER;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
|
||||
if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
|
||||
infof(data, "warning: ignoring value of ssl.verifyhost\n");
|
||||
|
||||
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
|
||||
@ -1652,14 +1675,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
data->set.ssl.certverifyresult=0; /* not checked yet */
|
||||
/* not checked yet */
|
||||
if(SSL_IS_PROXY())
|
||||
data->set.proxy_ssl.certverifyresult = 0;
|
||||
else
|
||||
data->set.ssl.certverifyresult = 0;
|
||||
|
||||
if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
|
||||
if(rv) {
|
||||
result = rv;
|
||||
@ -1667,24 +1695,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.ssl.CRLfile) {
|
||||
const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
|
||||
if(SSL_SET_OPTION(CRLfile)) {
|
||||
const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
|
||||
if(rv) {
|
||||
result = rv;
|
||||
goto error;
|
||||
}
|
||||
infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile);
|
||||
infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
char *nickname = dup_nickname(data, STRING_CERT);
|
||||
if(SSL_SET_OPTION(cert)) {
|
||||
char *nickname = dup_nickname(data, SSL_SET_OPTION(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, SSL_SET_OPTION(cert),
|
||||
SSL_SET_OPTION(key));
|
||||
if(rv) {
|
||||
/* failf() is already done in cert_stuff() */
|
||||
result = rv;
|
||||
@ -1704,15 +1732,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* wrap OS file descriptor by NSPR's file descriptor abstraction */
|
||||
nspr_io = PR_ImportTCPSocket(sockfd);
|
||||
if(!nspr_io)
|
||||
goto error;
|
||||
if(conn->proxy_ssl[sockindex].use) {
|
||||
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
|
||||
DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
|
||||
nspr_io = conn->proxy_ssl[sockindex].handle;
|
||||
second_layer = TRUE;
|
||||
}
|
||||
else {
|
||||
/* wrap OS file descriptor by NSPR's file descriptor abstraction */
|
||||
nspr_io = PR_ImportTCPSocket(sockfd);
|
||||
if(!nspr_io)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* create our own NSPR I/O layer */
|
||||
nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
|
||||
if(!nspr_io_stub) {
|
||||
PR_Close(nspr_io);
|
||||
if(!second_layer)
|
||||
PR_Close(nspr_io);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1721,7 +1758,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
|
||||
/* push our new layer to the NSPR I/O stack */
|
||||
if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
|
||||
PR_Close(nspr_io);
|
||||
if(!second_layer)
|
||||
PR_Close(nspr_io);
|
||||
PR_Close(nspr_io_stub);
|
||||
goto error;
|
||||
}
|
||||
@ -1729,7 +1767,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
/* import our model socket onto the current I/O stack */
|
||||
connssl->handle = SSL_ImportFD(model, nspr_io);
|
||||
if(!connssl->handle) {
|
||||
PR_Close(nspr_io);
|
||||
if(!second_layer)
|
||||
PR_Close(nspr_io);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1737,12 +1776,12 @@ 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(SSL_SET_OPTION(key_passwd)) {
|
||||
SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
|
||||
}
|
||||
|
||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
||||
if(data->set.ssl.verifystatus) {
|
||||
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||
if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
|
||||
!= SECSuccess)
|
||||
goto error;
|
||||
@ -1802,11 +1841,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
||||
goto error;
|
||||
|
||||
/* propagate hostname to the TLS layer */
|
||||
if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess)
|
||||
if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
/* prevent NSS from re-using the session for a different hostname */
|
||||
if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess)
|
||||
if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
|
||||
conn->http_proxy.host.name : conn->host.name)
|
||||
!= SECSuccess)
|
||||
goto error;
|
||||
|
||||
return CURLE_OK;
|
||||
@ -1824,6 +1866,8 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode result = CURLE_SSL_CONNECT_ERROR;
|
||||
PRUint32 timeout;
|
||||
long * const certverifyresult = SSL_IS_PROXY() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
|
||||
/* check timeout situation */
|
||||
const long time_left = Curl_timeleft(data, NULL, TRUE);
|
||||
@ -1839,9 +1883,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
||||
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
|
||||
/* blocking direction is updated by nss_update_connecting_state() */
|
||||
return CURLE_AGAIN;
|
||||
else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
|
||||
else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
|
||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||
else if(conn->data->set.ssl.certverifyresult!=0)
|
||||
else if(*certverifyresult != 0)
|
||||
result = CURLE_SSL_CACERT;
|
||||
goto error;
|
||||
}
|
||||
@ -1850,11 +1894,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);
|
||||
}
|
||||
|
@ -189,13 +189,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))
|
||||
@ -208,14 +208,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))
|
||||
@ -253,8 +253,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;
|
||||
}
|
||||
@ -334,7 +334,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;
|
||||
|
||||
@ -345,10 +346,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);
|
||||
}
|
||||
@ -457,7 +457,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",
|
||||
@ -570,7 +570,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
|
||||
@ -864,13 +864,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);
|
||||
@ -884,6 +879,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)
|
||||
@ -1046,16 +1050,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const char * const dispname = SSL_IS_PROXY() ?
|
||||
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);
|
||||
}
|
||||
@ -1097,7 +1105,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;
|
||||
@ -1119,13 +1127,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 {
|
||||
@ -1199,9 +1207,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 {
|
||||
@ -1638,17 +1646,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif
|
||||
long * const certverifyresult = SSL_IS_PROXY() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
const long int ssl_version = SSL_CONN_CONFIG(version);
|
||||
#ifdef USE_TLS_SRP
|
||||
const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
|
||||
#endif
|
||||
char * const ssl_cert = SSL_SET_OPTION(cert);
|
||||
const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
|
||||
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
|
||||
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
|
||||
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
|
||||
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
|
||||
const char * const hostname = SSL_IS_PROXY() ? 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:
|
||||
@ -1656,8 +1677,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
/* it will be handled later with the context options */
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
|
||||
req_method = TLS_client_method();
|
||||
#else
|
||||
req_method = SSLv23_client_method();
|
||||
@ -1670,7 +1691,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();
|
||||
@ -1683,7 +1704,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();
|
||||
@ -1768,14 +1789,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_SET_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
|
||||
@ -1869,19 +1890,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_SET_OPTION(key), SSL_SET_OPTION(key_type),
|
||||
SSL_SET_OPTION(key_passwd))) {
|
||||
/* failf() is already done in cert_stuff() */
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
|
||||
ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
ciphers = SSL_CONN_CONFIG(cipher_list);
|
||||
if(!ciphers)
|
||||
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
|
||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
|
||||
@ -1891,18 +1909,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_SET_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_SET_OPTION(password))) {
|
||||
failf(data, "failed setting SRP password");
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
|
||||
if(!SSL_CONN_CONFIG(cipher_list)) {
|
||||
infof(data, "Setting cipher list SRP\n");
|
||||
|
||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
|
||||
@ -1912,20 +1932,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 {
|
||||
@ -1942,22 +1959,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 {
|
||||
@ -1966,9 +1979,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
|
||||
@ -1990,8 +2001,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) {
|
||||
@ -2014,27 +2024,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_CONN_CONFIG(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",
|
||||
@ -2045,8 +2054,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;
|
||||
@ -2063,8 +2080,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
int err;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
||||
|| ssl_connect_2_reading == connssl->connecting_state
|
||||
|| ssl_connect_2_writing == connssl->connecting_state);
|
||||
|| ssl_connect_2_reading == connssl->connecting_state
|
||||
|| ssl_connect_2_writing == connssl->connecting_state);
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
@ -2139,8 +2156,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 = SSL_IS_PROXY() ?
|
||||
conn->http_proxy.host.name : conn->host.name;
|
||||
const long int port = SSL_IS_PROXY() ? 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;
|
||||
}
|
||||
|
||||
@ -2484,6 +2504,8 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
FILE *fp;
|
||||
char *buffer = data->state.buffer;
|
||||
const char *ptr;
|
||||
long * const certverifyresult = SSL_IS_PROXY() ?
|
||||
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||
BIO *mem = BIO_new(BIO_s_mem());
|
||||
|
||||
if(data->set.ssl.certinfo)
|
||||
@ -2499,7 +2521,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
infof(data, "Server certificate:\n");
|
||||
infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
|
||||
|
||||
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
||||
buffer, BUFSIZE);
|
||||
@ -2517,7 +2539,7 @@ static CURLcode servercert(struct connectdata *conn,
|
||||
|
||||
BIO_free(mem);
|
||||
|
||||
if(data->set.ssl.verifyhost) {
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
result = verifyhost(conn, connssl->server_cert);
|
||||
if(result) {
|
||||
X509_free(connssl->server_cert);
|
||||
@ -2540,12 +2562,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;
|
||||
@ -2555,7 +2577,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);
|
||||
@ -2567,7 +2589,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;
|
||||
@ -2575,15 +2597,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_CONN_CONFIG(verifypeer)) {
|
||||
/* We probably never reach this, because SSL_connect() will fail
|
||||
and we return earlier if verifypeer is set? */
|
||||
if(strict)
|
||||
@ -2602,7 +2623,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_CONN_CONFIG(verifystatus)) {
|
||||
result = verifystatus(conn, connssl);
|
||||
if(result) {
|
||||
X509_free(connssl->server_cert);
|
||||
@ -2647,7 +2668,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");
|
||||
@ -2658,7 +2680,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;
|
||||
@ -2679,8 +2701,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_CONN_CONFIG(verifypeer) ||
|
||||
SSL_CONN_CONFIG(verifyhost)));
|
||||
|
||||
if(!result)
|
||||
connssl->connecting_state = ssl_connect_done;
|
||||
@ -2827,7 +2849,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;
|
||||
}
|
||||
@ -2872,8 +2897,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;
|
||||
}
|
||||
|
@ -132,6 +132,10 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
|
||||
const char *capath = SSL_CONN_CONFIG(CApath);
|
||||
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||
conn->host.name;
|
||||
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
|
||||
|
||||
bool sni = TRUE; /* default is SNI enabled */
|
||||
int ret = -1;
|
||||
@ -146,11 +150,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(SSL_CONN_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(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
|
||||
sni = FALSE; /* SSLv3 has no SNI */
|
||||
|
||||
#ifdef THREADING_SUPPORT
|
||||
@ -180,34 +184,33 @@ 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(SSL_CONN_CONFIG(CAfile)) {
|
||||
ret = x509_crt_parse_file(&connssl->cacert,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
SSL_CONN_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);
|
||||
SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
|
||||
|
||||
if(data->set.ssl.verifypeer)
|
||||
if(SSL_CONN_CONFIG(verifypeer))
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_SSL_CAPATH]) {
|
||||
ret = x509_crt_parse_path(&connssl->cacert,
|
||||
data->set.str[STRING_SSL_CAPATH]);
|
||||
if(capath) {
|
||||
ret = x509_crt_parse_path(&connssl->cacert, capath);
|
||||
|
||||
if(ret<0) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||
#endif /* POLARSSL_ERROR_C */
|
||||
failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
|
||||
data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
|
||||
capath, -ret, errorbuf);
|
||||
|
||||
if(data->set.ssl.verifypeer)
|
||||
if(SSL_CONN_CONFIG(verifypeer))
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
}
|
||||
}
|
||||
@ -215,27 +218,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(SSL_SET_OPTION(cert)) {
|
||||
ret = x509_crt_parse_file(&connssl->clicert,
|
||||
data->set.str[STRING_CERT]);
|
||||
SSL_SET_OPTION(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);
|
||||
SSL_SET_OPTION(cert), -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the client private key */
|
||||
if(data->set.str[STRING_KEY]) {
|
||||
if(SSL_SET_OPTION(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, SSL_SET_OPTION(key),
|
||||
SSL_SET_OPTION(key_passwd));
|
||||
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
if(ret == 0)
|
||||
@ -249,7 +252,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);
|
||||
SSL_SET_OPTION(key), -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CERTPROBLEM;
|
||||
}
|
||||
@ -258,30 +261,29 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
/* Load the CRL */
|
||||
memset(&connssl->crl, 0, sizeof(x509_crl));
|
||||
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
if(SSL_SET_OPTION(CRLfile)) {
|
||||
ret = x509_crl_parse_file(&connssl->crl,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
SSL_SET_OPTION(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);
|
||||
SSL_SET_OPTION(CRLfile), -ret, errorbuf);
|
||||
|
||||
return CURLE_SSL_CRL_BADFILE;
|
||||
}
|
||||
}
|
||||
|
||||
infof(data, "PolarSSL: Connecting to %s:%d\n",
|
||||
conn->host.name, conn->remote_port);
|
||||
infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
|
||||
|
||||
if(ssl_init(&connssl->ssl)) {
|
||||
failf(data, "PolarSSL: ssl_init failed");
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
|
||||
switch(data->set.ssl.version) {
|
||||
switch(SSL_CONN_CONFIG(version)) {
|
||||
default:
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
@ -328,7 +330,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");
|
||||
}
|
||||
@ -339,16 +342,16 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
ssl_set_ca_chain(&connssl->ssl,
|
||||
&connssl->cacert,
|
||||
&connssl->crl,
|
||||
conn->host.name);
|
||||
hostname);
|
||||
|
||||
ssl_set_own_cert_rsa(&connssl->ssl,
|
||||
&connssl->clicert, &connssl->rsa);
|
||||
|
||||
if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
|
||||
if(!Curl_inet_pton(AF_INET, hostname, &addr) &&
|
||||
#ifdef ENABLE_IPV6
|
||||
!Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
|
||||
!Curl_inet_pton(AF_INET6, hostname, &addr) &&
|
||||
#endif
|
||||
sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
|
||||
sni && ssl_set_hostname(&connssl->ssl, hostname)) {
|
||||
infof(data, "WARNING: failed to configure "
|
||||
"server name indication (SNI) TLS extension\n");
|
||||
}
|
||||
@ -426,7 +429,7 @@ polarssl_connect_step2(struct connectdata *conn,
|
||||
|
||||
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
|
||||
|
||||
if(ret && data->set.ssl.verifypeer) {
|
||||
if(ret && SSL_CONN_CONFIG(verifypeer)) {
|
||||
if(ret & BADCERT_EXPIRED)
|
||||
failf(data, "Cert verify failed: BADCERT_EXPIRED");
|
||||
|
||||
@ -496,7 +499,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 +515,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. */
|
||||
@ -148,14 +148,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof(data, "schannel: disabled 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:
|
||||
@ -520,7 +520,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
|
||||
|
||||
@ -567,7 +567,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");
|
||||
@ -578,7 +579,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;
|
||||
@ -1441,7 +1443,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;
|
||||
|
249
lib/vtls/vtls.c
249
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,41 @@ 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) {
|
||||
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_NSS) || \
|
||||
defined(USE_GSKIT)
|
||||
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 +350,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 +378,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 +387,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 +408,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 +448,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 +465,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 +486,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 +500,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 +522,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 +542,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 +565,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 +576,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 +670,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;
|
||||
|
@ -50,11 +50,29 @@
|
||||
#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);
|
||||
/* set of helper macros for the backends to access the correct fields. For the
|
||||
proxy or for the remote host - to properly support HTTPS proxy */
|
||||
|
||||
#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
|
||||
ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
|
||||
CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
|
||||
#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \
|
||||
data->set.ssl.var)
|
||||
#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \
|
||||
conn->proxy_ssl_config.var : conn->ssl_config.var)
|
||||
|
||||
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 *);
|
||||
|
||||
@ -99,11 +117,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 */
|
||||
|
@ -1063,6 +1063,11 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
int matched = -1;
|
||||
size_t addrlen = (size_t) -1;
|
||||
ssize_t len;
|
||||
const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
|
||||
conn->host.name;
|
||||
const char * const dispname = SSL_IS_PROXY()?
|
||||
conn->http_proxy.host.dispname:
|
||||
conn->host.dispname;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct in6_addr addr;
|
||||
#else
|
||||
@ -1072,7 +1077,7 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
/* Verify that connection server matches info in X509 certificate at
|
||||
`beg'..`end'. */
|
||||
|
||||
if(!data->set.ssl.verifyhost)
|
||||
if(!SSL_CONN_CONFIG(verifyhost))
|
||||
return CURLE_OK;
|
||||
|
||||
if(!beg)
|
||||
@ -1081,11 +1086,11 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
|
||||
/* Get the server IP address. */
|
||||
#ifdef ENABLE_IPV6
|
||||
if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
|
||||
if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
|
||||
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))
|
||||
addrlen = sizeof(struct in_addr);
|
||||
|
||||
/* Process extensions. */
|
||||
@ -1110,7 +1115,7 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
name.beg, name.end);
|
||||
if(len > 0)
|
||||
if(strlen(dnsname) == (size_t) len)
|
||||
i = Curl_cert_hostcheck((const char *) dnsname, conn->host.name);
|
||||
i = Curl_cert_hostcheck((const char *) dnsname, hostname);
|
||||
free(dnsname);
|
||||
if(!i)
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
@ -1129,12 +1134,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
switch (matched) {
|
||||
case 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);
|
||||
return CURLE_OK;
|
||||
case 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);
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
@ -1166,14 +1171,14 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
}
|
||||
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
|
||||
failf(data, "SSL: illegal cert name field");
|
||||
else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) {
|
||||
else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
|
||||
infof(data, "\t common name: %s (matched)\n", dnsname);
|
||||
free(dnsname);
|
||||
return CURLE_OK;
|
||||
}
|
||||
else
|
||||
failf(data, "SSL: certificate subject name '%s' does not match "
|
||||
"target host name '%s'", dnsname, conn->host.dispname);
|
||||
"target host name '%s'", dnsname, dispname);
|
||||
free(dnsname);
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,19 @@ options:
|
||||
CURLOPT_PROXYPASSWORD
|
||||
CURLOPT_PROXYUSERNAME
|
||||
CURLOPT_PROXYUSERPWD
|
||||
CURLOPT_PROXY_CAINFO
|
||||
CURLOPT_PROXY_CAPATH
|
||||
CURLOPT_PROXY_CRLFILE
|
||||
CURLOPT_PROXY_KEYPASSWD
|
||||
CURLOPT_PROXY_SERVICE_NAME
|
||||
CURLOPT_PROXY_SSLCERT
|
||||
CURLOPT_PROXY_SSLCERTTYPE
|
||||
CURLOPT_PROXY_SSL_CIPHER_LIST
|
||||
CURLOPT_PROXY_SSLKEY
|
||||
CURLOPT_PROXY_SSLKEYTYPE
|
||||
CURLOPT_PROXY_TLSAUTH_PASSWORD
|
||||
CURLOPT_PROXY_TLSAUTH_TYPE
|
||||
CURLOPT_PROXY_TLSAUTH_USERNAME
|
||||
CURLOPT_RANDOM_FILE
|
||||
CURLOPT_RANGE
|
||||
CURLOPT_REFERER
|
||||
@ -103,6 +115,7 @@ options:
|
||||
CURLOPT_RTSP_TRANSPORT
|
||||
CURLOPT_SERVICE_NAME
|
||||
CURLOPT_SOCKS5_GSSAPI_SERVICE
|
||||
CURLOPT_SOCKS_PROXY
|
||||
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
|
||||
CURLOPT_SSH_KNOWNHOSTS
|
||||
CURLOPT_SSH_PRIVATE_KEYFILE
|
||||
|
@ -1164,7 +1164,19 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
case CURLOPT_PROXYPASSWORD:
|
||||
case CURLOPT_PROXYUSERNAME:
|
||||
case CURLOPT_PROXYUSERPWD:
|
||||
case CURLOPT_PROXY_CAINFO:
|
||||
case CURLOPT_PROXY_CAPATH:
|
||||
case CURLOPT_PROXY_CRLFILE:
|
||||
case CURLOPT_PROXY_KEYPASSWD:
|
||||
case CURLOPT_PROXY_SERVICE_NAME:
|
||||
case CURLOPT_PROXY_SSLCERT:
|
||||
case CURLOPT_PROXY_SSLCERTTYPE:
|
||||
case CURLOPT_PROXY_SSL_CIPHER_LIST:
|
||||
case CURLOPT_PROXY_SSLKEY:
|
||||
case CURLOPT_PROXY_SSLKEYTYPE:
|
||||
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
|
||||
case CURLOPT_PROXY_TLSAUTH_TYPE:
|
||||
case CURLOPT_PROXY_TLSAUTH_USERNAME:
|
||||
case CURLOPT_RANDOM_FILE:
|
||||
case CURLOPT_RANGE:
|
||||
case CURLOPT_REFERER:
|
||||
@ -1173,6 +1185,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
case CURLOPT_RTSP_TRANSPORT:
|
||||
case CURLOPT_SERVICE_NAME:
|
||||
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
|
||||
case CURLOPT_SOCKS_PROXY:
|
||||
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
|
||||
case CURLOPT_SSH_KNOWNHOSTS:
|
||||
case CURLOPT_SSH_PRIVATE_KEYFILE:
|
||||
|
@ -230,6 +230,8 @@
|
||||
d c 3
|
||||
d CURL_HTTP_VERSION_2...
|
||||
d c 3
|
||||
d CURL_HTTP_VERSION_2TLS...
|
||||
d c 4
|
||||
*
|
||||
d CURL_NETRC_IGNORED...
|
||||
d c 0
|
||||
@ -645,6 +647,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...
|
||||
@ -1238,6 +1242,42 @@
|
||||
d c 10240
|
||||
d CURLOPT_STREAM_DEPENDS_E...
|
||||
d c 10241
|
||||
d CURLOPT_PROXY_CAINFO...
|
||||
d c 10242
|
||||
d CURLOPT_PROXY_CAPATH...
|
||||
d c 10243
|
||||
d CURLOPT_PROXY_SSL_VERIFYPEER...
|
||||
d c 00244
|
||||
d CURLOPT_PROXY_SSL_VERIFYHOST...
|
||||
d c 00245
|
||||
d CURLOPT_PROXY_SSLVERSION...
|
||||
d c 00246
|
||||
d CURLOPT_PROXY_TLSAUTH_USERNAME...
|
||||
d c 10247
|
||||
d CURLOPT_PROXY_TLSAUTH_PASSWORD...
|
||||
d c 10248
|
||||
d CURLOPT_PROXY_TLSAUTH_TYPE...
|
||||
d c 10249
|
||||
d CURLOPT_PROXY_SSLCERT...
|
||||
d c 10250
|
||||
d CURLOPT_PROXY_SSLCERTTYPE...
|
||||
d c 10251
|
||||
d CURLOPT_PROXY_SSLKEY...
|
||||
d c 10252
|
||||
d CURLOPT_PROXY_SSLKEYTYPE...
|
||||
d c 10253
|
||||
d CURLOPT_PROXY_KEYPASSWD...
|
||||
d c 10254
|
||||
d CURLOPT_PROXY_SSL_CIPHER_LIST...
|
||||
d c 10255
|
||||
d CURLOPT_PROXY_CRLFILE...
|
||||
d c 10256
|
||||
d CURLOPT_PROXY_SSL_OPTIONS...
|
||||
d c 00257
|
||||
d CURLOPT_SOCKS_PROXY...
|
||||
d c 10258
|
||||
d CURLOPT_SOCKS_PROXYTYPE...
|
||||
d c 00259
|
||||
*
|
||||
/if not defined(CURL_NO_OLDIES)
|
||||
d CURLOPT_FILE c 10001
|
||||
@ -1420,6 +1460,8 @@
|
||||
d c X'0040002B'
|
||||
d CURLINFO_ACTIVESOCKET... CURLINFO_SOCKET + 44
|
||||
d c X'0050002C'
|
||||
d CURLINFO_PROXY_SSL_VERIFYRESULT... CURLINFO_LONG + 45
|
||||
d c X'0020002D'
|
||||
*
|
||||
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
|
||||
d c X'00200002'
|
||||
|
@ -67,6 +67,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);
|
||||
|
||||
@ -98,15 +101,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);
|
||||
|
@ -78,6 +78,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 */
|
||||
@ -106,15 +109,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;
|
||||
@ -127,6 +139,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;
|
||||
@ -142,6 +156,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;
|
||||
@ -200,7 +215,10 @@ 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 ssl_no_revoke; /* disable SSL certificate revocation checks */
|
||||
/*bool proxy_ssl_no_revoke; */
|
||||
|
||||
bool use_metalink; /* process given URLs as metalink XML file */
|
||||
metalinkfile *metalinkfile_list; /* point to the first node */
|
||||
|
@ -222,7 +222,25 @@ static const struct LongShort aliases[]= {
|
||||
{"Ep", "pinnedpubkey", TRUE},
|
||||
{"Eq", "cert-status", FALSE},
|
||||
{"Er", "false-start", FALSE},
|
||||
{"Es", "ssl-no-revoke", FALSE},
|
||||
{"EA", "ssl-no-revoke", 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},
|
||||
@ -379,6 +397,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
|
||||
@ -1309,6 +1341,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);
|
||||
@ -1390,23 +1425,90 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
config->falsestart = TRUE;
|
||||
break;
|
||||
|
||||
case 's': /* --ssl-no-revoke */
|
||||
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 'A': /* --ssl-no-revoke */
|
||||
if(curlinfo->features & CURL_VERSION_SSL)
|
||||
config->ssl_no_revoke = 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 '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",
|
||||
|
@ -867,8 +867,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 */
|
||||
@ -996,6 +997,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)) {
|
||||
|
||||
@ -1013,19 +1015,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);
|
||||
@ -1036,6 +1055,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);
|
||||
@ -1044,6 +1070,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);
|
||||
@ -1145,6 +1173,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 */
|
||||
@ -1318,6 +1350,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 */
|
||||
@ -1333,6 +1374,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
||||
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
|
||||
}
|
||||
|
||||
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),
|
||||
@ -155,6 +164,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[];
|
||||
@ -61,6 +62,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
|
||||
@ -69,6 +71,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…
Reference in New Issue
Block a user