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_PRIMARY_PORT 7.21.0
|
||||||
CURLINFO_PRIVATE 7.10.3
|
CURLINFO_PRIVATE 7.10.3
|
||||||
CURLINFO_PROXYAUTH_AVAIL 7.10.8
|
CURLINFO_PROXYAUTH_AVAIL 7.10.8
|
||||||
|
CURLINFO_PROXY_SSL_VERIFYRESULT 7.44.0
|
||||||
CURLINFO_REDIRECT_COUNT 7.9.7
|
CURLINFO_REDIRECT_COUNT 7.9.7
|
||||||
CURLINFO_REDIRECT_TIME 7.9.7
|
CURLINFO_REDIRECT_TIME 7.9.7
|
||||||
CURLINFO_REDIRECT_URL 7.18.2
|
CURLINFO_REDIRECT_URL 7.18.2
|
||||||
@@ -462,7 +463,23 @@ CURLOPT_PROXYPORT 7.1
|
|||||||
CURLOPT_PROXYTYPE 7.10
|
CURLOPT_PROXYTYPE 7.10
|
||||||
CURLOPT_PROXYUSERNAME 7.19.1
|
CURLOPT_PROXYUSERNAME 7.19.1
|
||||||
CURLOPT_PROXYUSERPWD 7.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_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_PROXY_TRANSFER_MODE 7.18.0
|
||||||
CURLOPT_PUT 7.1
|
CURLOPT_PUT 7.1
|
||||||
CURLOPT_QUOTE 7.1
|
CURLOPT_QUOTE 7.1
|
||||||
@@ -492,6 +509,8 @@ CURLOPT_SOCKOPTDATA 7.16.0
|
|||||||
CURLOPT_SOCKOPTFUNCTION 7.16.0
|
CURLOPT_SOCKOPTFUNCTION 7.16.0
|
||||||
CURLOPT_SOCKS5_GSSAPI_NEC 7.19.4
|
CURLOPT_SOCKS5_GSSAPI_NEC 7.19.4
|
||||||
CURLOPT_SOCKS5_GSSAPI_SERVICE 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_HOST 7.12.1 - 7.15.5
|
||||||
CURLOPT_SOURCE_PATH 7.12.1 - 7.15.5
|
CURLOPT_SOURCE_PATH 7.12.1 - 7.15.5
|
||||||
CURLOPT_SOURCE_PORT 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
|
CURLPROTO_TFTP 7.19.4
|
||||||
CURLPROXY_HTTP 7.10
|
CURLPROXY_HTTP 7.10
|
||||||
CURLPROXY_HTTP_1_0 7.19.4
|
CURLPROXY_HTTP_1_0 7.19.4
|
||||||
|
CURLPROXY_HTTPS 7.44.0
|
||||||
CURLPROXY_SOCKS4 7.10
|
CURLPROXY_SOCKS4 7.10
|
||||||
CURLPROXY_SOCKS4A 7.18.0
|
CURLPROXY_SOCKS4A 7.18.0
|
||||||
CURLPROXY_SOCKS5 7.10
|
CURLPROXY_SOCKS5 7.10
|
||||||
|
@@ -622,6 +622,7 @@ typedef enum {
|
|||||||
CONNECT HTTP/1.1 */
|
CONNECT HTTP/1.1 */
|
||||||
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
|
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
|
||||||
HTTP/1.0 */
|
HTTP/1.0 */
|
||||||
|
CURLPROXY_HTTPS = 2, /* added in TBD */
|
||||||
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
|
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
|
||||||
in 7.10 */
|
in 7.10 */
|
||||||
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
|
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
|
||||||
@@ -1188,7 +1189,8 @@ typedef enum {
|
|||||||
CINIT(SHARE, OBJECTPOINT, 100),
|
CINIT(SHARE, OBJECTPOINT, 100),
|
||||||
|
|
||||||
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
|
/* 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),
|
CINIT(PROXYTYPE, LONG, 101),
|
||||||
|
|
||||||
/* Set the Accept-Encoding string. Use this to tell a server you would like
|
/* 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 */
|
/* Set E-xclusive stream dependency on another CURL handle */
|
||||||
CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
|
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 */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
@@ -2167,9 +2233,10 @@ typedef enum {
|
|||||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||||
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
|
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
|
||||||
|
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 45,
|
||||||
/* Fill in new entries below here! */
|
/* Fill in new entries below here! */
|
||||||
|
|
||||||
CURLINFO_LASTONE = 44
|
CURLINFO_LASTONE = 45
|
||||||
} CURLINFO;
|
} CURLINFO;
|
||||||
|
|
||||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
/* 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)
|
static char *hashkey(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
return aprintf("%s:%d",
|
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);
|
conn->localport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -850,7 +850,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
failf(data, "Failed to connect to %s port %ld: %s",
|
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));
|
conn->port, Curl_strerror(conn, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -137,8 +137,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
|||||||
|
|
||||||
if(proxy) {
|
if(proxy) {
|
||||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||||
userp = conn->proxyuser;
|
userp = conn->http_proxy.user;
|
||||||
passwdp = conn->proxypasswd;
|
passwdp = conn->http_proxy.passwd;
|
||||||
ntlm = &conn->proxyntlm;
|
ntlm = &conn->proxyntlm;
|
||||||
authp = &conn->data->state.authproxy;
|
authp = &conn->data->state.authproxy;
|
||||||
}
|
}
|
||||||
|
@@ -350,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
|||||||
|
|
||||||
if(proxy) {
|
if(proxy) {
|
||||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||||
userp = conn->proxyuser;
|
userp = conn->http_proxy.user;
|
||||||
ntlm = &conn->proxyntlm;
|
ntlm = &conn->proxyntlm;
|
||||||
authp = &conn->data->state.authproxy;
|
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;
|
struct FTP *ftp = data->req.protop;
|
||||||
CURLcode result = CURLE_OK;
|
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
|
/* since we only have a plaintext TCP connection here, we must now
|
||||||
* do the TLS stuff */
|
* do the TLS stuff */
|
||||||
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
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.
|
* wait for more data anyway.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
else {
|
else if(!Curl_ssl_data_pending(conn, FIRSTSOCKET)) {
|
||||||
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
|
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
|
||||||
case -1: /* select() error, stop reading */
|
case -1: /* select() error, stop reading */
|
||||||
failf(data, "FTP response aborted due to select/poll error: %d",
|
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;
|
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)
|
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
|
If a proxy tunnel is used, returns the original host name instead, because
|
||||||
the effective control connection address is the proxy address,
|
the effective control connection address is the proxy address,
|
||||||
not the ftp host. */
|
not the ftp host. */
|
||||||
if(conn->bits.tunnel_proxy ||
|
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
|
||||||
conn->proxytype == CURLPROXY_SOCKS5 ||
|
|
||||||
conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
|
|
||||||
conn->proxytype == CURLPROXY_SOCKS4 ||
|
|
||||||
conn->proxytype == CURLPROXY_SOCKS4A)
|
|
||||||
return conn->host.name;
|
return conn->host.name;
|
||||||
|
|
||||||
return conn->ip_addr_str;
|
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
|
* 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!
|
* 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)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
/* BLOCKING, ignores the return code but 'addr' will be NULL in
|
/* BLOCKING, ignores the return code but 'addr' will be NULL in
|
||||||
case of failure */
|
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 */
|
(unsigned short)conn->port; /* we connect to the proxy's port */
|
||||||
|
|
||||||
if(!addr) {
|
if(!addr) {
|
||||||
failf(data, "Can't resolve proxy host %s:%hu",
|
failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
|
||||||
conn->proxy.name, connectport);
|
|
||||||
return CURLE_FTP_CANT_GET_HOST;
|
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 */
|
/* this just dumps information about this second connection */
|
||||||
ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
|
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 */
|
Curl_resolv_unlock(data, addr); /* we're done using this address */
|
||||||
conn->bits.do_more = TRUE;
|
conn->bits.do_more = TRUE;
|
||||||
state(conn, FTP_STOP); /* this phase is completed */
|
state(conn, FTP_STOP); /* this phase is completed */
|
||||||
@@ -2755,7 +2678,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
/* We don't have a SSL/TLS connection yet, but FTPS is
|
||||||
requested. Try a FTPS connection now */
|
requested. Try a FTPS connection now */
|
||||||
|
|
||||||
@@ -2800,7 +2726,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||||||
/* Curl_ssl_connect is BLOCKING */
|
/* Curl_ssl_connect is BLOCKING */
|
||||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
||||||
if(!result) {
|
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);
|
result = ftp_state_user(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2842,7 +2768,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||||||
case FTP_PROT:
|
case FTP_PROT:
|
||||||
if(ftpcode/100 == 2)
|
if(ftpcode/100 == 2)
|
||||||
/* We have enabled SSL for the data connection! */
|
/* 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;
|
(data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
|
||||||
/* FTP servers typically responds with 500 if they decide to reject
|
/* FTP servers typically responds with 500 if they decide to reject
|
||||||
our 'P' request */
|
our 'P' request */
|
||||||
@@ -3670,10 +3596,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
|||||||
/* Ready to do more? */
|
/* Ready to do more? */
|
||||||
if(connected) {
|
if(connected) {
|
||||||
DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
|
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 {
|
else {
|
||||||
if(result && (ftpc->count1 == 0)) {
|
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) {
|
if(ftpc->state) {
|
||||||
/* already in a state so skip the intial commands.
|
/* already in a state so skip the intial commands.
|
||||||
They are only done to kickstart the do_more state */
|
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 *cur_pos;
|
||||||
const char *filename = NULL;
|
const char *filename = NULL;
|
||||||
|
|
||||||
cur_pos = path_to_use; /* current position in path. point at the begin
|
cur_pos = path_to_use; /* current position in path. point at the begin of
|
||||||
of next path component */
|
next path component */
|
||||||
|
|
||||||
ftpc->ctl_valid = FALSE;
|
ftpc->ctl_valid = FALSE;
|
||||||
ftpc->cwdfail = FALSE;
|
ftpc->cwdfail = FALSE;
|
||||||
|
@@ -148,6 +148,9 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
|
|||||||
case CURLINFO_SSL_VERIFYRESULT:
|
case CURLINFO_SSL_VERIFYRESULT:
|
||||||
*param_longp = data->set.ssl.certverifyresult;
|
*param_longp = data->set.ssl.certverifyresult;
|
||||||
break;
|
break;
|
||||||
|
case CURLINFO_PROXY_SSL_VERIFYRESULT:
|
||||||
|
*param_longp = data->set.proxy_ssl.certverifyresult;
|
||||||
|
break;
|
||||||
case CURLINFO_REDIRECT_COUNT:
|
case CURLINFO_REDIRECT_COUNT:
|
||||||
*param_longp = data->set.followlocation;
|
*param_longp = data->set.followlocation;
|
||||||
break;
|
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) {
|
if(proxy) {
|
||||||
userp = &conn->allocptr.proxyuserpwd;
|
userp = &conn->allocptr.proxyuserpwd;
|
||||||
user = conn->proxyuser;
|
user = conn->http_proxy.user;
|
||||||
pwd = conn->proxypasswd;
|
pwd = conn->http_proxy.passwd;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
userp = &conn->allocptr.userpwd;
|
userp = &conn->allocptr.userpwd;
|
||||||
@@ -642,7 +642,7 @@ output_auth_headers(struct connectdata *conn,
|
|||||||
if(auth) {
|
if(auth) {
|
||||||
infof(data, "%s auth using %s with user '%s'\n",
|
infof(data, "%s auth using %s with user '%s'\n",
|
||||||
proxy?"Proxy":"Server", auth,
|
proxy?"Proxy":"Server", auth,
|
||||||
proxy?(conn->proxyuser?conn->proxyuser:""):
|
proxy?(conn->http_proxy.user?conn->http_proxy.user:""):
|
||||||
(conn->user?conn->user:""));
|
(conn->user?conn->user:""));
|
||||||
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
|
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
@@ -1092,8 +1092,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
|||||||
return result;
|
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
|
/* 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
|
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
|
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");
|
connkeep(conn, "HTTP default");
|
||||||
|
|
||||||
/* the CONNECT procedure might not have been completed */
|
/* the CONNECT procedure might not have been completed */
|
||||||
result = Curl_proxy_connect(conn);
|
result = Curl_proxy_connect(conn, FIRSTSOCKET);
|
||||||
if(result)
|
if(result)
|
||||||
return 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)
|
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
|
||||||
/* nothing else to do except wait right now - we're not done here. */
|
/* nothing else to do except wait right now - we're not done here. */
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@@ -1391,49 +1394,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
|||||||
|
|
||||||
return result;
|
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,
|
static int https_getsock(struct connectdata *conn,
|
||||||
curl_socket_t *socks,
|
curl_socket_t *socks,
|
||||||
int numsocks)
|
int numsocks)
|
||||||
{
|
{
|
||||||
if(conn->handler->flags & PROTOPT_SSL) {
|
if(conn->handler->flags & PROTOPT_SSL)
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
|
return Curl_ssl_getsock(conn, socks, numsocks);
|
||||||
|
|
||||||
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;
|
|
||||||
return GETSOCK_BLANK;
|
return GETSOCK_BLANK;
|
||||||
}
|
}
|
||||||
#endif /* USE_SSL */
|
#endif /* USE_SSL */
|
||||||
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_http_done() gets called from Curl_done() after a single HTTP request
|
* 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) {
|
if(proxy) {
|
||||||
digest = &data->state.proxydigest;
|
digest = &data->state.proxydigest;
|
||||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||||
userp = conn->proxyuser;
|
userp = conn->http_proxy.user;
|
||||||
passwdp = conn->proxypasswd;
|
passwdp = conn->http_proxy.passwd;
|
||||||
authp = &data->state.authproxy;
|
authp = &data->state.authproxy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -65,7 +65,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
char *spn = Curl_sasl_build_gssapi_spn(
|
char *spn = Curl_sasl_build_gssapi_spn(
|
||||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||||
data->set.str[STRING_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)
|
if(!spn)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
@@ -90,14 +90,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
|||||||
|
|
||||||
if(!neg_ctx->server_name) {
|
if(!neg_ctx->server_name) {
|
||||||
/* Check proxy auth requested but no given proxy 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;
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
|
||||||
/* Generate our SPN */
|
/* Generate our SPN */
|
||||||
neg_ctx->server_name = Curl_sasl_build_spn(
|
neg_ctx->server_name = Curl_sasl_build_spn(
|
||||||
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
proxy ? data->set.str[STRING_PROXY_SERVICE_NAME] :
|
||||||
data->set.str[STRING_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)
|
if(!neg_ctx->server_name)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@@ -37,19 +37,57 @@
|
|||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "curl_printf.h"
|
#include "curl_printf.h"
|
||||||
#include "curlx.h"
|
#include "curlx.h"
|
||||||
|
#include "vtls/vtls.h"
|
||||||
|
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#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) {
|
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||||
#ifndef CURL_DISABLE_PROXY
|
#ifndef CURL_DISABLE_PROXY
|
||||||
/* for [protocol] tunneled through HTTP proxy */
|
/* for [protocol] tunneled through HTTP proxy */
|
||||||
struct HTTP http_proxy;
|
struct HTTP http_proxy;
|
||||||
void *prot_save;
|
void *prot_save;
|
||||||
CURLcode result;
|
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 */
|
/* BLOCKING */
|
||||||
/* We want "seamless" operations through HTTP proxy tunnel */
|
/* 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));
|
memset(&http_proxy, 0, sizeof(http_proxy));
|
||||||
conn->data->req.protop = &http_proxy;
|
conn->data->req.protop = &http_proxy;
|
||||||
connkeep(conn, "HTTP proxy CONNECT");
|
connkeep(conn, "HTTP proxy CONNECT");
|
||||||
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
|
result = Curl_proxyCONNECT(conn, sockindex, host, port, FALSE);
|
||||||
conn->host.name, conn->remote_port, FALSE);
|
|
||||||
conn->data->req.protop = prot_save;
|
conn->data->req.protop = prot_save;
|
||||||
if(CURLE_OK != result)
|
if(CURLE_OK != result)
|
||||||
return result;
|
return result;
|
||||||
@@ -152,7 +189,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
char *host=(char *)"";
|
char *host=(char *)"";
|
||||||
const char *proxyconn="";
|
const char *proxyconn="";
|
||||||
const char *useragent="";
|
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";
|
"1.0" : "1.1";
|
||||||
char *hostheader= /* host:port with IPv6 support */
|
char *hostheader= /* host:port with IPv6 support */
|
||||||
aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
|
aprintf("%s%s%s:%hu", conn->bits.ipv6_ip?"[":"",
|
||||||
|
@@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
/* Default proxy timeout in milliseconds */
|
/* Default proxy timeout in milliseconds */
|
||||||
#define PROXY_TIMEOUT (3600*1000)
|
#define PROXY_TIMEOUT (3600*1000)
|
||||||
|
|
||||||
CURLcode Curl_proxy_connect(struct connectdata *conn);
|
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
|
#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
|
||||||
|
|
||||||
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
#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);
|
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
|
||||||
#else
|
#else
|
||||||
int ldap_option;
|
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)
|
#if defined(CURL_HAS_NOVELL_LDAPSDK)
|
||||||
rc = ldapssl_client_init(NULL, NULL);
|
rc = ldapssl_client_init(NULL, NULL);
|
||||||
if(rc != LDAP_SUCCESS) {
|
if(rc != LDAP_SUCCESS) {
|
||||||
@@ -281,11 +281,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
|
|||||||
result = CURLE_SSL_CERTPROBLEM;
|
result = CURLE_SSL_CERTPROBLEM;
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
if(data->set.ssl.verifypeer) {
|
if(conn->ssl_config.verifypeer) {
|
||||||
/* Novell SDK supports DER or BASE64 files. */
|
/* Novell SDK supports DER or BASE64 files. */
|
||||||
int cert_type = LDAPSSL_CERT_FILETYPE_B64;
|
int cert_type = LDAPSSL_CERT_FILETYPE_B64;
|
||||||
if((data->set.str[STRING_CERT_TYPE]) &&
|
if((data->set.ssl.cert_type) &&
|
||||||
(Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
|
(Curl_raw_equal(data->set.ssl.cert_type, "DER")))
|
||||||
cert_type = LDAPSSL_CERT_FILETYPE_DER;
|
cert_type = LDAPSSL_CERT_FILETYPE_DER;
|
||||||
if(!ldap_ca) {
|
if(!ldap_ca) {
|
||||||
failf(data, "LDAP local: ERROR %s CA cert not set!",
|
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;
|
goto quit;
|
||||||
}
|
}
|
||||||
#elif defined(LDAP_OPT_X_TLS)
|
#elif defined(LDAP_OPT_X_TLS)
|
||||||
if(data->set.ssl.verifypeer) {
|
if(conn->ssl_config.verifypeer) {
|
||||||
/* OpenLDAP SDK supports BASE64 files. */
|
/* OpenLDAP SDK supports BASE64 files. */
|
||||||
if((data->set.str[STRING_CERT_TYPE]) &&
|
if((data->set.ssl.cert_type) &&
|
||||||
(!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
|
(!Curl_raw_equal(data->set.ssl.cert_type, "PEM"))) {
|
||||||
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
|
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
|
||||||
result = CURLE_SSL_CERTPROBLEM;
|
result = CURLE_SSL_CERTPROBLEM;
|
||||||
goto quit;
|
goto quit;
|
||||||
|
18
lib/multi.c
18
lib/multi.c
@@ -42,7 +42,8 @@
|
|||||||
#include "multihandle.h"
|
#include "multihandle.h"
|
||||||
#include "pipeline.h"
|
#include "pipeline.h"
|
||||||
#include "sigpipe.h"
|
#include "sigpipe.h"
|
||||||
#include "curl_printf.h"
|
#include "vtls/vtls.h"
|
||||||
|
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
@@ -642,6 +643,9 @@ static int waitconnect_getsock(struct connectdata *conn,
|
|||||||
if(!numsocks)
|
if(!numsocks)
|
||||||
return GETSOCK_BLANK;
|
return GETSOCK_BLANK;
|
||||||
|
|
||||||
|
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||||
|
return Curl_ssl_getsock(conn, sock, numsocks);
|
||||||
|
|
||||||
for(i=0; i<2; i++) {
|
for(i=0; i<2; i++) {
|
||||||
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
|
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
|
||||||
sock[s] = conn->tempsock[i];
|
sock[s] = conn->tempsock[i];
|
||||||
@@ -1236,7 +1240,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
multistate(data, CURLM_STATE_CONNECT);
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
}
|
}
|
||||||
else if(!result) {
|
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 */
|
/* initiate protocol connect phase */
|
||||||
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
|
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 */
|
/* awaiting a completion of an asynch TCP connect */
|
||||||
result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
|
result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
|
||||||
if(connected && !result) {
|
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;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
multistate(data, data->easy_conn->bits.tunnel_proxy?
|
multistate(data, data->easy_conn->bits.tunnel_proxy?
|
||||||
CURLM_STATE_WAITPROXYCONNECT:
|
CURLM_STATE_WAITPROXYCONNECT:
|
||||||
|
@@ -38,7 +38,9 @@ typedef enum {
|
|||||||
CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
|
CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */
|
||||||
CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
|
CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */
|
||||||
CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect 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_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
|
||||||
CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
|
CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
|
||||||
phase */
|
phase */
|
||||||
|
@@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
|
|||||||
else
|
else
|
||||||
interval_ms = 0; /* immediate */
|
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 */
|
/* We are receiving and there is data in the cache so just read it */
|
||||||
rc = 1;
|
rc = 1;
|
||||||
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
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));
|
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)
|
int Curl_raw_nequal(const char *first, const char *second, size_t max)
|
||||||
{
|
{
|
||||||
while(*first && *second && max) {
|
while(*first && *second && max) {
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
int Curl_raw_equal(const char *first, const char *second);
|
int Curl_raw_equal(const char *first, const char *second);
|
||||||
int Curl_raw_nequal(const char *first, const char *second, size_t max);
|
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);
|
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,
|
const char *hostname,
|
||||||
int remote_port,
|
int remote_port,
|
||||||
int sockindex,
|
int sockindex,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn)
|
||||||
bool protocol4a)
|
|
||||||
{
|
{
|
||||||
|
const bool protocol4a =
|
||||||
|
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
|
||||||
#define SOCKS4REQLEN 262
|
#define SOCKS4REQLEN 262
|
||||||
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
|
unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
|
||||||
id */
|
id */
|
||||||
@@ -127,6 +128,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
|||||||
return CURLE_OPERATION_TIMEDOUT;
|
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);
|
(void)curlx_nonblock(sock, FALSE);
|
||||||
|
|
||||||
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
|
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];
|
curl_socket_t sock = conn->sock[sockindex];
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
long timeout;
|
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);
|
const size_t hostname_len = strlen(hostname);
|
||||||
ssize_t len = 0;
|
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 */
|
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
|
||||||
if(!socks5_resolve_local && hostname_len > 255) {
|
if(!socks5_resolve_local && hostname_len > 255) {
|
||||||
infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
|
infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
#ifdef CURL_DISABLE_PROXY
|
#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
|
#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
@@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
|||||||
const char *hostname,
|
const char *hostname,
|
||||||
int remote_port,
|
int remote_port,
|
||||||
int sockindex,
|
int sockindex,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn);
|
||||||
bool protocol4a);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function logs in to a SOCKS5 proxy and sends the specifics to the
|
* 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;
|
char *user=NULL;
|
||||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||||
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||||
|
const size_t serviceptr_length = strlen(serviceptr);
|
||||||
|
|
||||||
/* GSS-API request looks like
|
/* GSS-API request looks like
|
||||||
* +----+------+-----+----------------+
|
* +----+------+-----+----------------+
|
||||||
@@ -132,22 +133,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
|||||||
|
|
||||||
/* prepare service name */
|
/* prepare service name */
|
||||||
if(strchr(serviceptr, '/')) {
|
if(strchr(serviceptr, '/')) {
|
||||||
service.value = malloc(strlen(serviceptr));
|
service.length = serviceptr_length;
|
||||||
|
service.value = malloc(service.length);
|
||||||
if(!service.value)
|
if(!service.value)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
service.length = strlen(serviceptr);
|
|
||||||
memcpy(service.value, serviceptr, service.length);
|
memcpy(service.value, serviceptr, service.length);
|
||||||
|
|
||||||
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
||||||
(gss_OID) GSS_C_NULL_OID, &server);
|
(gss_OID) GSS_C_NULL_OID, &server);
|
||||||
}
|
}
|
||||||
else {
|
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)
|
if(!service.value)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
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",
|
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_major_status = gss_import_name(&gss_minor_status, &service,
|
||||||
GSS_C_NT_HOSTBASED_SERVICE, &server);
|
GSS_C_NT_HOSTBASED_SERVICE, &server);
|
||||||
|
@@ -84,6 +84,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
|||||||
unsigned long qop;
|
unsigned long qop;
|
||||||
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
|
||||||
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||||
|
const size_t service_length = strlen(service);
|
||||||
|
|
||||||
/* GSS-API request looks like
|
/* GSS-API request looks like
|
||||||
* +----+------+-----+----------------+
|
* +----+------+-----+----------------+
|
||||||
@@ -95,17 +96,19 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
|||||||
|
|
||||||
/* prepare service name */
|
/* prepare service name */
|
||||||
if(strchr(service, '/')) {
|
if(strchr(service, '/')) {
|
||||||
service_name = malloc(strlen(service));
|
service_name = malloc(service_length);
|
||||||
if(!service_name)
|
if(!service_name)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
memcpy(service_name, service, strlen(service));
|
memcpy(service_name, service, service_length);
|
||||||
}
|
}
|
||||||
else {
|
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)
|
if(!service_name)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
|
snprintf(service_name, service_length +
|
||||||
"%s/%s", service, conn->proxy.name);
|
strlen(conn->socks_proxy.host.name)+2, "%s/%s",
|
||||||
|
service, conn->socks_proxy.host.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_desc.cBuffers = 1;
|
input_desc.cBuffers = 1;
|
||||||
|
@@ -859,7 +859,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
|
sshc->passphrase = data->set.ssl.key_passwd;
|
||||||
if(!sshc->passphrase)
|
if(!sshc->passphrase)
|
||||||
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
|
/* 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
|
after the *_setopt() calls (that could specify the size of the cache) but
|
||||||
before any transfer takes place. */
|
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)
|
if(result)
|
||||||
return 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);
|
void Curl_verboseconnect(struct connectdata *conn);
|
||||||
#endif
|
#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 */
|
#endif /* HEADER_CURL_URL_H */
|
||||||
|
@@ -331,6 +331,8 @@ struct ssl_connect_data {
|
|||||||
gsk_handle handle;
|
gsk_handle handle;
|
||||||
int iocport;
|
int iocport;
|
||||||
ssl_connect_state connecting_state;
|
ssl_connect_state connecting_state;
|
||||||
|
int localfd;
|
||||||
|
int remotefd;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_AXTLS
|
#ifdef USE_AXTLS
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_ctx;
|
||||||
@@ -359,27 +361,37 @@ struct ssl_connect_data {
|
|||||||
#endif /* USE_DARWINSSL */
|
#endif /* USE_DARWINSSL */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssl_config_data {
|
struct ssl_primary_config {
|
||||||
long version; /* what version the client wants to use */
|
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 verifypeer; /* set TRUE if this is desired */
|
||||||
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
|
bool verifyhost; /* set TRUE if CN/SAN must match hostname */
|
||||||
bool verifystatus; /* set TRUE if certificate status must be checked */
|
bool verifystatus; /* set TRUE if certificate status must be checked */
|
||||||
char *CApath; /* certificate dir (doesn't work on windows) */
|
char *CApath; /* certificate dir (doesn't work on windows) */
|
||||||
char *CAfile; /* certificate to verify peer against */
|
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 *random_file; /* path to file containing "random" data */
|
||||||
char *egdsocket; /* path to file containing the EGD daemon socket */
|
char *egdsocket; /* path to file containing the EGD daemon socket */
|
||||||
char *cipher_list; /* list of ciphers to use */
|
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 */
|
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
|
||||||
void *fsslctxp; /* parameter for call back */
|
void *fsslctxp; /* parameter for call back */
|
||||||
bool sessionid; /* cache session IDs or not */
|
|
||||||
bool certinfo; /* gather lots of certificate info */
|
bool certinfo; /* gather lots of certificate info */
|
||||||
bool falsestart;
|
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
|
#ifdef USE_TLS_SRP
|
||||||
char *username; /* TLS username (for, e.g., SRP) */
|
char *username; /* TLS username (for, e.g., SRP) */
|
||||||
char *password; /* TLS password (for, e.g., SRP) */
|
char *password; /* TLS password (for, e.g., SRP) */
|
||||||
@@ -387,6 +399,11 @@ struct ssl_config_data {
|
|||||||
#endif
|
#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 */
|
/* information stored about one single SSL session */
|
||||||
struct curl_ssl_session {
|
struct curl_ssl_session {
|
||||||
char *name; /* host name for which this ID was used */
|
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 */
|
size_t idsize; /* if known, otherwise 0 */
|
||||||
long age; /* just a number, the higher the more recent */
|
long age; /* just a number, the higher the more recent */
|
||||||
int remote_port; /* remote port to connect to */
|
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 */
|
/* Struct used for Digest challenge-response authentication */
|
||||||
@@ -507,6 +524,7 @@ struct ConnectBits {
|
|||||||
bool reuse; /* if set, this is a re-used connection */
|
bool reuse; /* if set, this is a re-used connection */
|
||||||
bool proxy; /* if set, this transfer is done through a proxy - any type */
|
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 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 user_passwd; /* do we use user+password for this connection? */
|
||||||
bool proxy_user_passwd; /* user+password for the proxy? */
|
bool proxy_user_passwd; /* user+password for the proxy? */
|
||||||
bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
|
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
|
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
|
EPRT doesn't work we disable it for the forthcoming
|
||||||
requests */
|
requests */
|
||||||
|
bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
|
||||||
bool netrc; /* name+password provided by netrc */
|
bool netrc; /* name+password provided by netrc */
|
||||||
bool userpwd_in_url; /* name+password found in url */
|
bool userpwd_in_url; /* name+password found in url */
|
||||||
bool stream_was_rewound; /* Indicates that the stream was rewound after a
|
bool stream_was_rewound; /* Indicates that the stream was rewound after a
|
||||||
@@ -553,6 +572,9 @@ struct ConnectBits {
|
|||||||
connection */
|
connection */
|
||||||
bool type_set; /* type= was used in the URL */
|
bool type_set; /* type= was used in the URL */
|
||||||
bool multiplex; /* connection is multiplexed */
|
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 {
|
struct hostname {
|
||||||
@@ -840,6 +862,14 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
|
|||||||
size_t len, /* max amount to read */
|
size_t len, /* max amount to read */
|
||||||
CURLcode *err); /* error to return */
|
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
|
* The connectdata struct contains all fields and variables that should be
|
||||||
* unique for an entire connection.
|
* unique for an entire connection.
|
||||||
@@ -889,10 +919,15 @@ struct connectdata {
|
|||||||
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
|
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
|
||||||
|
|
||||||
struct hostname host;
|
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 */
|
long port; /* which port to use locally */
|
||||||
int remote_port; /* what remote port to connect to, not the proxy port! */
|
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
|
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
|
||||||
ip address and port number whenever an outgoing connection is
|
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 *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 httpversion; /* the HTTP version*10 reported by the server */
|
||||||
int rtspversion; /* the RTSP 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];
|
Curl_send *send[2];
|
||||||
|
|
||||||
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
|
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 */
|
struct ConnectBits bits; /* various state-flags for this connection */
|
||||||
|
|
||||||
@@ -1061,9 +1094,6 @@ struct connectdata {
|
|||||||
int socks5_gssapi_enctype;
|
int socks5_gssapi_enctype;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool verifypeer;
|
|
||||||
bool verifyhost;
|
|
||||||
|
|
||||||
/* When this connection is created, store the conditions for the local end
|
/* 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
|
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
|
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 */
|
struct Curl_multi; /* declared and used only in multi.c */
|
||||||
|
|
||||||
enum dupstring {
|
enum dupstring {
|
||||||
STRING_CERT, /* client certificate file name */
|
|
||||||
STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
|
|
||||||
STRING_COOKIE, /* HTTP cookie string to send */
|
STRING_COOKIE, /* HTTP cookie string to send */
|
||||||
STRING_COOKIEJAR, /* dump all cookies to this file */
|
STRING_COOKIEJAR, /* dump all cookies to this file */
|
||||||
STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
|
STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */
|
||||||
@@ -1385,25 +1413,16 @@ enum dupstring {
|
|||||||
STRING_FTP_ACCOUNT, /* ftp account data */
|
STRING_FTP_ACCOUNT, /* ftp account data */
|
||||||
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
|
STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
|
||||||
STRING_FTPPORT, /* port to send with the FTP PORT command */
|
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_KRB_LEVEL, /* krb security level */
|
||||||
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
|
STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find
|
||||||
$HOME/.netrc */
|
$HOME/.netrc */
|
||||||
STRING_PROXY, /* proxy to use */
|
STRING_PROXY, /* proxy to use */
|
||||||
|
STRING_SOCKS_PROXY, /* socks proxy to use */
|
||||||
STRING_SET_RANGE, /* range, if used */
|
STRING_SET_RANGE, /* range, if used */
|
||||||
STRING_SET_REFERER, /* custom string for the HTTP referer field */
|
STRING_SET_REFERER, /* custom string for the HTTP referer field */
|
||||||
STRING_SET_URL, /* what original URL to work on */
|
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_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_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_USERNAME, /* <username>, if used */
|
||||||
STRING_PASSWORD, /* <password>, if used */
|
STRING_PASSWORD, /* <password>, if used */
|
||||||
STRING_OPTIONS, /* <options>, if used */
|
STRING_OPTIONS, /* <options>, if used */
|
||||||
@@ -1428,10 +1447,6 @@ enum dupstring {
|
|||||||
STRING_MAIL_FROM,
|
STRING_MAIL_FROM,
|
||||||
STRING_MAIL_AUTH,
|
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 */
|
STRING_BEARER, /* <bearer>, if used */
|
||||||
#ifdef USE_UNIX_SOCKETS
|
#ifdef USE_UNIX_SOCKETS
|
||||||
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
|
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
|
long httpversion; /* when non-zero, a specific HTTP version requested to
|
||||||
be used in the library's request(s) */
|
be used in the library's request(s) */
|
||||||
struct ssl_config_data ssl; /* user defined SSL stuff */
|
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 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 dns_cache_timeout; /* DNS cache timeout */
|
||||||
long buffer_size; /* size of receive buffer to use */
|
long buffer_size; /* size of receive buffer to use */
|
||||||
void *private_data; /* application-private data */
|
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
|
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
|
||||||
us */
|
us */
|
||||||
bool connect_only; /* make connection, let application use the socket */
|
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 */
|
long ssh_auth_types; /* allowed SSH auth types */
|
||||||
bool http_te_skip; /* pass the raw body data to the user, even when
|
bool http_te_skip; /* pass the raw body data to the user, even when
|
||||||
transfer-encoded (chunked, compressed) */
|
transfer-encoded (chunked, compressed) */
|
||||||
|
@@ -160,7 +160,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
|
|
||||||
/* axTLS only supports TLSv1 */
|
/* axTLS only supports TLSv1 */
|
||||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
/* 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_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
break;
|
break;
|
||||||
@@ -185,17 +185,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
conn->ssl[sockindex].ssl = NULL;
|
conn->ssl[sockindex].ssl = NULL;
|
||||||
|
|
||||||
/* Load the trusted CA cert bundle file */
|
/* Load the trusted CA cert bundle file */
|
||||||
if(data->set.ssl.CAfile) {
|
if(SSL_CONN_CONFIG(CAfile)) {
|
||||||
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
|
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
|
||||||
!= SSL_OK) {
|
SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
|
||||||
infof(data, "error reading ca cert file %s \n",
|
infof(data, "error reading ca cert file %s \n",
|
||||||
data->set.ssl.CAfile);
|
SSL_CONN_CONFIG(CAfile));
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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:
|
/* gtls.c tasks we're skipping for now:
|
||||||
@@ -207,15 +207,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Load client certificate */
|
/* Load client certificate */
|
||||||
if(data->set.str[STRING_CERT]) {
|
if(SSL_SET_OPTION(cert)) {
|
||||||
i=0;
|
i=0;
|
||||||
/* Instead of trying to analyze cert type here, let axTLS try them all. */
|
/* Instead of trying to analyze cert type here, let axTLS try them all. */
|
||||||
while(cert_types[i] != 0) {
|
while(cert_types[i] != 0) {
|
||||||
ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
|
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) {
|
if(ssl_fcn_return == SSL_OK) {
|
||||||
infof(data, "successfully read cert file %s \n",
|
infof(data, "successfully read cert file %s \n",
|
||||||
data->set.str[STRING_CERT]);
|
SSL_SET_OPTION(cert));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -223,7 +223,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
/* Tried all cert types, none worked. */
|
/* Tried all cert types, none worked. */
|
||||||
if(cert_types[i] == 0) {
|
if(cert_types[i] == 0) {
|
||||||
failf(data, "%s is not x509 or pkcs12 format",
|
failf(data, "%s is not x509 or pkcs12 format",
|
||||||
data->set.str[STRING_CERT]);
|
SSL_SET_OPTION(cert));
|
||||||
return CURLE_SSL_CERTPROBLEM;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,15 +231,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
/* Load client key.
|
/* Load client key.
|
||||||
If a pkcs12 file successfully loaded a cert, then there's nothing to do
|
If a pkcs12 file successfully loaded a cert, then there's nothing to do
|
||||||
because the key has already been loaded. */
|
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;
|
i=0;
|
||||||
/* Instead of trying to analyze key type here, let axTLS try them all. */
|
/* Instead of trying to analyze key type here, let axTLS try them all. */
|
||||||
while(key_types[i] != 0) {
|
while(key_types[i] != 0) {
|
||||||
ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
|
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) {
|
if(ssl_fcn_return == SSL_OK) {
|
||||||
infof(data, "successfully read key file %s \n",
|
infof(data, "successfully read key file %s \n",
|
||||||
data->set.str[STRING_KEY]);
|
SSL_SET_OPTION(key));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -247,7 +247,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
|||||||
/* Tried all key types, none worked. */
|
/* Tried all key types, none worked. */
|
||||||
if(key_types[i] == 0) {
|
if(key_types[i] == 0) {
|
||||||
failf(data, "Failure: %s is not a supported key file",
|
failf(data, "Failure: %s is not a supported key file",
|
||||||
data->set.str[STRING_KEY]);
|
SSL_SET_OPTION(key));
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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. */
|
/* 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! */
|
/* we got a session id, use it! */
|
||||||
infof (data, "SSL re-using session ID\n");
|
infof (data, "SSL re-using session ID\n");
|
||||||
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
|
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;
|
const char *dns_altname;
|
||||||
int8_t found_subject_alt_names = 0;
|
int8_t found_subject_alt_names = 0;
|
||||||
int8_t found_subject_alt_name_matching_conn = 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
|
/* 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?
|
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Verify server's certificate */
|
/* Verify server's certificate */
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
if(ssl_verify_cert(ssl) != SSL_OK) {
|
if(ssl_verify_cert(ssl) != SSL_OK) {
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "server cert verify failed");
|
failf(data, "server cert verify failed");
|
||||||
@@ -324,8 +329,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
|||||||
found_subject_alt_names = 1;
|
found_subject_alt_names = 1;
|
||||||
|
|
||||||
infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
|
infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
|
||||||
dns_altname, conn->host.name);
|
dns_altname, hostname);
|
||||||
if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
|
if(Curl_cert_hostcheck(dns_altname, hostname)) {
|
||||||
found_subject_alt_name_matching_conn = 1;
|
found_subject_alt_name_matching_conn = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -333,23 +338,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
|||||||
|
|
||||||
/* RFC2818 checks */
|
/* RFC2818 checks */
|
||||||
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
|
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
/* Break connection ! */
|
/* Break connection ! */
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "\tsubjectAltName(s) do not match %s\n",
|
failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
|
||||||
conn->host.dispname);
|
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "\tsubjectAltName(s) do not match %s\n",
|
infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
|
||||||
conn->host.dispname);
|
|
||||||
}
|
}
|
||||||
else if(found_subject_alt_names == 0) {
|
else if(found_subject_alt_names == 0) {
|
||||||
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
|
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
|
||||||
CN as a legacy fallback */
|
CN as a legacy fallback */
|
||||||
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
|
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
|
||||||
if(peer_CN == NULL) {
|
if(peer_CN == NULL) {
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "unable to obtain common name from peer certificate");
|
failf(data, "unable to obtain common name from peer certificate");
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
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");
|
infof(data, "unable to obtain common name from peer certificate");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
/* Break connection ! */
|
/* Break connection ! */
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
||||||
peer_CN, conn->host.dispname);
|
peer_CN, dispname);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
|
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 */
|
/* Put our freshly minted SSL session in cache */
|
||||||
ssl_idsize = ssl_get_session_id_size(ssl);
|
ssl_idsize = ssl_get_session_id_size(ssl);
|
||||||
ssl_sessionid = ssl_get_session_id(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)
|
!= CURLE_OK)
|
||||||
infof (data, "failed to add session to cache\n");
|
infof (data, "failed to add session to cache\n");
|
||||||
|
|
||||||
|
@@ -117,7 +117,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
/* 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_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
|
#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
|
||||||
@@ -168,7 +168,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(data->set.ssl.version) {
|
switch(SSL_CONN_CONFIG(version)) {
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
|
#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
|
||||||
@@ -191,18 +191,18 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
|
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
/* load trusted cacert */
|
/* load trusted cacert */
|
||||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
if(SSL_CONN_CONFIG(CAfile)) {
|
||||||
if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
|
if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
|
||||||
data->set.str[STRING_SSL_CAFILE],
|
SSL_CONN_CONFIG(CAfile),
|
||||||
data->set.str[STRING_SSL_CAPATH])) {
|
SSL_CONN_CONFIG(CApath))) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
/* Fail if we insist on successfully verifying the server. */
|
/* Fail if we insist on successfully verifying the server. */
|
||||||
failf(data, "error setting certificate verify locations:\n"
|
failf(data, "error setting certificate verify locations:\n"
|
||||||
" CAfile: %s\n CApath: %s",
|
" CAfile: %s\n CApath: %s",
|
||||||
data->set.str[STRING_SSL_CAFILE]?
|
SSL_CONN_CONFIG(CAfile)?
|
||||||
data->set.str[STRING_SSL_CAFILE]: "none",
|
SSL_CONN_CONFIG(CAfile): "none",
|
||||||
data->set.str[STRING_SSL_CAPATH]?
|
SSL_CONN_CONFIG(CApath)?
|
||||||
data->set.str[STRING_SSL_CAPATH] : "none");
|
SSL_CONN_CONFIG(CApath) : "none");
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -219,25 +219,25 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
infof(data,
|
infof(data,
|
||||||
" CAfile: %s\n"
|
" CAfile: %s\n"
|
||||||
" CApath: %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",
|
"none",
|
||||||
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
|
SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
|
||||||
"none");
|
"none");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the client certificate, and private key */
|
/* Load the client certificate, and private key */
|
||||||
if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
|
if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
|
||||||
int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
|
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) {
|
file_type) != 1) {
|
||||||
failf(data, "unable to use client certificate (no key or wrong pass"
|
failf(data, "unable to use client certificate (no key or wrong pass"
|
||||||
" phrase?)");
|
" phrase?)");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
|
file_type = do_file_type(SSL_SET_OPTION(key_type));
|
||||||
if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
|
if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
|
||||||
file_type) != 1) {
|
file_type) != 1) {
|
||||||
failf(data, "unable to set private key");
|
failf(data, "unable to set private key");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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
|
* anyway. In the latter case the result of the verification is checked with
|
||||||
* SSL_get_verify_result() below. */
|
* SSL_get_verify_result() below. */
|
||||||
SSL_CTX_set_verify(conssl->ctx,
|
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);
|
NULL);
|
||||||
|
|
||||||
#ifdef HAVE_SNI
|
#ifdef HAVE_SNI
|
||||||
@@ -259,13 +260,15 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
#endif
|
#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) &&
|
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
|
#ifdef ENABLE_IPV6
|
||||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
|
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
|
||||||
#endif
|
#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)) {
|
(unsigned short)hostname_len) != 1)) {
|
||||||
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||||
"TLS extension\n");
|
"TLS extension\n");
|
||||||
@@ -284,7 +287,7 @@ cyassl_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef NO_FILESYSTEM
|
#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"
|
failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
|
||||||
" with \"no filesystem\". Either disable peer verification"
|
" with \"no filesystem\". Either disable peer verification"
|
||||||
" (insecure) or if you are building an application with libcurl you"
|
" (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! */
|
/* 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! */
|
/* we got a session id, use it! */
|
||||||
if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
|
if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
|
||||||
failf(data, "SSL: SSL_set_session failed: %s",
|
failf(data, "SSL: SSL_set_session failed: %s",
|
||||||
@@ -332,13 +335,17 @@ cyassl_connect_step2(struct connectdata *conn,
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
|
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->recv[sockindex] = cyassl_recv;
|
||||||
conn->send[sockindex] = cyassl_send;
|
conn->send[sockindex] = cyassl_send;
|
||||||
|
|
||||||
/* Enable RFC2818 checks */
|
/* Enable RFC2818 checks */
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
|
ret = CyaSSL_check_domain_name(conssl->handle, hostname);
|
||||||
if(ret == SSL_FAILURE)
|
if(ret == SSL_FAILURE)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@@ -362,31 +369,31 @@ cyassl_connect_step2(struct connectdata *conn,
|
|||||||
else if(DOMAIN_NAME_MISMATCH == detail) {
|
else if(DOMAIN_NAME_MISMATCH == detail) {
|
||||||
#if 1
|
#if 1
|
||||||
failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
|
failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
|
||||||
conn->host.dispname);
|
dispname);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
#else
|
#else
|
||||||
/* When the CyaSSL_check_domain_name() is used and you desire to continue
|
/* 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
|
* 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()
|
* way to do this is currently to switch the CyaSSL_check_domain_name()
|
||||||
* in and out based on the 'data->set.ssl.verifyhost' value. */
|
* in and out based on the 'conn->ssl_config.verifyhost' value. */
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"\tsubject alt name(s) or common name do not match \"%s\"\n",
|
"\tsubject alt name(s) or common name do not match \"%s\"\n",
|
||||||
conn->host.dispname);
|
dispname);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
infof(data,
|
infof(data,
|
||||||
"\tsubject alt name(s) and/or common name do not match \"%s\"\n",
|
"\tsubject alt name(s) and/or common name do not match \"%s\"\n",
|
||||||
conn->host.dispname);
|
dispname);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
|
#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
|
||||||
else if(ASN_NO_SIGNER_E == detail) {
|
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");
|
failf(data, "\tCA signer not available for verification\n");
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
@@ -466,7 +473,8 @@ cyassl_connect_step3(struct connectdata *conn,
|
|||||||
|
|
||||||
our_ssl_sessionid = SSL_get_session(connssl->handle);
|
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(incache) {
|
||||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||||
infof(data, "old SSL session ID is stale, removing\n");
|
infof(data, "old SSL session ID is stale, removing\n");
|
||||||
@@ -477,7 +485,7 @@ cyassl_connect_step3(struct connectdata *conn,
|
|||||||
|
|
||||||
if(!incache) {
|
if(!incache) {
|
||||||
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
||||||
0 /* unknown size */);
|
0 /* unknown size */, sockindex);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data, "failed to store ssl session");
|
failf(data, "failed to store ssl session");
|
||||||
return result;
|
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 */
|
/* 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 CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
|
||||||
if(SSLSetProtocolVersionMax != NULL) {
|
if(SSLSetProtocolVersionMax != NULL) {
|
||||||
switch(data->set.ssl.version) {
|
switch(conn->ssl_config.version) {
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
@@ -1096,7 +1096,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||||
kSSLProtocolAll,
|
kSSLProtocolAll,
|
||||||
false);
|
false);
|
||||||
switch (data->set.ssl.version) {
|
switch (conn->ssl_config.version) {
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
@@ -1148,7 +1148,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
|
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
|
||||||
switch(data->set.ssl.version) {
|
switch(conn->ssl_config.version) {
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
@@ -1293,7 +1293,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
#else
|
#else
|
||||||
if(SSLSetSessionOption != NULL) {
|
if(SSLSetSessionOption != NULL) {
|
||||||
#endif /* CURL_BUILD_MAC */
|
#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];
|
data->set.str[STRING_SSL_CAFILE];
|
||||||
err = SSLSetSessionOption(connssl->ssl_ctx,
|
err = SSLSetSessionOption(connssl->ssl_ctx,
|
||||||
kSSLSessionOptionBreakOnServerAuth,
|
kSSLSessionOptionBreakOnServerAuth,
|
||||||
@@ -1306,7 +1306,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
else {
|
else {
|
||||||
#if CURL_SUPPORT_MAC_10_8
|
#if CURL_SUPPORT_MAC_10_8
|
||||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||||
data->set.ssl.verifypeer?true:false);
|
conn->ssl_config.verifypeer?true:false);
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
@@ -1315,7 +1315,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
err = SSLSetEnableCertVerify(connssl->ssl_ctx,
|
||||||
data->set.ssl.verifypeer?true:false);
|
conn->ssl_config.verifypeer?true:false);
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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.
|
/* Configure hostname check. SNI is used if available.
|
||||||
* Both hostname check and SNI require SSLSetPeerDomainName().
|
* Both hostname check and SNI require SSLSetPeerDomainName().
|
||||||
* Also: the verifyhost setting influences SNI usage */
|
* 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,
|
err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
|
||||||
strlen(conn->host.name));
|
strlen(conn->host.name));
|
||||||
|
|
||||||
|
319
lib/vtls/gskit.c
319
lib/vtls/gskit.c
@@ -81,6 +81,10 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Directions. */
|
||||||
|
#define SOS_READ 0x01
|
||||||
|
#define SOS_WRITE 0x02
|
||||||
|
|
||||||
/* SSL version flags. */
|
/* SSL version flags. */
|
||||||
#define CURL_GSKPROTO_SSLV2 0
|
#define CURL_GSKPROTO_SSLV2 0
|
||||||
#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
|
#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)
|
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 char *clp;
|
||||||
const gskit_cipher *ctp;
|
const gskit_cipher *ctp;
|
||||||
int i;
|
int i;
|
||||||
@@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
|
|||||||
connssl->iocport = -1;
|
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,
|
static int
|
||||||
struct SessionHandle *data)
|
inetsocketpair(int sv[2])
|
||||||
{
|
{
|
||||||
if(conn->handle) {
|
int lfd; /* Listening socket. */
|
||||||
gskit_status(data, gsk_secure_soc_close(&conn->handle),
|
int sfd; /* Server socket. */
|
||||||
"gsk_secure_soc_close()", 0);
|
int cfd; /* Client socket. */
|
||||||
conn->handle = (gsk_handle) NULL;
|
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)
|
const void *mem, size_t len, CURLcode *curlcode)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
CURLcode cc;
|
CURLcode cc = CURLE_SEND_ERROR;
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
cc = gskit_status(data,
|
if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
|
||||||
gsk_secure_soc_write(conn->ssl[sockindex].handle,
|
cc = gskit_status(data,
|
||||||
(char *) mem, (int) len, &written),
|
gsk_secure_soc_write(conn->ssl[sockindex].handle,
|
||||||
"gsk_secure_soc_write()", CURLE_SEND_ERROR);
|
(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) {
|
if(cc != CURLE_OK) {
|
||||||
*curlcode = cc;
|
*curlcode = cc;
|
||||||
written = -1;
|
written = -1;
|
||||||
@@ -539,15 +727,23 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
|
|||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
int buffsize;
|
int buffsize;
|
||||||
int nread;
|
int nread;
|
||||||
CURLcode cc;
|
CURLcode cc = CURLE_RECV_ERROR;
|
||||||
|
|
||||||
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
|
if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
|
||||||
cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
|
buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
|
||||||
buf, buffsize, &nread),
|
cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
|
||||||
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
|
buf, buffsize, &nread),
|
||||||
if(cc != CURLE_OK) {
|
"gsk_secure_soc_read()", CURLE_RECV_ERROR);
|
||||||
|
}
|
||||||
|
switch(cc) {
|
||||||
|
case CURLE_OK:
|
||||||
|
break;
|
||||||
|
case CURLE_OPERATION_TIMEDOUT:
|
||||||
|
cc = CURLE_AGAIN;
|
||||||
|
default:
|
||||||
*curlcode = cc;
|
*curlcode = cc;
|
||||||
nread = -1;
|
nread = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (ssize_t) nread;
|
return (ssize_t) nread;
|
||||||
}
|
}
|
||||||
@@ -560,18 +756,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
gsk_handle envir;
|
gsk_handle envir;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
int rc;
|
int rc;
|
||||||
char *keyringfile;
|
const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
|
||||||
char *keyringpwd;
|
const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
|
||||||
char *keyringlabel;
|
const char * const keyringlabel = SSL_SET_OPTION(cert);
|
||||||
char *sni;
|
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;
|
unsigned int protoflags;
|
||||||
long timeout;
|
long timeout;
|
||||||
Qso_OverlappedIO_t commarea;
|
Qso_OverlappedIO_t commarea;
|
||||||
|
int sockpair[2];
|
||||||
|
static const int sobufsize = CURL_MAX_WRITE_SIZE;
|
||||||
|
|
||||||
/* Create SSL environment, start (preferably asynchronous) handshake. */
|
/* Create SSL environment, start (preferably asynchronous) handshake. */
|
||||||
|
|
||||||
connssl->handle = (gsk_handle) NULL;
|
connssl->handle = (gsk_handle) NULL;
|
||||||
connssl->iocport = -1;
|
connssl->iocport = -1;
|
||||||
|
connssl->localfd = -1;
|
||||||
|
connssl->remotefd = -1;
|
||||||
|
|
||||||
/* GSKit supports two ways of specifying an SSL context: either by
|
/* GSKit supports two ways of specifying an SSL context: either by
|
||||||
* application identifier (that should have been defined at the system
|
* 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.
|
* 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;
|
envir = (gsk_handle) NULL;
|
||||||
|
|
||||||
if(keyringlabel && *keyringlabel && !keyringpwd &&
|
if(keyringlabel && *keyringlabel && !keyringpwd &&
|
||||||
@@ -613,18 +814,36 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
if(result)
|
if(result)
|
||||||
return 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. */
|
/* Determine which SSL/TLS version should be enabled. */
|
||||||
protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
|
protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
|
||||||
CURL_GSKPROTO_TLSV12_MASK;
|
CURL_GSKPROTO_TLSV12_MASK;
|
||||||
sni = conn->host.name;
|
sni = hostname;
|
||||||
switch (data->set.ssl.version) {
|
switch (ssl_version) {
|
||||||
case CURL_SSLVERSION_SSLv2:
|
case CURL_SSLVERSION_SSLv2:
|
||||||
protoflags = CURL_GSKPROTO_SSLV2_MASK;
|
protoflags = CURL_GSKPROTO_SSLV2_MASK;
|
||||||
sni = (char *) NULL;
|
sni = NULL;
|
||||||
break;
|
break;
|
||||||
case CURL_SSLVERSION_SSLv3:
|
case CURL_SSLVERSION_SSLv3:
|
||||||
protoflags = CURL_GSKPROTO_SSLV3_MASK;
|
protoflags = CURL_GSKPROTO_SSLV3_MASK;
|
||||||
sni = (char *) NULL;
|
sni = NULL;
|
||||||
break;
|
break;
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
protoflags = CURL_GSKPROTO_TLSV10_MASK |
|
protoflags = CURL_GSKPROTO_TLSV10_MASK |
|
||||||
@@ -661,9 +880,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
(timeout + 999) / 1000);
|
(timeout + 999) / 1000);
|
||||||
}
|
}
|
||||||
if(!result)
|
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)
|
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) {
|
if(!protoflags) {
|
||||||
failf(data, "No SSL protocol/cipher combination enabled");
|
failf(data, "No SSL protocol/cipher combination enabled");
|
||||||
result = CURLE_SSL_CIPHER;
|
result = CURLE_SSL_CIPHER;
|
||||||
@@ -706,7 +928,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
if(!result)
|
if(!result)
|
||||||
result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
|
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);
|
GSK_SERVER_AUTH_PASSTHRU, FALSE);
|
||||||
|
|
||||||
if(!result) {
|
if(!result) {
|
||||||
@@ -730,6 +952,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
else if(errno != ENOBUFS)
|
else if(errno != ENOBUFS)
|
||||||
result = gskit_status(data, GSK_ERROR_IO,
|
result = gskit_status(data, GSK_ERROR_IO,
|
||||||
"QsoCreateIOCompletionPort()", 0);
|
"QsoCreateIOCompletionPort()", 0);
|
||||||
|
else if(conn->proxy_ssl[sockindex].use) {
|
||||||
|
/* Cannot pipeline while handshaking synchronously. */
|
||||||
|
result = CURLE_SSL_CONNECT_ERROR;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* No more completion port available. Use synchronous IO. */
|
/* No more completion port available. Use synchronous IO. */
|
||||||
result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
|
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. */
|
/* Error: rollback. */
|
||||||
close_one(connssl, data);
|
close_one(connssl, conn, sockindex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,6 +1139,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
|
|||||||
result = gskit_connect_step1(conn, 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. */
|
/* Step 2: check if handshake is over. */
|
||||||
if(!result && connssl->connecting_state == ssl_connect_2) {
|
if(!result && connssl->connecting_state == ssl_connect_2) {
|
||||||
/* check allowed time left */
|
/* 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);
|
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. */
|
/* Step 3: gather certificate info, verify host. */
|
||||||
if(!result && connssl->connecting_state == ssl_connect_3)
|
if(!result && connssl->connecting_state == ssl_connect_3)
|
||||||
result = gskit_connect_step3(conn, sockindex);
|
result = gskit_connect_step3(conn, sockindex);
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
close_one(connssl, data);
|
close_one(connssl, conn, sockindex);
|
||||||
else if(connssl->connecting_state == ssl_connect_done) {
|
else if(connssl->connecting_state == ssl_connect_done) {
|
||||||
connssl->state = ssl_connection_complete;
|
connssl->state = ssl_connection_complete;
|
||||||
connssl->connecting_state = ssl_connect_1;
|
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)
|
void Curl_gskit_close(struct connectdata *conn, int sockindex)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
close_one(&conn->ssl[sockindex], conn, sockindex);
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
|
||||||
|
|
||||||
if(connssl->use)
|
|
||||||
close_one(connssl, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -999,7 +1232,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
|
if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
close_one(connssl, data);
|
close_one(connssl, conn, sockindex);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
what = Curl_socket_ready(conn->sock[sockindex],
|
what = Curl_socket_ready(conn->sock[sockindex],
|
||||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
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;
|
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()
|
/* Curl_gtls_init()
|
||||||
*
|
*
|
||||||
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
|
* 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;
|
void *ssl_sessionid;
|
||||||
size_t ssl_idsize;
|
size_t ssl_idsize;
|
||||||
bool sni = TRUE; /* default is SNI enabled */
|
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
|
#ifdef ENABLE_IPV6
|
||||||
struct in6_addr addr;
|
struct in6_addr addr;
|
||||||
#else
|
#else
|
||||||
@@ -403,6 +416,9 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
const char *err = NULL;
|
const char *err = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
|
||||||
|
conn->host.name;
|
||||||
|
|
||||||
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
||||||
/* to make us tolerant against being called more than once for the
|
/* to make us tolerant against being called more than once for the
|
||||||
same connection */
|
same connection */
|
||||||
@@ -412,11 +428,11 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
Curl_gtls_init();
|
Curl_gtls_init();
|
||||||
|
|
||||||
/* GnuTLS only supports SSLv3 and TLSv1 */
|
/* 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");
|
failf(data, "GnuTLS does not support SSLv2");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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 */
|
sni = FALSE; /* SSLv3 has no SNI */
|
||||||
|
|
||||||
/* allocate a cred struct */
|
/* allocate a cred struct */
|
||||||
@@ -427,8 +443,8 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
|
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
|
||||||
infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
|
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
|
||||||
|
|
||||||
rc = gnutls_srp_allocate_client_credentials(
|
rc = gnutls_srp_allocate_client_credentials(
|
||||||
&conn->ssl[sockindex].srp_client_cred);
|
&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].
|
rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
|
||||||
srp_client_cred,
|
srp_client_cred,
|
||||||
data->set.ssl.username,
|
SSL_SET_OPTION(username),
|
||||||
data->set.ssl.password);
|
SSL_SET_OPTION(password));
|
||||||
if(rc != GNUTLS_E_SUCCESS) {
|
if(rc != GNUTLS_E_SUCCESS) {
|
||||||
failf(data, "gnutls_srp_set_client_cred() failed: %s",
|
failf(data, "gnutls_srp_set_client_cred() failed: %s",
|
||||||
gnutls_strerror(rc));
|
gnutls_strerror(rc));
|
||||||
@@ -450,56 +466,56 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.ssl.CAfile) {
|
if(SSL_CONN_CONFIG(CAfile)) {
|
||||||
/* set the trusted CA cert bundle file */
|
/* set the trusted CA cert bundle file */
|
||||||
gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
|
gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
|
||||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
||||||
|
|
||||||
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
|
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
|
||||||
data->set.ssl.CAfile,
|
SSL_CONN_CONFIG(CAfile),
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
infof(data, "error reading ca cert file %s (%s)\n",
|
infof(data, "error reading ca cert file %s (%s)\n",
|
||||||
data->set.ssl.CAfile, gnutls_strerror(rc));
|
SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
|
||||||
if(data->set.ssl.verifypeer)
|
if(SSL_CONN_CONFIG(verifypeer))
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "found %d certificates in %s\n",
|
infof(data, "found %d certificates in %s\n", rc,
|
||||||
rc, data->set.ssl.CAfile);
|
SSL_CONN_CONFIG(CAfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_CAPATH
|
#ifdef HAS_CAPATH
|
||||||
if(data->set.ssl.CApath) {
|
if(SSL_CONN_CONFIG(CApath)) {
|
||||||
/* set the trusted CA cert directory */
|
/* set the trusted CA cert directory */
|
||||||
rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
|
rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
|
||||||
data->set.ssl.CApath,
|
SSL_CONN_CONFIG(CApath),
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
infof(data, "error reading ca cert file %s (%s)\n",
|
infof(data, "error reading ca cert file %s (%s)\n",
|
||||||
data->set.ssl.CAfile, gnutls_strerror(rc));
|
SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
|
||||||
if(data->set.ssl.verifypeer)
|
if(SSL_CONN_CONFIG(verifypeer))
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "found %d certificates in %s\n",
|
infof(data, "found %d certificates in %s\n",
|
||||||
rc, data->set.ssl.CApath);
|
rc, SSL_CONN_CONFIG(CApath));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.ssl.CRLfile) {
|
if(SSL_SET_OPTION(CRLfile)) {
|
||||||
/* set the CRL list file */
|
/* set the CRL list file */
|
||||||
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
|
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
|
||||||
data->set.ssl.CRLfile,
|
SSL_SET_OPTION(CRLfile),
|
||||||
GNUTLS_X509_FMT_PEM);
|
GNUTLS_X509_FMT_PEM);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
failf(data, "error reading crl file %s (%s)",
|
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;
|
return CURLE_SSL_CRL_BADFILE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "found %d CRL in %s\n",
|
infof(data, "found %d CRL in %s\n",
|
||||||
rc, data->set.ssl.CRLfile);
|
rc, SSL_SET_OPTION(CRLfile));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize TLS session as a client */
|
/* Initialize TLS session as a client */
|
||||||
@@ -512,13 +528,13 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
/* convenient assign */
|
/* convenient assign */
|
||||||
session = conn->ssl[sockindex].session;
|
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
|
#ifdef ENABLE_IPV6
|
||||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
|
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
|
||||||
#endif
|
#endif
|
||||||
sni &&
|
sni &&
|
||||||
(gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
|
(gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
|
||||||
strlen(conn->host.name)) < 0))
|
strlen(hostname)) < 0))
|
||||||
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||||
"TLS extension\n");
|
"TLS extension\n");
|
||||||
|
|
||||||
@@ -539,13 +555,13 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
if(rc != GNUTLS_E_SUCCESS)
|
if(rc != GNUTLS_E_SUCCESS)
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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"
|
failf(data, "can't pass a custom cipher list to older GnuTLS"
|
||||||
" versions");
|
" versions");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data->set.ssl.version) {
|
switch (SSL_CONN_CONFIG(version) {
|
||||||
case CURL_SSLVERSION_SSLv3:
|
case CURL_SSLVERSION_SSLv3:
|
||||||
protocol_priority[0] = GNUTLS_SSL3;
|
protocol_priority[0] = GNUTLS_SSL3;
|
||||||
break;
|
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
|
/* 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
|
* removed if a run-time error indicates that SRP is not supported by this
|
||||||
* GnuTLS version */
|
* GnuTLS version */
|
||||||
switch (data->set.ssl.version) {
|
switch (SSL_CONN_CONFIG(version)) {
|
||||||
case CURL_SSLVERSION_SSLv3:
|
case CURL_SSLVERSION_SSLv3:
|
||||||
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
|
prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
|
||||||
sni = false;
|
sni = false;
|
||||||
@@ -655,8 +671,8 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.str[STRING_CERT]) {
|
if(SSL_SET_OPTION(cert)) {
|
||||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
if(SSL_SET_OPTION(key_passwd)) {
|
||||||
#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
|
#if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
|
||||||
const unsigned int supported_key_encryption_algorithms =
|
const unsigned int supported_key_encryption_algorithms =
|
||||||
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
|
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;
|
GNUTLS_PKCS_USE_PBES2_AES_256;
|
||||||
rc = gnutls_certificate_set_x509_key_file2(
|
rc = gnutls_certificate_set_x509_key_file2(
|
||||||
conn->ssl[sockindex].cred,
|
conn->ssl[sockindex].cred,
|
||||||
data->set.str[STRING_CERT],
|
SSL_SET_OPTION(cert),
|
||||||
data->set.str[STRING_KEY] ?
|
SSL_SET_OPTION(key) ?
|
||||||
data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
|
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
|
||||||
do_file_type(data->set.str[STRING_CERT_TYPE]),
|
do_file_type(SSL_SET_OPTION(cert_type)),
|
||||||
data->set.str[STRING_KEY_PASSWD],
|
SSL_SET_OPTION(key_passwd),
|
||||||
supported_key_encryption_algorithms);
|
supported_key_encryption_algorithms);
|
||||||
if(rc != GNUTLS_E_SUCCESS) {
|
if(rc != GNUTLS_E_SUCCESS) {
|
||||||
failf(data,
|
failf(data,
|
||||||
@@ -683,15 +699,14 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rc = gnutls_certificate_set_x509_key_file(
|
if(gnutls_certificate_set_x509_key_file(
|
||||||
conn->ssl[sockindex].cred,
|
conn->ssl[sockindex].cred,
|
||||||
data->set.str[STRING_CERT],
|
SSL_SET_OPTION(cert),
|
||||||
data->set.str[STRING_KEY] ?
|
SSL_SET_OPTION(key) ?
|
||||||
data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
|
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
|
||||||
do_file_type(data->set.str[STRING_CERT_TYPE]) );
|
do_file_type(SSL_SET_OPTION(cert_type)) ) !=
|
||||||
if(rc != GNUTLS_E_SUCCESS) {
|
GNUTLS_E_SUCCESS) {
|
||||||
failf(data, "error reading X.509 key or certificate file: %s",
|
failf(data, "error reading X.509 key or certificate file");
|
||||||
gnutls_strerror(rc));
|
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -699,7 +714,7 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
|
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
/* put the credentials to the current session */
|
/* 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,
|
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
|
||||||
conn->ssl[sockindex].srp_client_cred);
|
conn->ssl[sockindex].srp_client_cred);
|
||||||
if(rc != GNUTLS_E_SUCCESS) {
|
if(rc != GNUTLS_E_SUCCESS) {
|
||||||
@@ -718,19 +733,30 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the connection handle (file descriptor for the socket) */
|
if(conn->proxy_ssl[sockindex].use) {
|
||||||
gnutls_transport_set_ptr(session,
|
transport_ptr = conn->proxy_ssl[sockindex].session;
|
||||||
GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
|
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. */
|
/* register callback functions to send and receive data. */
|
||||||
gnutls_transport_set_push_function(session, Curl_gtls_push);
|
gnutls_transport_set_push_function(session, gnutls_transport_push);
|
||||||
gnutls_transport_set_pull_function(session, Curl_gtls_pull);
|
gnutls_transport_set_pull_function(session, gnutls_transport_pull);
|
||||||
|
|
||||||
/* lowat must be set to zero when using custom push and pull functions. */
|
/* lowat must be set to zero when using custom push and pull functions. */
|
||||||
gnutls_transport_set_lowat(session, 0);
|
gnutls_transport_set_lowat(session, 0);
|
||||||
|
|
||||||
#ifdef HAS_OCSP
|
#ifdef HAS_OCSP
|
||||||
if(data->set.ssl.verifystatus) {
|
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||||
rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
|
rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
|
||||||
if(rc != GNUTLS_E_SUCCESS) {
|
if(rc != GNUTLS_E_SUCCESS) {
|
||||||
failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
|
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
|
/* This might be a reconnect, so we check for a session ID in the cache
|
||||||
to speed up things */
|
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! */
|
/* we got a session id, use it! */
|
||||||
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
|
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
|
||||||
|
|
||||||
@@ -837,8 +863,9 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
gnutls_datum_t proto;
|
gnutls_datum_t proto;
|
||||||
#endif
|
#endif
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
gnutls_protocol_t version = gnutls_protocol_get_version(session);
|
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. */
|
/* 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),
|
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);
|
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
|
||||||
if(!chainp) {
|
if(!chainp) {
|
||||||
if(data->set.ssl.verifypeer ||
|
if(SSL_CONN_CONFIG(verifypeer) ||
|
||||||
data->set.ssl.verifyhost ||
|
SSL_CONN_CONFIG(verifyhost) ||
|
||||||
data->set.ssl.issuercert) {
|
data->set.ssl.issuercert) {
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
|
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
|
||||||
&& data->set.ssl.username != NULL
|
&& SSL_SET_OPTION(username) != NULL
|
||||||
&& !data->set.ssl.verifypeer
|
&& !SSL_CONN_CONFIG(verifypeer)
|
||||||
&& gnutls_cipher_get(session)) {
|
&& gnutls_cipher_get(session)) {
|
||||||
/* no peer cert, but auth is ok if we have SRP user and cipher and no
|
/* no peer cert, but auth is ok if we have SRP user and cipher and no
|
||||||
peer verify */
|
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
|
/* 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
|
status (trusted, invalid etc.). The value of status should be one or
|
||||||
more of the gnutls_certificate_status_t enumerated elements bitwise
|
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 */
|
/* verify_status is a bitmask of gnutls_certificate_status bits */
|
||||||
if(verify_status & GNUTLS_CERT_INVALID) {
|
if(verify_status & GNUTLS_CERT_INVALID) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
failf(data, "server certificate verification failed. CAfile: %s "
|
failf(data, "server certificate verification failed. CAfile: %s "
|
||||||
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
|
"CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
|
||||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
"none",
|
||||||
|
SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
|
||||||
return CURLE_SSL_CACERT;
|
return CURLE_SSL_CACERT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -927,7 +955,7 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
infof(data, "\t server certificate verification SKIPPED\n");
|
infof(data, "\t server certificate verification SKIPPED\n");
|
||||||
|
|
||||||
#ifdef HAS_OCSP
|
#ifdef HAS_OCSP
|
||||||
if(data->set.ssl.verifystatus) {
|
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||||
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
|
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
|
||||||
gnutls_datum_t status_request;
|
gnutls_datum_t status_request;
|
||||||
gnutls_ocsp_resp_t ocsp_resp;
|
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
|
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
|
||||||
alternative name PKIX extension. Returns non zero on success, and zero on
|
alternative name PKIX extension. Returns non zero on success, and zero on
|
||||||
failure. */
|
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
|
#if GNUTLS_VERSION_NUMBER < 0x030306
|
||||||
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
|
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
|
||||||
addresses. */
|
addresses. */
|
||||||
@@ -1088,10 +1116,10 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
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;
|
addrlen = 4;
|
||||||
#ifdef ENABLE_IPV6
|
#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;
|
addrlen = 16;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1116,15 +1144,18 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(!rc) {
|
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 "
|
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);
|
gnutls_x509_crt_deinit(x509_cert);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "\t common name: %s (does not match '%s')\n",
|
infof(data, "\t common name: %s (does not match '%s')\n",
|
||||||
certbuf, conn->host.dispname);
|
certbuf, dispname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
infof(data, "\t common name: %s (matched)\n", certbuf);
|
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);
|
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
|
||||||
|
|
||||||
if(certclock == (time_t)-1) {
|
if(certclock == (time_t)-1) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
failf(data, "server cert expiration date verify failed");
|
failf(data, "server cert expiration date verify failed");
|
||||||
gnutls_x509_crt_deinit(x509_cert);
|
gnutls_x509_crt_deinit(x509_cert);
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
@@ -1143,7 +1174,7 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(certclock < time(NULL)) {
|
if(certclock < time(NULL)) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
failf(data, "server certificate expiration date has passed.");
|
failf(data, "server certificate expiration date has passed.");
|
||||||
gnutls_x509_crt_deinit(x509_cert);
|
gnutls_x509_crt_deinit(x509_cert);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
@@ -1158,7 +1189,7 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
|
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
|
||||||
|
|
||||||
if(certclock == (time_t)-1) {
|
if(certclock == (time_t)-1) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
failf(data, "server cert activation date verify failed");
|
failf(data, "server cert activation date verify failed");
|
||||||
gnutls_x509_crt_deinit(x509_cert);
|
gnutls_x509_crt_deinit(x509_cert);
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
@@ -1168,7 +1199,7 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(certclock > time(NULL)) {
|
if(certclock > time(NULL)) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
failf(data, "server certificate not activated yet.");
|
failf(data, "server certificate not activated yet.");
|
||||||
gnutls_x509_crt_deinit(x509_cert);
|
gnutls_x509_crt_deinit(x509_cert);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
@@ -1276,7 +1307,8 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
/* extract session ID to the allocated buffer */
|
/* extract session ID to the allocated buffer */
|
||||||
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
|
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) {
|
if(incache) {
|
||||||
/* there was one before in the cache, so instead of risking that the
|
/* 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 */
|
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 */
|
/* 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) {
|
if(result) {
|
||||||
free(connect_sessionid);
|
free(connect_sessionid);
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
@@ -1365,6 +1398,20 @@ Curl_gtls_connect(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
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,
|
static ssize_t gtls_send(struct connectdata *conn,
|
||||||
int sockindex,
|
int sockindex,
|
||||||
const void *mem,
|
const void *mem,
|
||||||
@@ -1384,29 +1431,29 @@ static ssize_t gtls_send(struct connectdata *conn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_one(struct connectdata *conn,
|
static void close_one(struct ssl_connect_data *ssl)
|
||||||
int idx)
|
|
||||||
{
|
{
|
||||||
if(conn->ssl[idx].session) {
|
if(ssl->session) {
|
||||||
gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
|
gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
|
||||||
gnutls_deinit(conn->ssl[idx].session);
|
gnutls_deinit(ssl->session);
|
||||||
conn->ssl[idx].session = NULL;
|
ssl->session = NULL;
|
||||||
}
|
}
|
||||||
if(conn->ssl[idx].cred) {
|
if(ssl->cred) {
|
||||||
gnutls_certificate_free_credentials(conn->ssl[idx].cred);
|
gnutls_certificate_free_credentials(ssl->cred);
|
||||||
conn->ssl[idx].cred = NULL;
|
ssl->cred = NULL;
|
||||||
}
|
}
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(conn->ssl[idx].srp_client_cred) {
|
if(ssl->srp_client_cred) {
|
||||||
gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
|
gnutls_srp_free_client_credentials(ssl->srp_client_cred);
|
||||||
conn->ssl[idx].srp_client_cred = NULL;
|
ssl->srp_client_cred = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curl_gtls_close(struct connectdata *conn, int sockindex)
|
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);
|
gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
|
||||||
|
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
|
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
|
||||||
&& data->set.ssl.username != NULL)
|
&& SSL_SET_OPTION(username) != NULL)
|
||||||
gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
|
gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1539,8 +1586,8 @@ static int Curl_gtls_seed(struct SessionHandle *data)
|
|||||||
/* Quickly add a bit of entropy */
|
/* Quickly add a bit of entropy */
|
||||||
gcry_fast_random_poll();
|
gcry_fast_random_poll();
|
||||||
|
|
||||||
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
|
if(!ssl_seeded || data->set.ssl.primary.random_file ||
|
||||||
data->set.str[STRING_SSL_EGDSOCKET]) {
|
data->set.ssl.primary.egdsocket) {
|
||||||
ssl_seeded = TRUE;
|
ssl_seeded = TRUE;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
|
|||||||
CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
|
CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
|
||||||
int sockindex,
|
int sockindex,
|
||||||
bool *done);
|
bool *done);
|
||||||
|
bool Curl_gtls_data_pending(const struct connectdata *conn,
|
||||||
|
int connindex);
|
||||||
|
|
||||||
/* close a SSL connection */
|
/* close a SSL connection */
|
||||||
void Curl_gtls_close(struct connectdata *conn, int sockindex);
|
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_engines_list(x) ((void)x, (struct curl_slist *)NULL)
|
||||||
#define curlssl_version Curl_gtls_version
|
#define curlssl_version Curl_gtls_version
|
||||||
#define curlssl_check_cxn(x) ((void)x, -1)
|
#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_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_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)
|
#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
|
* should be later deallocated using free(). If the OOM failure occurs, we
|
||||||
* return NULL, too.
|
* 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;
|
const char *n;
|
||||||
|
|
||||||
if(!is_file(str))
|
if(!is_file(str))
|
||||||
@@ -554,6 +553,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
|||||||
SECStatus status;
|
SECStatus status;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
struct ssl_connect_data *ssl = conn->ssl;
|
struct ssl_connect_data *ssl = conn->ssl;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
(void)sockindex; /* unused */
|
(void)sockindex; /* unused */
|
||||||
|
|
||||||
@@ -571,8 +571,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
|
|||||||
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
|
SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
|
||||||
PK11_IsPresent(slot);
|
PK11_IsPresent(slot);
|
||||||
|
|
||||||
status = PK11_Authenticate(slot, PR_TRUE,
|
status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
|
||||||
conn->data->set.str[STRING_KEY_PASSWD]);
|
|
||||||
PK11_FreeSlot(slot);
|
PK11_FreeSlot(slot);
|
||||||
|
|
||||||
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
|
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;
|
struct connectdata *conn = (struct connectdata *)arg;
|
||||||
|
|
||||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
#ifdef SSL_ENABLE_OCSP_STAPLING
|
||||||
if(conn->data->set.ssl.verifystatus) {
|
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||||
SECStatus cacheResult;
|
SECStatus cacheResult;
|
||||||
|
|
||||||
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
|
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
|
||||||
@@ -677,7 +676,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!conn->data->set.ssl.verifypeer) {
|
if(!SSL_CONN_CONFIG(verifypeer)) {
|
||||||
infof(conn->data, "skipping SSL peer certificate verification\n");
|
infof(conn->data, "skipping SSL peer certificate verification\n");
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
}
|
}
|
||||||
@@ -897,9 +896,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
|
|||||||
CERTCertificate *cert;
|
CERTCertificate *cert;
|
||||||
|
|
||||||
/* remember the cert verification result */
|
/* 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 */
|
/* we are asked not to verify the host name */
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
|
|
||||||
@@ -1334,38 +1336,57 @@ Curl_nss_check_cxn(struct connectdata *conn)
|
|||||||
return -1; /* connection status unknown */
|
return -1; /* connection status unknown */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void nss_close(struct ssl_connect_data *connssl)
|
||||||
* 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];
|
/* 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) {
|
if(connssl->handle) {
|
||||||
/* NSS closes the socket we previously handed to it, so we must mark it
|
if(client_cert)
|
||||||
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))
|
|
||||||
/* A server might require different authentication based on the
|
/* A server might require different authentication based on the
|
||||||
* particular path being requested by the client. To support this
|
* particular path being requested by the client. To support this
|
||||||
* scenario, we must ensure that a connection will never reuse the
|
* scenario, we must ensure that a connection will never reuse the
|
||||||
* authentication data from a previous connection. */
|
* authentication data from a previous connection. */
|
||||||
SSL_InvalidateSession(connssl->handle);
|
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);
|
PR_Close(connssl->handle);
|
||||||
connssl->handle = NULL;
|
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
|
/* return true if NSS can provide error code (and possibly msg) for the
|
||||||
error */
|
error */
|
||||||
static bool is_nss_error(CURLcode err)
|
static bool is_nss_error(CURLcode err)
|
||||||
@@ -1404,8 +1425,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
|||||||
int sockindex)
|
int sockindex)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
const char *cafile = data->set.ssl.CAfile;
|
const char *cafile = SSL_CONN_CONFIG(CAfile);
|
||||||
const char *capath = data->set.ssl.CApath;
|
const char *capath = SSL_CONN_CONFIG(CApath);
|
||||||
|
|
||||||
if(cafile) {
|
if(cafile) {
|
||||||
CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
|
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,
|
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:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
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];
|
curl_socket_t sockfd = conn->sock[sockindex];
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
bool second_layer = FALSE;
|
||||||
|
|
||||||
SSLVersionRange sslver = {
|
SSLVersionRange sslver = {
|
||||||
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
|
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
|
||||||
@@ -1614,18 +1637,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* do not use SSL cache if disabled or we are not going to verify peer */
|
/* do not use SSL cache if disabled or we are not going to verify peer */
|
||||||
ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
|
ssl_no_cache = (data->set.general_ssl.sessionid
|
||||||
PR_FALSE : PR_TRUE;
|
&& SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
|
||||||
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
|
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* enable/disable the requested SSL version(s) */
|
/* 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;
|
goto error;
|
||||||
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
|
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
|
||||||
goto error;
|
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
|
#ifdef SSL_CBC_RANDOM_IV
|
||||||
/* unless the user explicitly asks to allow the protocol vulnerability, we
|
/* unless the user explicitly asks to allow the protocol vulnerability, we
|
||||||
use the work-around */
|
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");
|
infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.ssl.cipher_list) {
|
if(SSL_CONN_CONFIG(cipher_list)) {
|
||||||
if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
|
if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
|
||||||
result = CURLE_SSL_CIPHER;
|
result = CURLE_SSL_CIPHER;
|
||||||
goto error;
|
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");
|
infof(data, "warning: ignoring value of ssl.verifyhost\n");
|
||||||
|
|
||||||
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
|
/* 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)
|
if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
|
||||||
goto error;
|
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)
|
if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
|
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
|
const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
|
||||||
if(rv) {
|
if(rv) {
|
||||||
result = rv;
|
result = rv;
|
||||||
@@ -1667,24 +1695,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.ssl.CRLfile) {
|
if(SSL_SET_OPTION(CRLfile)) {
|
||||||
const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
|
const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
|
||||||
if(rv) {
|
if(rv) {
|
||||||
result = rv;
|
result = rv;
|
||||||
goto error;
|
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]) {
|
if(SSL_SET_OPTION(cert)) {
|
||||||
char *nickname = dup_nickname(data, STRING_CERT);
|
char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
|
||||||
if(nickname) {
|
if(nickname) {
|
||||||
/* we are not going to use libnsspem.so to read the client cert */
|
/* we are not going to use libnsspem.so to read the client cert */
|
||||||
connssl->obj_clicert = NULL;
|
connssl->obj_clicert = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
|
CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
|
||||||
data->set.str[STRING_KEY]);
|
SSL_SET_OPTION(key));
|
||||||
if(rv) {
|
if(rv) {
|
||||||
/* failf() is already done in cert_stuff() */
|
/* failf() is already done in cert_stuff() */
|
||||||
result = rv;
|
result = rv;
|
||||||
@@ -1704,15 +1732,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wrap OS file descriptor by NSPR's file descriptor abstraction */
|
if(conn->proxy_ssl[sockindex].use) {
|
||||||
nspr_io = PR_ImportTCPSocket(sockfd);
|
DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
|
||||||
if(!nspr_io)
|
DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
|
||||||
goto error;
|
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 */
|
/* create our own NSPR I/O layer */
|
||||||
nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
|
nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
|
||||||
if(!nspr_io_stub) {
|
if(!nspr_io_stub) {
|
||||||
PR_Close(nspr_io);
|
if(!second_layer)
|
||||||
|
PR_Close(nspr_io);
|
||||||
goto error;
|
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 */
|
/* push our new layer to the NSPR I/O stack */
|
||||||
if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
|
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);
|
PR_Close(nspr_io_stub);
|
||||||
goto error;
|
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 */
|
/* import our model socket onto the current I/O stack */
|
||||||
connssl->handle = SSL_ImportFD(model, nspr_io);
|
connssl->handle = SSL_ImportFD(model, nspr_io);
|
||||||
if(!connssl->handle) {
|
if(!connssl->handle) {
|
||||||
PR_Close(nspr_io);
|
if(!second_layer)
|
||||||
|
PR_Close(nspr_io);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1737,12 +1776,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
|||||||
model = NULL;
|
model = NULL;
|
||||||
|
|
||||||
/* This is the password associated with the cert that we're using */
|
/* This is the password associated with the cert that we're using */
|
||||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
if(SSL_SET_OPTION(key_passwd)) {
|
||||||
SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
|
SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
#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)
|
if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
|
||||||
!= SECSuccess)
|
!= SECSuccess)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -1802,11 +1841,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* propagate hostname to the TLS layer */
|
/* 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;
|
goto error;
|
||||||
|
|
||||||
/* prevent NSS from re-using the session for a different hostname */
|
/* 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;
|
goto error;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
@@ -1824,6 +1866,8 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
|||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
CURLcode result = CURLE_SSL_CONNECT_ERROR;
|
CURLcode result = CURLE_SSL_CONNECT_ERROR;
|
||||||
PRUint32 timeout;
|
PRUint32 timeout;
|
||||||
|
long * const certverifyresult = SSL_IS_PROXY() ?
|
||||||
|
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
|
||||||
|
|
||||||
/* check timeout situation */
|
/* check timeout situation */
|
||||||
const long time_left = Curl_timeleft(data, NULL, TRUE);
|
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)
|
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
|
||||||
/* blocking direction is updated by nss_update_connecting_state() */
|
/* blocking direction is updated by nss_update_connecting_state() */
|
||||||
return CURLE_AGAIN;
|
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;
|
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||||
else if(conn->data->set.ssl.certverifyresult!=0)
|
else if(*certverifyresult != 0)
|
||||||
result = CURLE_SSL_CACERT;
|
result = CURLE_SSL_CACERT;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -1850,11 +1894,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
|
|||||||
if(result)
|
if(result)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if(data->set.str[STRING_SSL_ISSUERCERT]) {
|
if(data->set.ssl.issuercert) {
|
||||||
SECStatus ret = SECFailure;
|
SECStatus ret = SECFailure;
|
||||||
char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
|
char *nickname = dup_nickname(data, data->set.ssl.issuercert);
|
||||||
if(nickname) {
|
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);
|
ret = check_issuer_cert(connssl->handle, nickname);
|
||||||
free(nickname);
|
free(nickname);
|
||||||
}
|
}
|
||||||
|
@@ -189,13 +189,13 @@ static int ossl_seed(struct SessionHandle *data)
|
|||||||
#ifndef RANDOM_FILE
|
#ifndef RANDOM_FILE
|
||||||
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
|
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
|
||||||
us to! */
|
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 */
|
#define RANDOM_FILE "" /* doesn't matter won't be used */
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* let the option override the define */
|
/* let the option override the define */
|
||||||
nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
|
nread += RAND_load_file((data->set.ssl.primary.random_file?
|
||||||
data->set.str[STRING_SSL_RANDOM_FILE]:
|
data->set.ssl.primary.random_file:
|
||||||
RANDOM_FILE),
|
RANDOM_FILE),
|
||||||
RAND_LOAD_LENGTH);
|
RAND_LOAD_LENGTH);
|
||||||
if(seed_enough(nread))
|
if(seed_enough(nread))
|
||||||
@@ -208,14 +208,14 @@ static int ossl_seed(struct SessionHandle *data)
|
|||||||
#ifndef EGD_SOCKET
|
#ifndef EGD_SOCKET
|
||||||
/* If we don't have the define set, we only do this if the egd-option
|
/* If we don't have the define set, we only do this if the egd-option
|
||||||
is set */
|
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 */
|
#define EGD_SOCKET "" /* doesn't matter won't be used */
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* If there's an option and a define, the option overrides the
|
/* If there's an option and a define, the option overrides the
|
||||||
define */
|
define */
|
||||||
int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
|
int ret = RAND_egd(data->set.ssl.primary.egdsocket?
|
||||||
data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
|
data->set.ssl.primary.egdsocket:EGD_SOCKET);
|
||||||
if(-1 != ret) {
|
if(-1 != ret) {
|
||||||
nread += ret;
|
nread += ret;
|
||||||
if(seed_enough(nread))
|
if(seed_enough(nread))
|
||||||
@@ -253,8 +253,8 @@ static void Curl_ossl_seed(struct SessionHandle *data)
|
|||||||
time-consuming seedings in vain */
|
time-consuming seedings in vain */
|
||||||
static bool ssl_seeded = FALSE;
|
static bool ssl_seeded = FALSE;
|
||||||
|
|
||||||
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
|
if(!ssl_seeded || data->set.ssl.primary.random_file ||
|
||||||
data->set.str[STRING_SSL_EGDSOCKET]) {
|
data->set.ssl.primary.egdsocket) {
|
||||||
ossl_seed(data);
|
ossl_seed(data);
|
||||||
ssl_seeded = TRUE;
|
ssl_seeded = TRUE;
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,8 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
char *cert_file,
|
char *cert_file,
|
||||||
const char *cert_type,
|
const char *cert_type,
|
||||||
char *key_file,
|
char *key_file,
|
||||||
const char *key_type)
|
const char *key_type,
|
||||||
|
char *key_passwd)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
@@ -345,10 +346,9 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
X509 *x509;
|
X509 *x509;
|
||||||
int cert_done = 0;
|
int cert_done = 0;
|
||||||
|
|
||||||
if(data->set.str[STRING_KEY_PASSWD]) {
|
if(key_passwd) {
|
||||||
/* set the password in the callback userdata */
|
/* set the password in the callback userdata */
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ctx,
|
SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
|
||||||
data->set.str[STRING_KEY_PASSWD]);
|
|
||||||
/* Set passwd callback: */
|
/* Set passwd callback: */
|
||||||
SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
|
SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
|
||||||
}
|
}
|
||||||
@@ -457,7 +457,7 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
|
|
||||||
PKCS12_PBE_add();
|
PKCS12_PBE_add();
|
||||||
|
|
||||||
if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
|
if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
|
||||||
&ca)) {
|
&ca)) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"could not parse PKCS12 file, check password, OpenSSL error %s",
|
"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
|
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||||
ui_method,
|
ui_method,
|
||||||
#endif
|
#endif
|
||||||
data->set.str[STRING_KEY_PASSWD]);
|
key_passwd);
|
||||||
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
|
||||||
UI_destroy_method(ui_method);
|
UI_destroy_method(ui_method);
|
||||||
#endif
|
#endif
|
||||||
@@ -864,13 +864,8 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static void ossl_close(struct ssl_connect_data *connssl)
|
||||||
* This function is called when an SSL connection is closed.
|
|
||||||
*/
|
|
||||||
void Curl_ossl_close(struct connectdata *conn, int sockindex)
|
|
||||||
{
|
{
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
|
||||||
|
|
||||||
if(connssl->handle) {
|
if(connssl->handle) {
|
||||||
(void)SSL_shutdown(connssl->handle);
|
(void)SSL_shutdown(connssl->handle);
|
||||||
SSL_set_connect_state(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
|
* This function is called to shut down the SSL layer but keep the
|
||||||
* socket open (CCC - Clear Command Channel)
|
* socket open (CCC - Clear Command Channel)
|
||||||
@@ -1046,16 +1050,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#endif
|
#endif
|
||||||
CURLcode result = CURLE_OK;
|
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
|
#ifdef ENABLE_IPV6
|
||||||
if(conn->bits.ipv6_ip &&
|
if(conn->bits.ipv6_ip &&
|
||||||
Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
|
Curl_inet_pton(AF_INET6, hostname, &addr)) {
|
||||||
target = GEN_IPADD;
|
target = GEN_IPADD;
|
||||||
addrlen = sizeof(struct in6_addr);
|
addrlen = sizeof(struct in6_addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
|
if(Curl_inet_pton(AF_INET, hostname, &addr)) {
|
||||||
target = GEN_IPADD;
|
target = GEN_IPADD;
|
||||||
addrlen = sizeof(struct in_addr);
|
addrlen = sizeof(struct in_addr);
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1105,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
if((altlen == strlen(altptr)) &&
|
if((altlen == strlen(altptr)) &&
|
||||||
/* if this isn't true, there was an embedded zero in the name
|
/* if this isn't true, there was an embedded zero in the name
|
||||||
string and we cannot match it. */
|
string and we cannot match it. */
|
||||||
Curl_cert_hostcheck(altptr, conn->host.name))
|
Curl_cert_hostcheck(altptr, hostname))
|
||||||
matched = 1;
|
matched = 1;
|
||||||
else
|
else
|
||||||
matched = 0;
|
matched = 0;
|
||||||
@@ -1119,13 +1127,13 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
|
|
||||||
if(matched == 1)
|
if(matched == 1)
|
||||||
/* an alternative name matched the server hostname */
|
/* 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) {
|
else if(matched == 0) {
|
||||||
/* an alternative name field existed, but didn't match and then
|
/* an alternative name field existed, but didn't match and then
|
||||||
we MUST fail */
|
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 "
|
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;
|
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1199,9 +1207,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
|
|||||||
"SSL: unable to obtain common name from peer certificate");
|
"SSL: unable to obtain common name from peer certificate");
|
||||||
result = CURLE_PEER_FAILED_VERIFICATION;
|
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 "
|
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;
|
result = CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1638,17 +1646,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#endif
|
#endif
|
||||||
#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);
|
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||||
|
|
||||||
/* Make funny stuff to get random input */
|
/* Make funny stuff to get random input */
|
||||||
Curl_ossl_seed(data);
|
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 */
|
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||||
|
switch(ssl_version) {
|
||||||
switch(data->set.ssl.version) {
|
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
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_1:
|
||||||
case CURL_SSLVERSION_TLSv1_2:
|
case CURL_SSLVERSION_TLSv1_2:
|
||||||
/* it will be handled later with the context options */
|
/* it will be handled later with the context options */
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
|
||||||
!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
|
!defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
req_method = TLS_client_method();
|
req_method = TLS_client_method();
|
||||||
#else
|
#else
|
||||||
req_method = SSLv23_client_method();
|
req_method = SSLv23_client_method();
|
||||||
@@ -1670,7 +1691,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
return CURLE_NOT_BUILT_IN;
|
return CURLE_NOT_BUILT_IN;
|
||||||
#else
|
#else
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
|
if(ssl_authtype == CURL_TLSAUTH_SRP)
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
#endif
|
#endif
|
||||||
req_method = SSLv2_client_method();
|
req_method = SSLv2_client_method();
|
||||||
@@ -1683,7 +1704,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
return CURLE_NOT_BUILT_IN;
|
return CURLE_NOT_BUILT_IN;
|
||||||
#else
|
#else
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
|
if(ssl_authtype == CURL_TLSAUTH_SRP)
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
#endif
|
#endif
|
||||||
req_method = SSLv3_client_method();
|
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
|
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
|
||||||
/* unless the user explicitly ask to allow the protocol vulnerability we
|
/* unless the user explicitly ask to allow the protocol vulnerability we
|
||||||
use the work-around */
|
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;
|
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch(data->set.ssl.version) {
|
switch(ssl_version) {
|
||||||
case CURL_SSLVERSION_SSLv3:
|
case CURL_SSLVERSION_SSLv3:
|
||||||
#ifdef USE_TLS_SRP
|
#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");
|
infof(data, "Set version TLSv1.x for SRP authorisation\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1869,19 +1890,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
if(ssl_cert || ssl_cert_type) {
|
||||||
if(!cert_stuff(conn,
|
if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
|
||||||
connssl->ctx,
|
SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
|
||||||
data->set.str[STRING_CERT],
|
SSL_SET_OPTION(key_passwd))) {
|
||||||
data->set.str[STRING_CERT_TYPE],
|
|
||||||
data->set.str[STRING_KEY],
|
|
||||||
data->set.str[STRING_KEY_TYPE])) {
|
|
||||||
/* failf() is already done in cert_stuff() */
|
/* failf() is already done in cert_stuff() */
|
||||||
return CURLE_SSL_CERTPROBLEM;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
|
ciphers = SSL_CONN_CONFIG(cipher_list);
|
||||||
if(!ciphers)
|
if(!ciphers)
|
||||||
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
|
ciphers = (char *)DEFAULT_CIPHER_SELECTION;
|
||||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
|
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);
|
infof(data, "Cipher selection: %s\n", ciphers);
|
||||||
|
|
||||||
#ifdef USE_TLS_SRP
|
#ifdef USE_TLS_SRP
|
||||||
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
|
if(ssl_authtype == CURL_TLSAUTH_SRP) {
|
||||||
infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
|
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");
|
failf(data, "Unable to set SRP user name");
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
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");
|
failf(data, "failed setting SRP password");
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
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");
|
infof(data, "Setting cipher list SRP\n");
|
||||||
|
|
||||||
if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
|
if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
|
||||||
@@ -1912,20 +1932,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
/* tell SSL where to find CA certificates that are used to verify
|
||||||
the servers certificate. */
|
the servers certificate. */
|
||||||
if(!SSL_CTX_load_verify_locations(connssl->ctx,
|
if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
|
||||||
data->set.str[STRING_SSL_CAFILE],
|
if(verifypeer) {
|
||||||
data->set.str[STRING_SSL_CAPATH])) {
|
|
||||||
if(data->set.ssl.verifypeer) {
|
|
||||||
/* Fail if we insist on successfully verifying the server. */
|
/* Fail if we insist on successfully verifying the server. */
|
||||||
failf(data, "error setting certificate verify locations:\n"
|
failf(data, "error setting certificate verify locations:\n"
|
||||||
" CAfile: %s\n CApath: %s",
|
" CAfile: %s\n CApath: %s",
|
||||||
data->set.str[STRING_SSL_CAFILE]?
|
ssl_cafile ? ssl_cafile : "none",
|
||||||
data->set.str[STRING_SSL_CAFILE]: "none",
|
ssl_capath ? ssl_capath : "none");
|
||||||
data->set.str[STRING_SSL_CAPATH]?
|
|
||||||
data->set.str[STRING_SSL_CAPATH] : "none");
|
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1942,22 +1959,18 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
infof(data,
|
infof(data,
|
||||||
" CAfile: %s\n"
|
" CAfile: %s\n"
|
||||||
" CApath: %s\n",
|
" CApath: %s\n",
|
||||||
data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
|
ssl_cafile ? ssl_cafile : "none",
|
||||||
"none",
|
ssl_capath ? ssl_capath : "none");
|
||||||
data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_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
|
/* tell SSL where to find CRL file that is used to check certificate
|
||||||
* revocation */
|
* revocation */
|
||||||
lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
|
lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
|
||||||
X509_LOOKUP_file());
|
X509_LOOKUP_file());
|
||||||
if(!lookup ||
|
if(!lookup ||
|
||||||
(!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
|
(!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
|
||||||
X509_FILETYPE_PEM)) ) {
|
failf(data, "error loading CRL file: %s", ssl_crlfile);
|
||||||
failf(data, "error loading CRL file: %s",
|
|
||||||
data->set.str[STRING_SSL_CRLFILE]);
|
|
||||||
return CURLE_SSL_CRL_BADFILE;
|
return CURLE_SSL_CRL_BADFILE;
|
||||||
}
|
}
|
||||||
else {
|
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_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
|
||||||
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
|
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
|
||||||
}
|
}
|
||||||
infof(data,
|
infof(data, " CRLfile: %s\n", ssl_crlfile ? ssl_crlfile: "none");
|
||||||
" CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
|
|
||||||
data->set.str[STRING_SSL_CRLFILE]: "none");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try building a chain using issuers in the trusted store first to avoid
|
/* 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
|
* anyway. In the latter case the result of the verification is checked with
|
||||||
* SSL_get_verify_result() below. */
|
* SSL_get_verify_result() below. */
|
||||||
SSL_CTX_set_verify(connssl->ctx,
|
SSL_CTX_set_verify(connssl->ctx,
|
||||||
data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
|
verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* give application a chance to interfere with SSL set up. */
|
/* give application a chance to interfere with SSL set up. */
|
||||||
if(data->set.ssl.fsslctx) {
|
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) && \
|
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||||
!defined(OPENSSL_IS_BORINGSSL)
|
!defined(OPENSSL_IS_BORINGSSL)
|
||||||
if(data->set.ssl.verifystatus)
|
if(SSL_CONN_CONFIG(verifystatus))
|
||||||
SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
|
SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SSL_set_connect_state(connssl->handle);
|
SSL_set_connect_state(connssl->handle);
|
||||||
|
|
||||||
connssl->server_cert = 0x0;
|
connssl->server_cert = 0x0;
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
#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
|
#ifdef ENABLE_IPV6
|
||||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
|
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
|
||||||
#endif
|
#endif
|
||||||
sni &&
|
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) "
|
infof(data, "WARNING: failed to configure server name indication (SNI) "
|
||||||
"TLS extension\n");
|
"TLS extension\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check if there's a cached ID we can/should use here! */
|
/* 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! */
|
/* we got a session id, use it! */
|
||||||
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
|
if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
|
||||||
failf(data, "SSL: SSL_set_session failed: %s",
|
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");
|
infof (data, "SSL re-using session ID\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pass the raw socket into the SSL layers */
|
if(conn->proxy_ssl[sockindex].use) {
|
||||||
if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
|
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",
|
failf(data, "SSL: SSL_set_fd failed: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
@@ -2063,8 +2080,8 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
|
|||||||
int err;
|
int err;
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
||||||
|| ssl_connect_2_reading == connssl->connecting_state
|
|| ssl_connect_2_reading == connssl->connecting_state
|
||||||
|| ssl_connect_2_writing == connssl->connecting_state);
|
|| ssl_connect_2_writing == connssl->connecting_state);
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
@@ -2139,8 +2156,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
|
|||||||
* the SO_ERROR is also lost.
|
* the SO_ERROR is also lost.
|
||||||
*/
|
*/
|
||||||
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
|
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 ",
|
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
|
||||||
conn->host.name, conn->remote_port);
|
hostname, port);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2484,6 +2504,8 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *buffer = data->state.buffer;
|
char *buffer = data->state.buffer;
|
||||||
const char *ptr;
|
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());
|
BIO *mem = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
if(data->set.ssl.certinfo)
|
if(data->set.ssl.certinfo)
|
||||||
@@ -2499,7 +2521,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
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),
|
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
||||||
buffer, BUFSIZE);
|
buffer, BUFSIZE);
|
||||||
@@ -2517,7 +2539,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
|
|
||||||
BIO_free(mem);
|
BIO_free(mem);
|
||||||
|
|
||||||
if(data->set.ssl.verifyhost) {
|
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||||
result = verifyhost(conn, connssl->server_cert);
|
result = verifyhost(conn, connssl->server_cert);
|
||||||
if(result) {
|
if(result) {
|
||||||
X509_free(connssl->server_cert);
|
X509_free(connssl->server_cert);
|
||||||
@@ -2540,12 +2562,12 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
deallocating the certificate. */
|
deallocating the certificate. */
|
||||||
|
|
||||||
/* e.g. match issuer name with provided issuer certificate */
|
/* e.g. match issuer name with provided issuer certificate */
|
||||||
if(data->set.str[STRING_SSL_ISSUERCERT]) {
|
if(data->set.ssl.issuercert) {
|
||||||
fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT);
|
fp = fopen(data->set.ssl.issuercert, FOPEN_READTEXT);
|
||||||
if(!fp) {
|
if(!fp) {
|
||||||
if(strict)
|
if(strict)
|
||||||
failf(data, "SSL: Unable to open issuer cert (%s)",
|
failf(data, "SSL: Unable to open issuer cert (%s)",
|
||||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
data->set.ssl.issuercert);
|
||||||
X509_free(connssl->server_cert);
|
X509_free(connssl->server_cert);
|
||||||
connssl->server_cert = NULL;
|
connssl->server_cert = NULL;
|
||||||
return CURLE_SSL_ISSUER_ERROR;
|
return CURLE_SSL_ISSUER_ERROR;
|
||||||
@@ -2555,7 +2577,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
if(!issuer) {
|
if(!issuer) {
|
||||||
if(strict)
|
if(strict)
|
||||||
failf(data, "SSL: Unable to read issuer cert (%s)",
|
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(connssl->server_cert);
|
||||||
X509_free(issuer);
|
X509_free(issuer);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -2567,7 +2589,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
|
if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
|
||||||
if(strict)
|
if(strict)
|
||||||
failf(data, "SSL: Certificate issuer check failed (%s)",
|
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(connssl->server_cert);
|
||||||
X509_free(issuer);
|
X509_free(issuer);
|
||||||
connssl->server_cert = NULL;
|
connssl->server_cert = NULL;
|
||||||
@@ -2575,15 +2597,14 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
infof(data, "\t SSL certificate issuer check ok (%s)\n",
|
infof(data, "\t SSL certificate issuer check ok (%s)\n",
|
||||||
data->set.str[STRING_SSL_ISSUERCERT]);
|
data->set.ssl.issuercert);
|
||||||
X509_free(issuer);
|
X509_free(issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
lerr = data->set.ssl.certverifyresult =
|
lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
|
||||||
SSL_get_verify_result(connssl->handle);
|
|
||||||
|
|
||||||
if(data->set.ssl.certverifyresult != X509_V_OK) {
|
if(*certverifyresult != X509_V_OK) {
|
||||||
if(data->set.ssl.verifypeer) {
|
if(SSL_CONN_CONFIG(verifypeer)) {
|
||||||
/* We probably never reach this, because SSL_connect() will fail
|
/* We probably never reach this, because SSL_connect() will fail
|
||||||
and we return earlier if verifypeer is set? */
|
and we return earlier if verifypeer is set? */
|
||||||
if(strict)
|
if(strict)
|
||||||
@@ -2602,7 +2623,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
|
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||||
!defined(OPENSSL_IS_BORINGSSL)
|
!defined(OPENSSL_IS_BORINGSSL)
|
||||||
if(data->set.ssl.verifystatus) {
|
if(SSL_CONN_CONFIG(verifystatus)) {
|
||||||
result = verifystatus(conn, connssl);
|
result = verifystatus(conn, connssl);
|
||||||
if(result) {
|
if(result) {
|
||||||
X509_free(connssl->server_cert);
|
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),
|
will stay in memory until explicitly freed with SSL_SESSION_free(3),
|
||||||
regardless of its state. */
|
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(incache) {
|
||||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||||
infof(data, "old SSL session ID is stale, removing\n");
|
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) {
|
if(!incache) {
|
||||||
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
|
||||||
0 /* unknown size */);
|
0 /* unknown size */, sockindex);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data, "failed to store ssl session");
|
failf(data, "failed to store ssl session");
|
||||||
return result;
|
return result;
|
||||||
@@ -2679,8 +2701,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
|
|||||||
* operations.
|
* operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = servercert(conn, connssl,
|
result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
|
||||||
(data->set.ssl.verifypeer || data->set.ssl.verifyhost));
|
SSL_CONN_CONFIG(verifyhost)));
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
connssl->connecting_state = ssl_connect_done;
|
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)
|
if(conn->ssl[connindex].handle)
|
||||||
/* SSL is in use */
|
/* 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
|
else
|
||||||
return FALSE;
|
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.
|
/* A failure in the SSL library occurred, usually a protocol error.
|
||||||
The OpenSSL error queue contains more information on the error. */
|
The OpenSSL error queue contains more information on the error. */
|
||||||
sslerror = ERR_get_error();
|
sslerror = ERR_get_error();
|
||||||
failf(conn->data, "SSL_write() error: %s",
|
if(sslerror ==
|
||||||
ERR_error_string(sslerror, error_buffer));
|
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;
|
*curlcode = CURLE_SEND_ERROR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -132,6 +132,10 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
|
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 */
|
bool sni = TRUE; /* default is SNI enabled */
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -146,11 +150,11 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
errorbuf[0]=0;
|
errorbuf[0]=0;
|
||||||
|
|
||||||
/* PolarSSL only supports SSLv3 and TLSv1 */
|
/* 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");
|
failf(data, "PolarSSL does not support SSLv2");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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 */
|
sni = FALSE; /* SSLv3 has no SNI */
|
||||||
|
|
||||||
#ifdef THREADING_SUPPORT
|
#ifdef THREADING_SUPPORT
|
||||||
@@ -180,34 +184,33 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
/* Load the trusted CA */
|
/* Load the trusted CA */
|
||||||
memset(&connssl->cacert, 0, sizeof(x509_crt));
|
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,
|
ret = x509_crt_parse_file(&connssl->cacert,
|
||||||
data->set.str[STRING_SSL_CAFILE]);
|
SSL_CONN_CONFIG(CAfile));
|
||||||
|
|
||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
#ifdef POLARSSL_ERROR_C
|
#ifdef POLARSSL_ERROR_C
|
||||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||||
#endif /* POLARSSL_ERROR_C */
|
#endif /* POLARSSL_ERROR_C */
|
||||||
failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
|
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;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.str[STRING_SSL_CAPATH]) {
|
if(capath) {
|
||||||
ret = x509_crt_parse_path(&connssl->cacert,
|
ret = x509_crt_parse_path(&connssl->cacert, capath);
|
||||||
data->set.str[STRING_SSL_CAPATH]);
|
|
||||||
|
|
||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
#ifdef POLARSSL_ERROR_C
|
#ifdef POLARSSL_ERROR_C
|
||||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||||
#endif /* POLARSSL_ERROR_C */
|
#endif /* POLARSSL_ERROR_C */
|
||||||
failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
|
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;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,27 +218,27 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
/* Load the client certificate */
|
/* Load the client certificate */
|
||||||
memset(&connssl->clicert, 0, sizeof(x509_crt));
|
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,
|
ret = x509_crt_parse_file(&connssl->clicert,
|
||||||
data->set.str[STRING_CERT]);
|
SSL_SET_OPTION(cert));
|
||||||
|
|
||||||
if(ret) {
|
if(ret) {
|
||||||
#ifdef POLARSSL_ERROR_C
|
#ifdef POLARSSL_ERROR_C
|
||||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||||
#endif /* POLARSSL_ERROR_C */
|
#endif /* POLARSSL_ERROR_C */
|
||||||
failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
|
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;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the client private key */
|
/* Load the client private key */
|
||||||
if(data->set.str[STRING_KEY]) {
|
if(SSL_SET_OPTION(key)) {
|
||||||
pk_context pk;
|
pk_context pk;
|
||||||
pk_init(&pk);
|
pk_init(&pk);
|
||||||
ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
|
ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
|
||||||
data->set.str[STRING_KEY_PASSWD]);
|
SSL_SET_OPTION(key_passwd));
|
||||||
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
|
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
|
||||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||||
if(ret == 0)
|
if(ret == 0)
|
||||||
@@ -249,7 +252,7 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||||
#endif /* POLARSSL_ERROR_C */
|
#endif /* POLARSSL_ERROR_C */
|
||||||
failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
|
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;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
@@ -258,30 +261,29 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
/* Load the CRL */
|
/* Load the CRL */
|
||||||
memset(&connssl->crl, 0, sizeof(x509_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,
|
ret = x509_crl_parse_file(&connssl->crl,
|
||||||
data->set.str[STRING_SSL_CRLFILE]);
|
SSL_SET_OPTION(CRLfile));
|
||||||
|
|
||||||
if(ret) {
|
if(ret) {
|
||||||
#ifdef POLARSSL_ERROR_C
|
#ifdef POLARSSL_ERROR_C
|
||||||
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
error_strerror(ret, errorbuf, sizeof(errorbuf));
|
||||||
#endif /* POLARSSL_ERROR_C */
|
#endif /* POLARSSL_ERROR_C */
|
||||||
failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
|
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;
|
return CURLE_SSL_CRL_BADFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
infof(data, "PolarSSL: Connecting to %s:%d\n",
|
infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
|
||||||
conn->host.name, conn->remote_port);
|
|
||||||
|
|
||||||
if(ssl_init(&connssl->ssl)) {
|
if(ssl_init(&connssl->ssl)) {
|
||||||
failf(data, "PolarSSL: ssl_init failed");
|
failf(data, "PolarSSL: ssl_init failed");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(data->set.ssl.version) {
|
switch(SSL_CONN_CONFIG(version)) {
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
@@ -328,7 +330,8 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
net_send, &conn->sock[sockindex]);
|
net_send, &conn->sock[sockindex]);
|
||||||
|
|
||||||
ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
|
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);
|
memcpy(&connssl->ssn, old_session, old_session_size);
|
||||||
infof(data, "PolarSSL re-using session\n");
|
infof(data, "PolarSSL re-using session\n");
|
||||||
}
|
}
|
||||||
@@ -339,16 +342,16 @@ polarssl_connect_step1(struct connectdata *conn,
|
|||||||
ssl_set_ca_chain(&connssl->ssl,
|
ssl_set_ca_chain(&connssl->ssl,
|
||||||
&connssl->cacert,
|
&connssl->cacert,
|
||||||
&connssl->crl,
|
&connssl->crl,
|
||||||
conn->host.name);
|
hostname);
|
||||||
|
|
||||||
ssl_set_own_cert_rsa(&connssl->ssl,
|
ssl_set_own_cert_rsa(&connssl->ssl,
|
||||||
&connssl->clicert, &connssl->rsa);
|
&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
|
#ifdef ENABLE_IPV6
|
||||||
!Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
|
!Curl_inet_pton(AF_INET6, hostname, &addr) &&
|
||||||
#endif
|
#endif
|
||||||
sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
|
sni && ssl_set_hostname(&connssl->ssl, hostname)) {
|
||||||
infof(data, "WARNING: failed to configure "
|
infof(data, "WARNING: failed to configure "
|
||||||
"server name indication (SNI) TLS extension\n");
|
"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);
|
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)
|
if(ret & BADCERT_EXPIRED)
|
||||||
failf(data, "Cert verify failed: 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);
|
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
|
||||||
|
|
||||||
/* Save the current session data for possible re-use */
|
/* 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(incache) {
|
||||||
if(old_ssl_sessionid != our_ssl_sessionid) {
|
if(old_ssl_sessionid != our_ssl_sessionid) {
|
||||||
infof(data, "old SSL session ID is stale, removing\n");
|
infof(data, "old SSL session ID is stale, removing\n");
|
||||||
@@ -511,7 +515,8 @@ polarssl_connect_step3(struct connectdata *conn,
|
|||||||
if(new_session) {
|
if(new_session) {
|
||||||
memcpy(new_session, our_ssl_sessionid, sizeof(ssl_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
|
else
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
@@ -111,7 +111,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
|||||||
conn->host.name, conn->remote_port);
|
conn->host.name, conn->remote_port);
|
||||||
|
|
||||||
/* check for an existing re-usable credential handle */
|
/* 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;
|
connssl->cred = old_cred;
|
||||||
infof(data, "schannel: re-using existing credential handle\n");
|
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));
|
memset(&schannel_cred, 0, sizeof(schannel_cred));
|
||||||
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||||
|
|
||||||
if(data->set.ssl.verifypeer) {
|
if(conn->ssl_config.verifypeer) {
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
/* certificate validation on CE doesn't seem to work right; we'll
|
/* certificate validation on CE doesn't seem to work right; we'll
|
||||||
do it following a more manual process. */
|
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");
|
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;
|
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||||
infof(data, "schannel: verifyhost setting prevents Schannel from "
|
infof(data, "schannel: verifyhost setting prevents Schannel from "
|
||||||
"comparing the supplied target name with the subject "
|
"comparing the supplied target name with the subject "
|
||||||
"names in server certificates. Also disables SNI.\n");
|
"names in server certificates. Also disables SNI.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(data->set.ssl.version) {
|
switch(conn->ssl_config.version) {
|
||||||
default:
|
default:
|
||||||
case CURL_SSLVERSION_DEFAULT:
|
case CURL_SSLVERSION_DEFAULT:
|
||||||
case CURL_SSLVERSION_TLSv1:
|
case CURL_SSLVERSION_TLSv1:
|
||||||
@@ -520,7 +520,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
|
|||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
/* Windows CE doesn't do any server certificate validation.
|
/* Windows CE doesn't do any server certificate validation.
|
||||||
We have to do it manually. */
|
We have to do it manually. */
|
||||||
if(data->set.ssl.verifypeer)
|
if(conn->ssl_config.verifypeer)
|
||||||
return verify_certificate(conn, sockindex);
|
return verify_certificate(conn, sockindex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -567,7 +567,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* save the current session data for possible re-use */
|
/* 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(incache) {
|
||||||
if(old_cred != connssl->cred) {
|
if(old_cred != connssl->cred) {
|
||||||
infof(data, "schannel: old credential handle is stale, removing\n");
|
infof(data, "schannel: old credential handle is stale, removing\n");
|
||||||
@@ -578,7 +579,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
|
|||||||
|
|
||||||
if(!incache) {
|
if(!incache) {
|
||||||
result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
|
result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
|
||||||
sizeof(struct curl_schannel_cred));
|
sizeof(struct curl_schannel_cred),
|
||||||
|
sockindex);
|
||||||
if(result) {
|
if(result) {
|
||||||
failf(data, "schannel: failed to store credential handle");
|
failf(data, "schannel: failed to store credential handle");
|
||||||
return result;
|
return result;
|
||||||
@@ -1441,7 +1443,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(result == CURLE_OK) {
|
if(result == CURLE_OK) {
|
||||||
if(data->set.ssl.verifyhost) {
|
if(conn->ssl_config.verifyhost) {
|
||||||
TCHAR cert_hostname_buff[128];
|
TCHAR cert_hostname_buff[128];
|
||||||
xcharp_u hostname;
|
xcharp_u hostname;
|
||||||
xcharp_u cert_hostname;
|
xcharp_u cert_hostname;
|
||||||
|
249
lib/vtls/vtls.c
249
lib/vtls/vtls.c
@@ -65,6 +65,7 @@
|
|||||||
#include "url.h"
|
#include "url.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "share.h"
|
#include "share.h"
|
||||||
|
#include "multiif.h"
|
||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
#include "curl_md5.h"
|
#include "curl_md5.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
@@ -80,86 +81,84 @@
|
|||||||
(data->share->specifier & \
|
(data->share->specifier & \
|
||||||
(1<<CURL_LOCK_DATA_SSL_SESSION)))
|
(1<<CURL_LOCK_DATA_SSL_SESSION)))
|
||||||
|
|
||||||
static bool safe_strequal(char* str1, char* str2)
|
#define CLONE_STRING(var) if(source->var) { \
|
||||||
{
|
dest->var = strdup(source->var); \
|
||||||
if(str1 && str2)
|
if(!dest->var) \
|
||||||
/* both pointers point to something then compare them */
|
return FALSE; \
|
||||||
return (0 != Curl_raw_equal(str1, str2)) ? TRUE : FALSE;
|
} \
|
||||||
else
|
else \
|
||||||
/* if both pointers are NULL then treat them as equal */
|
dest->var = NULL;
|
||||||
return (!str1 && !str2) ? TRUE : FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Curl_ssl_config_matches(struct ssl_config_data* data,
|
Curl_ssl_config_matches(struct ssl_primary_config* data,
|
||||||
struct ssl_config_data* needle)
|
struct ssl_primary_config* needle)
|
||||||
{
|
{
|
||||||
if((data->version == needle->version) &&
|
if((data->version == needle->version) &&
|
||||||
(data->verifypeer == needle->verifypeer) &&
|
(data->verifypeer == needle->verifypeer) &&
|
||||||
(data->verifyhost == needle->verifyhost) &&
|
(data->verifyhost == needle->verifyhost) &&
|
||||||
safe_strequal(data->CApath, needle->CApath) &&
|
Curl_safe_strequal(data->CApath, needle->CApath) &&
|
||||||
safe_strequal(data->CAfile, needle->CAfile) &&
|
Curl_safe_strequal(data->CAfile, needle->CAfile) &&
|
||||||
safe_strequal(data->random_file, needle->random_file) &&
|
Curl_safe_strequal(data->random_file, needle->random_file) &&
|
||||||
safe_strequal(data->egdsocket, needle->egdsocket) &&
|
Curl_safe_strequal(data->egdsocket, needle->egdsocket) &&
|
||||||
safe_strequal(data->cipher_list, needle->cipher_list))
|
Curl_safe_strequal(data->cipher_list, needle->cipher_list))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
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
|
bool
|
||||||
Curl_clone_ssl_config(struct ssl_config_data *source,
|
Curl_clone_ssl_config(struct ssl_config_data *source,
|
||||||
struct ssl_config_data *dest)
|
struct ssl_config_data *dest)
|
||||||
{
|
{
|
||||||
dest->sessionid = source->sessionid;
|
Curl_clone_primary_ssl_config(&source->primary, &dest->primary);
|
||||||
dest->verifyhost = source->verifyhost;
|
dest->enable_beast = source->enable_beast;
|
||||||
dest->verifypeer = source->verifypeer;
|
dest->certverifyresult = source->certverifyresult;
|
||||||
dest->version = source->version;
|
dest->fsslctx = source->fsslctx;
|
||||||
|
dest->fsslctxp = source->fsslctxp;
|
||||||
|
dest->certinfo = source->certinfo;
|
||||||
|
|
||||||
if(source->CAfile) {
|
CLONE_STRING(CRLfile);
|
||||||
dest->CAfile = strdup(source->CAfile);
|
CLONE_STRING(issuercert);
|
||||||
if(!dest->CAfile)
|
CLONE_STRING(cert);
|
||||||
return FALSE;
|
CLONE_STRING(cert_type);
|
||||||
}
|
CLONE_STRING(key);
|
||||||
else
|
CLONE_STRING(key_type);
|
||||||
dest->CAfile = NULL;
|
CLONE_STRING(key_passwd);
|
||||||
|
|
||||||
if(source->CApath) {
|
#ifdef USE_TLS_SRP
|
||||||
dest->CApath = strdup(source->CApath);
|
CLONE_STRING(username);
|
||||||
if(!dest->CApath)
|
CLONE_STRING(password);
|
||||||
return FALSE;
|
dest->authtype = source->authtype;
|
||||||
}
|
#endif
|
||||||
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;
|
|
||||||
|
|
||||||
return TRUE;
|
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->CAfile);
|
||||||
Curl_safefree(sslc->CApath);
|
Curl_safefree(sslc->CApath);
|
||||||
@@ -244,6 +243,23 @@ int Curl_ssl_backend(void)
|
|||||||
return (int)CURL_SSL_BACKEND;
|
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
|
#ifdef USE_SSL
|
||||||
|
|
||||||
/* "global" init done? */
|
/* "global" init done? */
|
||||||
@@ -279,19 +295,41 @@ void Curl_ssl_cleanup(void)
|
|||||||
static bool ssl_prefs_check(struct SessionHandle *data)
|
static bool ssl_prefs_check(struct SessionHandle *data)
|
||||||
{
|
{
|
||||||
/* check for CURLOPT_SSLVERSION invalid parameter value */
|
/* check for CURLOPT_SSLVERSION invalid parameter value */
|
||||||
if((data->set.ssl.version < 0)
|
if((data->set.ssl.primary.version < 0)
|
||||||
|| (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
|
|| (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
|
||||||
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
|
failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
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
|
CURLcode
|
||||||
Curl_ssl_connect(struct connectdata *conn, int sockindex)
|
Curl_ssl_connect(struct connectdata *conn, int sockindex)
|
||||||
{
|
{
|
||||||
CURLcode result;
|
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))
|
if(!ssl_prefs_check(conn->data))
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
|
||||||
@@ -312,6 +350,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
|
|||||||
bool *done)
|
bool *done)
|
||||||
{
|
{
|
||||||
CURLcode result;
|
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))
|
if(!ssl_prefs_check(conn->data))
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
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,
|
bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||||
void **ssl_sessionid,
|
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 curl_ssl_session *check;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
@@ -343,9 +387,16 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
|
|||||||
long *general_age;
|
long *general_age;
|
||||||
bool no_match = TRUE;
|
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;
|
*ssl_sessionid = NULL;
|
||||||
|
|
||||||
if(!conn->ssl_config.sessionid)
|
if(!data->set.general_ssl.sessionid)
|
||||||
/* session ID re-use is disabled */
|
/* session ID re-use is disabled */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@@ -357,14 +408,14 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
|
|||||||
else
|
else
|
||||||
general_age = &data->state.sessionage;
|
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];
|
check = &data->state.session[i];
|
||||||
if(!check->sessionid)
|
if(!check->sessionid)
|
||||||
/* not session ID means blank entry */
|
/* not session ID means blank entry */
|
||||||
continue;
|
continue;
|
||||||
if(Curl_raw_equal(conn->host.name, check->name) &&
|
if(Curl_raw_equal(name, check->name) &&
|
||||||
(conn->remote_port == check->remote_port) &&
|
(port == check->remote_port) &&
|
||||||
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
|
Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
|
||||||
/* yes, we have a session ID! */
|
/* yes, we have a session ID! */
|
||||||
(*general_age)++; /* increase general age */
|
(*general_age)++; /* increase general age */
|
||||||
check->age = *general_age; /* set this as used in this 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->sessionid = NULL;
|
||||||
session->age = 0; /* fresh */
|
session->age = 0; /* fresh */
|
||||||
|
|
||||||
Curl_free_ssl_config(&session->ssl_config);
|
Curl_free_primary_ssl_config(&session->ssl_config);
|
||||||
|
|
||||||
Curl_safefree(session->name);
|
Curl_safefree(session->name);
|
||||||
}
|
}
|
||||||
@@ -414,7 +465,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
|
|||||||
if(SSLSESSION_SHARED(data))
|
if(SSLSESSION_SHARED(data))
|
||||||
Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
|
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];
|
struct curl_ssl_session *check = &data->state.session[i];
|
||||||
|
|
||||||
if(check->sessionid == ssl_sessionid) {
|
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,
|
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||||
void *ssl_sessionid,
|
void *ssl_sessionid,
|
||||||
size_t idsize)
|
size_t idsize,
|
||||||
|
int sockindex)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
struct SessionHandle *data=conn->data; /* the mother of all structs */
|
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
|
IT. We still store it here in case the re-using is again enabled for an
|
||||||
upcoming transfer */
|
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)
|
if(!clone_host)
|
||||||
return CURLE_OUT_OF_MEMORY; /* bail out */
|
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 */
|
/* 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++) {
|
data->state.session[i].sessionid; i++) {
|
||||||
if(data->state.session[i].age < oldest_age) {
|
if(data->state.session[i].age < oldest_age) {
|
||||||
oldest_age = data->state.session[i].age;
|
oldest_age = data->state.session[i].age;
|
||||||
store = &data->state.session[i];
|
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! */
|
/* cache is full, we must "kill" the oldest entry! */
|
||||||
Curl_ssl_kill_session(store);
|
Curl_ssl_kill_session(store);
|
||||||
else
|
else
|
||||||
@@ -485,14 +542,15 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
|||||||
/* free it if there's one already present */
|
/* free it if there's one already present */
|
||||||
free(store->name);
|
free(store->name);
|
||||||
store->name = clone_host; /* clone host 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 */
|
/* Unlock */
|
||||||
if(SSLSESSION_SHARED(data))
|
if(SSLSESSION_SHARED(data))
|
||||||
Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
|
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 */
|
store->sessionid = NULL; /* let caller free sessionid */
|
||||||
free(clone_host);
|
free(clone_host);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
@@ -507,7 +565,7 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
|||||||
size_t i;
|
size_t i;
|
||||||
/* kill the session ID cache if not shared */
|
/* kill the session ID cache if not shared */
|
||||||
if(data->state.session && !SSLSESSION_SHARED(data)) {
|
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 */
|
/* the single-killer function handles empty table slots */
|
||||||
Curl_ssl_kill_session(&data->state.session[i]);
|
Curl_ssl_kill_session(&data->state.session[i]);
|
||||||
|
|
||||||
@@ -518,6 +576,43 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
|||||||
curlssl_close_all(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)
|
void Curl_ssl_close(struct connectdata *conn, int sockindex)
|
||||||
{
|
{
|
||||||
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
|
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
|
||||||
@@ -575,7 +670,7 @@ CURLcode Curl_ssl_initsessions(struct SessionHandle *data, size_t amount)
|
|||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
/* store the info in the SSL section */
|
/* 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.session = session;
|
||||||
data->state.sessionage = 1; /* this is brand new */
|
data->state.sessionage = 1; /* this is brand new */
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
@@ -50,11 +50,29 @@
|
|||||||
#define ALPN_HTTP_1_1_LENGTH 8
|
#define ALPN_HTTP_1_1_LENGTH 8
|
||||||
#define ALPN_HTTP_1_1 "http/1.1"
|
#define ALPN_HTTP_1_1 "http/1.1"
|
||||||
|
|
||||||
bool Curl_ssl_config_matches(struct ssl_config_data* data,
|
/* set of helper macros for the backends to access the correct fields. For the
|
||||||
struct ssl_config_data* needle);
|
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,
|
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||||
struct ssl_config_data* dest);
|
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_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 *);
|
unsigned int Curl_rand(struct SessionHandle *);
|
||||||
|
|
||||||
@@ -99,11 +117,13 @@ CURLcode Curl_ssl_push_certinfo(struct SessionHandle * data, int certnum,
|
|||||||
/* extract a session ID */
|
/* extract a session ID */
|
||||||
bool Curl_ssl_getsessionid(struct connectdata *conn,
|
bool Curl_ssl_getsessionid(struct connectdata *conn,
|
||||||
void **ssl_sessionid,
|
void **ssl_sessionid,
|
||||||
size_t *idsize) /* set 0 if unknown */;
|
size_t *idsize, /* set 0 if unknown */
|
||||||
|
int sockindex);
|
||||||
/* add a new session ID */
|
/* add a new session ID */
|
||||||
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
|
||||||
void *ssl_sessionid,
|
void *ssl_sessionid,
|
||||||
size_t idsize);
|
size_t idsize,
|
||||||
|
int sockindex);
|
||||||
/* Kill a single session ID entry in the cache */
|
/* Kill a single session ID entry in the cache */
|
||||||
void Curl_ssl_kill_session(struct curl_ssl_session *session);
|
void Curl_ssl_kill_session(struct curl_ssl_session *session);
|
||||||
/* delete a session from the cache */
|
/* delete a session from the cache */
|
||||||
|
@@ -1063,6 +1063,11 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
int matched = -1;
|
int matched = -1;
|
||||||
size_t addrlen = (size_t) -1;
|
size_t addrlen = (size_t) -1;
|
||||||
ssize_t len;
|
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
|
#ifdef ENABLE_IPV6
|
||||||
struct in6_addr addr;
|
struct in6_addr addr;
|
||||||
#else
|
#else
|
||||||
@@ -1072,7 +1077,7 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
/* Verify that connection server matches info in X509 certificate at
|
/* Verify that connection server matches info in X509 certificate at
|
||||||
`beg'..`end'. */
|
`beg'..`end'. */
|
||||||
|
|
||||||
if(!data->set.ssl.verifyhost)
|
if(!SSL_CONN_CONFIG(verifyhost))
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
if(!beg)
|
if(!beg)
|
||||||
@@ -1081,11 +1086,11 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
|
|
||||||
/* Get the server IP address. */
|
/* Get the server IP address. */
|
||||||
#ifdef ENABLE_IPV6
|
#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);
|
addrlen = sizeof(struct in6_addr);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
|
if(Curl_inet_pton(AF_INET, hostname, &addr))
|
||||||
addrlen = sizeof(struct in_addr);
|
addrlen = sizeof(struct in_addr);
|
||||||
|
|
||||||
/* Process extensions. */
|
/* Process extensions. */
|
||||||
@@ -1110,7 +1115,7 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
name.beg, name.end);
|
name.beg, name.end);
|
||||||
if(len > 0)
|
if(len > 0)
|
||||||
if(strlen(dnsname) == (size_t) len)
|
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);
|
free(dnsname);
|
||||||
if(!i)
|
if(!i)
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
@@ -1129,12 +1134,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
switch (matched) {
|
switch (matched) {
|
||||||
case 1:
|
case 1:
|
||||||
/* an alternative name matched the server hostname */
|
/* 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;
|
return CURLE_OK;
|
||||||
case 0:
|
case 0:
|
||||||
/* an alternative name field existed, but didn't match and then
|
/* an alternative name field existed, but didn't match and then
|
||||||
we MUST fail */
|
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;
|
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 ? */
|
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
|
||||||
failf(data, "SSL: illegal cert name field");
|
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);
|
infof(data, "\t common name: %s (matched)\n", dnsname);
|
||||||
free(dnsname);
|
free(dnsname);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
failf(data, "SSL: certificate subject name '%s' does not match "
|
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);
|
free(dnsname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -94,7 +94,19 @@ options:
|
|||||||
CURLOPT_PROXYPASSWORD
|
CURLOPT_PROXYPASSWORD
|
||||||
CURLOPT_PROXYUSERNAME
|
CURLOPT_PROXYUSERNAME
|
||||||
CURLOPT_PROXYUSERPWD
|
CURLOPT_PROXYUSERPWD
|
||||||
|
CURLOPT_PROXY_CAINFO
|
||||||
|
CURLOPT_PROXY_CAPATH
|
||||||
|
CURLOPT_PROXY_CRLFILE
|
||||||
|
CURLOPT_PROXY_KEYPASSWD
|
||||||
CURLOPT_PROXY_SERVICE_NAME
|
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_RANDOM_FILE
|
||||||
CURLOPT_RANGE
|
CURLOPT_RANGE
|
||||||
CURLOPT_REFERER
|
CURLOPT_REFERER
|
||||||
@@ -103,6 +115,7 @@ options:
|
|||||||
CURLOPT_RTSP_TRANSPORT
|
CURLOPT_RTSP_TRANSPORT
|
||||||
CURLOPT_SERVICE_NAME
|
CURLOPT_SERVICE_NAME
|
||||||
CURLOPT_SOCKS5_GSSAPI_SERVICE
|
CURLOPT_SOCKS5_GSSAPI_SERVICE
|
||||||
|
CURLOPT_SOCKS_PROXY
|
||||||
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
|
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
|
||||||
CURLOPT_SSH_KNOWNHOSTS
|
CURLOPT_SSH_KNOWNHOSTS
|
||||||
CURLOPT_SSH_PRIVATE_KEYFILE
|
CURLOPT_SSH_PRIVATE_KEYFILE
|
||||||
|
@@ -1164,7 +1164,19 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
|||||||
case CURLOPT_PROXYPASSWORD:
|
case CURLOPT_PROXYPASSWORD:
|
||||||
case CURLOPT_PROXYUSERNAME:
|
case CURLOPT_PROXYUSERNAME:
|
||||||
case CURLOPT_PROXYUSERPWD:
|
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_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_RANDOM_FILE:
|
||||||
case CURLOPT_RANGE:
|
case CURLOPT_RANGE:
|
||||||
case CURLOPT_REFERER:
|
case CURLOPT_REFERER:
|
||||||
@@ -1173,6 +1185,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
|||||||
case CURLOPT_RTSP_TRANSPORT:
|
case CURLOPT_RTSP_TRANSPORT:
|
||||||
case CURLOPT_SERVICE_NAME:
|
case CURLOPT_SERVICE_NAME:
|
||||||
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
|
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
|
||||||
|
case CURLOPT_SOCKS_PROXY:
|
||||||
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
|
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
|
||||||
case CURLOPT_SSH_KNOWNHOSTS:
|
case CURLOPT_SSH_KNOWNHOSTS:
|
||||||
case CURLOPT_SSH_PRIVATE_KEYFILE:
|
case CURLOPT_SSH_PRIVATE_KEYFILE:
|
||||||
|
@@ -230,6 +230,8 @@
|
|||||||
d c 3
|
d c 3
|
||||||
d CURL_HTTP_VERSION_2...
|
d CURL_HTTP_VERSION_2...
|
||||||
d c 3
|
d c 3
|
||||||
|
d CURL_HTTP_VERSION_2TLS...
|
||||||
|
d c 4
|
||||||
*
|
*
|
||||||
d CURL_NETRC_IGNORED...
|
d CURL_NETRC_IGNORED...
|
||||||
d c 0
|
d c 0
|
||||||
@@ -645,6 +647,8 @@
|
|||||||
d c 0
|
d c 0
|
||||||
d CURLPROXY_HTTP_1_0...
|
d CURLPROXY_HTTP_1_0...
|
||||||
d c 1
|
d c 1
|
||||||
|
d CURLPROXY_HTTPS...
|
||||||
|
d c 2
|
||||||
d CURLPROXY_SOCKS4...
|
d CURLPROXY_SOCKS4...
|
||||||
d c 4
|
d c 4
|
||||||
d CURLPROXY_SOCKS5...
|
d CURLPROXY_SOCKS5...
|
||||||
@@ -1238,6 +1242,42 @@
|
|||||||
d c 10240
|
d c 10240
|
||||||
d CURLOPT_STREAM_DEPENDS_E...
|
d CURLOPT_STREAM_DEPENDS_E...
|
||||||
d c 10241
|
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)
|
/if not defined(CURL_NO_OLDIES)
|
||||||
d CURLOPT_FILE c 10001
|
d CURLOPT_FILE c 10001
|
||||||
@@ -1420,6 +1460,8 @@
|
|||||||
d c X'0040002B'
|
d c X'0040002B'
|
||||||
d CURLINFO_ACTIVESOCKET... CURLINFO_SOCKET + 44
|
d CURLINFO_ACTIVESOCKET... CURLINFO_SOCKET + 44
|
||||||
d c X'0050002C'
|
d c X'0050002C'
|
||||||
|
d CURLINFO_PROXY_SSL_VERIFYRESULT... CURLINFO_LONG + 45
|
||||||
|
d c X'0020002D'
|
||||||
*
|
*
|
||||||
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
|
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
|
||||||
d c X'00200002'
|
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_username);
|
||||||
Curl_safefree(config->tls_password);
|
Curl_safefree(config->tls_password);
|
||||||
Curl_safefree(config->tls_authtype);
|
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->proxyuserpwd);
|
||||||
Curl_safefree(config->proxy);
|
Curl_safefree(config->proxy);
|
||||||
|
|
||||||
@@ -98,15 +101,24 @@ static void free_config_fields(struct OperationConfig *config)
|
|||||||
config->url_out = NULL;
|
config->url_out = NULL;
|
||||||
|
|
||||||
Curl_safefree(config->cipher_list);
|
Curl_safefree(config->cipher_list);
|
||||||
|
Curl_safefree(config->proxy_cipher_list);
|
||||||
Curl_safefree(config->cert);
|
Curl_safefree(config->cert);
|
||||||
|
Curl_safefree(config->proxy_cert);
|
||||||
Curl_safefree(config->cert_type);
|
Curl_safefree(config->cert_type);
|
||||||
|
Curl_safefree(config->proxy_cert_type);
|
||||||
Curl_safefree(config->cacert);
|
Curl_safefree(config->cacert);
|
||||||
|
Curl_safefree(config->proxy_cacert);
|
||||||
Curl_safefree(config->capath);
|
Curl_safefree(config->capath);
|
||||||
|
Curl_safefree(config->proxy_capath);
|
||||||
Curl_safefree(config->crlfile);
|
Curl_safefree(config->crlfile);
|
||||||
Curl_safefree(config->pinnedpubkey);
|
Curl_safefree(config->pinnedpubkey);
|
||||||
|
Curl_safefree(config->proxy_crlfile);
|
||||||
Curl_safefree(config->key);
|
Curl_safefree(config->key);
|
||||||
|
Curl_safefree(config->proxy_key);
|
||||||
Curl_safefree(config->key_type);
|
Curl_safefree(config->key_type);
|
||||||
|
Curl_safefree(config->proxy_key_type);
|
||||||
Curl_safefree(config->key_passwd);
|
Curl_safefree(config->key_passwd);
|
||||||
|
Curl_safefree(config->proxy_key_passwd);
|
||||||
Curl_safefree(config->pubkey);
|
Curl_safefree(config->pubkey);
|
||||||
Curl_safefree(config->hostpubmd5);
|
Curl_safefree(config->hostpubmd5);
|
||||||
Curl_safefree(config->engine);
|
Curl_safefree(config->engine);
|
||||||
|
@@ -78,6 +78,9 @@ struct OperationConfig {
|
|||||||
char *tls_username;
|
char *tls_username;
|
||||||
char *tls_password;
|
char *tls_password;
|
||||||
char *tls_authtype;
|
char *tls_authtype;
|
||||||
|
char *proxy_tls_username;
|
||||||
|
char *proxy_tls_password;
|
||||||
|
char *proxy_tls_authtype;
|
||||||
char *proxyuserpwd;
|
char *proxyuserpwd;
|
||||||
char *proxy;
|
char *proxy;
|
||||||
int proxyver; /* set to CURLPROXY_HTTP* define */
|
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_get; /* point to the node to fill in URL */
|
||||||
struct getout *url_out; /* point to the node to fill in outfile */
|
struct getout *url_out; /* point to the node to fill in outfile */
|
||||||
char *cipher_list;
|
char *cipher_list;
|
||||||
|
char *proxy_cipher_list;
|
||||||
char *cert;
|
char *cert;
|
||||||
|
char *proxy_cert;
|
||||||
char *cert_type;
|
char *cert_type;
|
||||||
|
char *proxy_cert_type;
|
||||||
char *cacert;
|
char *cacert;
|
||||||
|
char *proxy_cacert;
|
||||||
char *capath;
|
char *capath;
|
||||||
|
char *proxy_capath;
|
||||||
char *crlfile;
|
char *crlfile;
|
||||||
|
char *proxy_crlfile;
|
||||||
char *pinnedpubkey;
|
char *pinnedpubkey;
|
||||||
char *key;
|
char *key;
|
||||||
|
char *proxy_key;
|
||||||
char *key_type;
|
char *key_type;
|
||||||
|
char *proxy_key_type;
|
||||||
char *key_passwd;
|
char *key_passwd;
|
||||||
|
char *proxy_key_passwd;
|
||||||
char *pubkey;
|
char *pubkey;
|
||||||
char *hostpubmd5;
|
char *hostpubmd5;
|
||||||
char *engine;
|
char *engine;
|
||||||
@@ -127,6 +139,8 @@ struct OperationConfig {
|
|||||||
bool globoff;
|
bool globoff;
|
||||||
bool use_httpget;
|
bool use_httpget;
|
||||||
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
|
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 verifystatus;
|
||||||
bool create_dirs;
|
bool create_dirs;
|
||||||
bool ftp_create_dirs;
|
bool ftp_create_dirs;
|
||||||
@@ -142,6 +156,7 @@ struct OperationConfig {
|
|||||||
struct curl_slist *postquote;
|
struct curl_slist *postquote;
|
||||||
struct curl_slist *prequote;
|
struct curl_slist *prequote;
|
||||||
long ssl_version;
|
long ssl_version;
|
||||||
|
long proxy_ssl_version;
|
||||||
long ip_version;
|
long ip_version;
|
||||||
curl_TimeCond timecond;
|
curl_TimeCond timecond;
|
||||||
time_t condtime;
|
time_t condtime;
|
||||||
@@ -200,7 +215,10 @@ struct OperationConfig {
|
|||||||
bool xattr; /* store metadata in extended attributes */
|
bool xattr; /* store metadata in extended attributes */
|
||||||
long gssapi_delegation;
|
long gssapi_delegation;
|
||||||
bool ssl_allow_beast; /* allow this SSL vulnerability */
|
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 ssl_no_revoke; /* disable SSL certificate revocation checks */
|
||||||
|
/*bool proxy_ssl_no_revoke; */
|
||||||
|
|
||||||
bool use_metalink; /* process given URLs as metalink XML file */
|
bool use_metalink; /* process given URLs as metalink XML file */
|
||||||
metalinkfile *metalinkfile_list; /* point to the first node */
|
metalinkfile *metalinkfile_list; /* point to the first node */
|
||||||
|
@@ -222,7 +222,25 @@ static const struct LongShort aliases[]= {
|
|||||||
{"Ep", "pinnedpubkey", TRUE},
|
{"Ep", "pinnedpubkey", TRUE},
|
||||||
{"Eq", "cert-status", FALSE},
|
{"Eq", "cert-status", FALSE},
|
||||||
{"Er", "false-start", 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", "fail", FALSE},
|
||||||
{"F", "form", TRUE},
|
{"F", "form", TRUE},
|
||||||
{"Fs", "form-string", TRUE},
|
{"Fs", "form-string", TRUE},
|
||||||
@@ -379,6 +397,20 @@ done:
|
|||||||
*certname_place = '\0';
|
*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 */
|
ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||||
char *nextarg, /* NULL if unset */
|
char *nextarg, /* NULL if unset */
|
||||||
bool *usedarg, /* set to TRUE if the arg
|
bool *usedarg, /* set to TRUE if the arg
|
||||||
@@ -1309,6 +1341,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
switch(subletter) {
|
switch(subletter) {
|
||||||
|
case '\0': /* certificate file */
|
||||||
|
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
|
||||||
|
break;
|
||||||
case 'a': /* CA info PEM file */
|
case 'a': /* CA info PEM file */
|
||||||
/* CA info PEM file */
|
/* CA info PEM file */
|
||||||
GetStr(&config->cacert, nextarg);
|
GetStr(&config->cacert, nextarg);
|
||||||
@@ -1390,23 +1425,90 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
config->falsestart = TRUE;
|
config->falsestart = TRUE;
|
||||||
break;
|
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)
|
if(curlinfo->features & CURL_VERSION_SSL)
|
||||||
config->ssl_no_revoke = TRUE;
|
config->ssl_no_revoke = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* certificate file */
|
case 'x': /* certificate file for proxy */
|
||||||
{
|
GetFileAndPassword(nextarg, &config->proxy_cert,
|
||||||
char *certname, *passphrase;
|
&config->proxy_key_passwd);
|
||||||
parse_cert_parameter(nextarg, &certname, &passphrase);
|
break;
|
||||||
Curl_safefree(config->cert);
|
case 'y': /* cert file type for proxy */
|
||||||
config->cert = certname;
|
GetStr(&config->proxy_cert_type, nextarg);
|
||||||
if(passphrase) {
|
break;
|
||||||
Curl_safefree(config->key_passwd);
|
case 'z': /* private key file for proxy */
|
||||||
config->key_passwd = passphrase;
|
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);
|
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;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
|
@@ -171,9 +171,35 @@ static const char *const helptext[] = {
|
|||||||
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
|
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
|
||||||
" --proxy-basic Use Basic authentication on the proxy (H)",
|
" --proxy-basic Use Basic authentication on the proxy (H)",
|
||||||
" --proxy-digest Use Digest 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 "
|
" --proxy-negotiate "
|
||||||
"Use HTTP Negotiate (SPNEGO) authentication on the proxy (H)",
|
"Use HTTP Negotiate (SPNEGO) authentication on the proxy (H)",
|
||||||
" --proxy-ntlm Use NTLM 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",
|
" --proxy-service-name NAME SPNEGO proxy service name",
|
||||||
" --service-name NAME SPNEGO service name",
|
" --service-name NAME SPNEGO service name",
|
||||||
" -U, --proxy-user USER[:PASSWORD] Proxy user and password",
|
" -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 */
|
/* new in libcurl 7.10 */
|
||||||
if(config->socksproxy) {
|
if(config->socksproxy) {
|
||||||
my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
|
my_setopt_str(curl, CURLOPT_SOCKS_PROXY, config->socksproxy);
|
||||||
my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
|
my_setopt_enum(curl, CURLOPT_SOCKS_PROXYTYPE,
|
||||||
|
(long)config->socksver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new in libcurl 7.10.6 */
|
/* 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(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
|
||||||
|
|
||||||
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
|
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)) {
|
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
|
||||||
|
|
||||||
@@ -1013,19 +1015,36 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
|||||||
|
|
||||||
if(config->cacert)
|
if(config->cacert)
|
||||||
my_setopt_str(curl, CURLOPT_CAINFO, 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)
|
if(config->capath)
|
||||||
my_setopt_str(curl, CURLOPT_CAPATH, 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)
|
if(config->crlfile)
|
||||||
my_setopt_str(curl, CURLOPT_CRLFILE, 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)
|
if(config->pinnedpubkey)
|
||||||
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
|
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
|
||||||
|
|
||||||
if(curlinfo->features & CURL_VERSION_SSL) {
|
if(curlinfo->features & CURL_VERSION_SSL) {
|
||||||
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
|
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_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_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_SSLKEYTYPE, config->key_type);
|
||||||
|
my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
|
||||||
|
config->proxy_key_type);
|
||||||
|
|
||||||
if(config->insecure_ok) {
|
if(config->insecure_ok) {
|
||||||
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
@@ -1036,6 +1055,13 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
|||||||
/* libcurl default is strict verifyhost -> 2L */
|
/* libcurl default is strict verifyhost -> 2L */
|
||||||
/* my_setopt(curl, CURLOPT_SSL_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)
|
if(config->verifystatus)
|
||||||
my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
|
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(curl, CURLOPT_SSL_FALSESTART, 1L);
|
||||||
|
|
||||||
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
|
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)
|
if(config->path_as_is)
|
||||||
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
|
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
|
||||||
@@ -1145,6 +1173,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
|||||||
if(config->cipher_list)
|
if(config->cipher_list)
|
||||||
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, 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: */
|
/* new in libcurl 7.9.2: */
|
||||||
if(config->disable_epsv)
|
if(config->disable_epsv)
|
||||||
/* disable it */
|
/* disable it */
|
||||||
@@ -1318,6 +1350,15 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
|||||||
if(config->tls_authtype)
|
if(config->tls_authtype)
|
||||||
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
|
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
|
||||||
config->tls_authtype);
|
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 */
|
/* new in 7.22.0 */
|
||||||
@@ -1333,6 +1374,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
|
|||||||
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
|
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)
|
if(config->mail_auth)
|
||||||
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
||||||
|
|
||||||
|
@@ -45,6 +45,15 @@
|
|||||||
const NameValue setopt_nv_CURLPROXY[] = {
|
const NameValue setopt_nv_CURLPROXY[] = {
|
||||||
NV(CURLPROXY_HTTP),
|
NV(CURLPROXY_HTTP),
|
||||||
NV(CURLPROXY_HTTP_1_0),
|
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_SOCKS4),
|
||||||
NV(CURLPROXY_SOCKS5),
|
NV(CURLPROXY_SOCKS5),
|
||||||
NV(CURLPROXY_SOCKS4A),
|
NV(CURLPROXY_SOCKS4A),
|
||||||
@@ -155,6 +164,8 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
|
|||||||
NV1(CURLOPT_SSL_VERIFYHOST, 1),
|
NV1(CURLOPT_SSL_VERIFYHOST, 1),
|
||||||
NV1(CURLOPT_SSL_ENABLE_NPN, 1),
|
NV1(CURLOPT_SSL_ENABLE_NPN, 1),
|
||||||
NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
|
NV1(CURLOPT_SSL_ENABLE_ALPN, 1),
|
||||||
|
NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1),
|
||||||
|
NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1),
|
||||||
NVEND
|
NVEND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -47,6 +47,7 @@ typedef struct {
|
|||||||
} NameValueUnsigned;
|
} NameValueUnsigned;
|
||||||
|
|
||||||
extern const NameValue setopt_nv_CURLPROXY[];
|
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_HTTP_VERSION[];
|
||||||
extern const NameValue setopt_nv_CURL_SSLVERSION[];
|
extern const NameValue setopt_nv_CURL_SSLVERSION[];
|
||||||
extern const NameValue setopt_nv_CURL_TIMECOND[];
|
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_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
|
||||||
#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
|
#define setopt_nv_CURLOPT_HTTPAUTH setopt_nv_CURLAUTH
|
||||||
#define setopt_nv_CURLOPT_SSLVERSION setopt_nv_CURL_SSLVERSION
|
#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_TIMECONDITION setopt_nv_CURL_TIMECOND
|
||||||
#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
|
#define setopt_nv_CURLOPT_FTP_SSL_CCC setopt_nv_CURLFTPSSL_CCC
|
||||||
#define setopt_nv_CURLOPT_USE_SSL setopt_nv_CURLUSESSL
|
#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_PROTOCOLS setopt_nv_CURLPROTO
|
||||||
#define setopt_nv_CURLOPT_REDIR_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_PROXYTYPE setopt_nv_CURLPROXY
|
||||||
|
#define setopt_nv_CURLOPT_SOCKS_PROXYTYPE setopt_nv_CURL_SOCKS_PROXY
|
||||||
#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
|
#define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH
|
||||||
|
|
||||||
/* Intercept setopt calls for --libcurl */
|
/* Intercept setopt calls for --libcurl */
|
||||||
|
@@ -52,6 +52,7 @@ typedef enum {
|
|||||||
VAR_FTP_ENTRY_PATH,
|
VAR_FTP_ENTRY_PATH,
|
||||||
VAR_REDIRECT_URL,
|
VAR_REDIRECT_URL,
|
||||||
VAR_SSL_VERIFY_RESULT,
|
VAR_SSL_VERIFY_RESULT,
|
||||||
|
VAR_PROXY_SSL_VERIFY_RESULT,
|
||||||
VAR_EFFECTIVE_FILENAME,
|
VAR_EFFECTIVE_FILENAME,
|
||||||
VAR_PRIMARY_IP,
|
VAR_PRIMARY_IP,
|
||||||
VAR_PRIMARY_PORT,
|
VAR_PRIMARY_PORT,
|
||||||
@@ -90,6 +91,7 @@ static const struct variable replacements[]={
|
|||||||
{"ftp_entry_path", VAR_FTP_ENTRY_PATH},
|
{"ftp_entry_path", VAR_FTP_ENTRY_PATH},
|
||||||
{"redirect_url", VAR_REDIRECT_URL},
|
{"redirect_url", VAR_REDIRECT_URL},
|
||||||
{"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
|
{"ssl_verify_result", VAR_SSL_VERIFY_RESULT},
|
||||||
|
{"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT},
|
||||||
{"filename_effective", VAR_EFFECTIVE_FILENAME},
|
{"filename_effective", VAR_EFFECTIVE_FILENAME},
|
||||||
{"remote_ip", VAR_PRIMARY_IP},
|
{"remote_ip", VAR_PRIMARY_IP},
|
||||||
{"remote_port", VAR_PRIMARY_PORT},
|
{"remote_port", VAR_PRIMARY_PORT},
|
||||||
@@ -250,6 +252,12 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
|
|||||||
&longinfo))
|
&longinfo))
|
||||||
fprintf(stream, "%ld", longinfo);
|
fprintf(stream, "%ld", longinfo);
|
||||||
break;
|
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:
|
case VAR_EFFECTIVE_FILENAME:
|
||||||
if(outs->filename)
|
if(outs->filename)
|
||||||
fprintf(stream, "%s", outs->filename);
|
fprintf(stream, "%s", outs->filename);
|
||||||
|
Reference in New Issue
Block a user