gnutls: finished support for HTTPS proxies.
This commit is contained in:

committed by
Daniel Stenberg

parent
043c5f5c33
commit
127a7b0257
@@ -4767,6 +4767,7 @@ static CURLcode parse_proxy(struct SessionHandle *data,
|
|||||||
long port = -1;
|
long port = -1;
|
||||||
char *proxyuser = NULL;
|
char *proxyuser = NULL;
|
||||||
char *proxypasswd = NULL;
|
char *proxypasswd = NULL;
|
||||||
|
bool sockstype;
|
||||||
|
|
||||||
/* We do the proxy host string parsing here. We want the host name and the
|
/* We do the proxy host string parsing here. We want the host name and the
|
||||||
* port name. Accept a protocol:// prefix
|
* port name. Accept a protocol:// prefix
|
||||||
@@ -4791,10 +4792,10 @@ static CURLcode parse_proxy(struct SessionHandle *data,
|
|||||||
else
|
else
|
||||||
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
|
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
|
||||||
|
|
||||||
bool sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
|
sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
|
||||||
proxytype == CURLPROXY_SOCKS5 ||
|
proxytype == CURLPROXY_SOCKS5 ||
|
||||||
proxytype == CURLPROXY_SOCKS4A ||
|
proxytype == CURLPROXY_SOCKS4A ||
|
||||||
proxytype == CURLPROXY_SOCKS4;
|
proxytype == CURLPROXY_SOCKS4;
|
||||||
|
|
||||||
/* Is there a username and password given in this proxy url? */
|
/* Is there a username and password given in this proxy url? */
|
||||||
atsign = strchr(proxyptr, '@');
|
atsign = strchr(proxyptr, '@');
|
||||||
|
114
lib/vtls/gtls.c
114
lib/vtls/gtls.c
@@ -170,6 +170,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
|
||||||
@@ -372,6 +382,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
|
||||||
@@ -429,8 +442,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);
|
||||||
@@ -442,8 +455,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));
|
||||||
@@ -489,19 +502,19 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#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 */
|
||||||
@@ -541,7 +554,7 @@ 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;
|
||||||
@@ -657,13 +670,13 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(data->set.ssl.cert) {
|
if(SSL_SET_OPTION(cert)) {
|
||||||
if(gnutls_certificate_set_x509_key_file(
|
if(gnutls_certificate_set_x509_key_file(
|
||||||
conn->ssl[sockindex].cred,
|
conn->ssl[sockindex].cred,
|
||||||
data->set.ssl.cert,
|
SSL_SET_OPTION(cert),
|
||||||
data->set.ssl.key ?
|
SSL_SET_OPTION(key) ?
|
||||||
data->set.ssl.key : data->set.ssl.cert,
|
SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
|
||||||
do_file_type(data->set.ssl.cert_type) ) !=
|
do_file_type(SSL_SET_OPTION(cert_type)) ) !=
|
||||||
GNUTLS_E_SUCCESS) {
|
GNUTLS_E_SUCCESS) {
|
||||||
failf(data, "error reading X.509 key or certificate file");
|
failf(data, "error reading X.509 key or certificate file");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
@@ -672,7 +685,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) {
|
||||||
@@ -691,13 +704,24 @@ 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);
|
||||||
@@ -833,8 +857,8 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
SSL_CONN_CONFIG(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
|
||||||
&& !SSL_CONN_CONFIG(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
|
||||||
@@ -888,7 +912,7 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
failf(data, "server certificate verification failed. CAfile: %s "
|
failf(data, "server certificate verification failed. CAfile: %s "
|
||||||
"CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
|
"CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
|
||||||
"none",
|
"none",
|
||||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
|
||||||
return CURLE_SSL_CACERT;
|
return CURLE_SSL_CACERT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1344,6 +1368,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,
|
||||||
@@ -1363,29 +1401,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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1451,8 +1489,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
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
@@ -74,7 +76,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_cert_status_request() Curl_gtls_cert_status_request()
|
#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
|
||||||
|
@@ -308,7 +308,7 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex) {
|
|||||||
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
|
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
|
||||||
if(ssl_connection_complete == conn->ssl[sockindex].state &&
|
if(ssl_connection_complete == conn->ssl[sockindex].state &&
|
||||||
!conn->proxy_ssl[sockindex].use) {
|
!conn->proxy_ssl[sockindex].use) {
|
||||||
#if defined(USE_OPENSSL) || defined(USE_NSS)
|
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_NSS)
|
||||||
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
|
conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
|
||||||
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
|
memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
|
||||||
#else
|
#else
|
||||||
|
Reference in New Issue
Block a user